From aacd97444cedf0fd737e5c7c36e05d44fa45dbe5 Mon Sep 17 00:00:00 2001 From: Thomas Hatcher Date: Wed, 15 Jul 2026 14:11:38 +0000 Subject: [PATCH 1/6] initial commit TYCHON Quantum Command integration package --- packages/tychon_quantum_command/LICENSE.txt | 93 ++ .../_dev/build/docs/README.md | 1104 +++++++++++++ packages/tychon_quantum_command/changelog.yml | 5 + .../tychon_pqc/agent/stream/stream.yml.hbs | 44 + .../elasticsearch/ingest_pipeline/default.yml | 627 +++++++ .../tychon_pqc/fields/base-fields.yml | 44 + .../data_stream/tychon_pqc/fields/ecs.yml | 329 ++++ .../data_stream/tychon_pqc/fields/fields.yml | 1450 +++++++++++++++++ .../data_stream/tychon_pqc/manifest.yml | 46 + .../data_stream/tychon_pqc/sample_event.json | 37 + .../tychon_quantum_command/docs/README.md | 1105 +++++++++++++ .../applications/fields/base-fields.yml | 38 + .../transform/applications/fields/ecs.yml | 42 + .../transform/applications/fields/fields.yml | 55 + .../transform/applications/manifest.yml | 11 + .../transform/applications/transform.yml | 21 + .../transform/archives/fields/base-fields.yml | 10 + .../transform/archives/fields/ecs.yml | 6 + .../transform/archives/fields/fields.yml | 17 + .../transform/archives/manifest.yml | 11 + .../transform/archives/transform.yml | 21 + .../transform/assets/fields/base-fields.yml | 38 + .../transform/assets/fields/ecs.yml | 39 + .../transform/assets/fields/fields.yml | 11 + .../transform/assets/manifest.yml | 11 + .../transform/assets/transform.yml | 21 + .../browser_exts/fields/base-fields.yml | 40 + .../transform/browser_exts/fields/ecs.yml | 28 + .../transform/browser_exts/fields/fields.yml | 16 + .../transform/browser_exts/manifest.yml | 11 + .../transform/browser_exts/transform.yml | 21 + .../certificates/fields/base-fields.yml | 38 + .../transform/certificates/fields/ecs.yml | 89 + .../transform/certificates/fields/fields.yml | 110 ++ .../transform/certificates/manifest.yml | 11 + .../transform/certificates/transform.yml | 21 + .../transform/ciphers/fields/base-fields.yml | 38 + .../transform/ciphers/fields/ecs.yml | 95 ++ .../transform/ciphers/fields/fields.yml | 105 ++ .../transform/ciphers/manifest.yml | 11 + .../transform/ciphers/transform.yml | 21 + .../crypto_libs/fields/base-fields.yml | 38 + .../transform/crypto_libs/fields/ecs.yml | 34 + .../transform/crypto_libs/fields/fields.yml | 31 + .../transform/crypto_libs/manifest.yml | 11 + .../transform/crypto_libs/transform.yml | 21 + .../inst_apps/fields/base-fields.yml | 40 + .../transform/inst_apps/fields/ecs.yml | 32 + .../transform/inst_apps/fields/fields.yml | 8 + .../transform/inst_apps/manifest.yml | 11 + .../transform/inst_apps/transform.yml | 21 + .../inventory/fields/base-fields.yml | 40 + .../transform/inventory/fields/ecs.yml | 81 + .../transform/inventory/fields/fields.yml | 71 + .../transform/inventory/manifest.yml | 11 + .../transform/inventory/transform.yml | 21 + .../ipsec_tnls/fields/base-fields.yml | 38 + .../transform/ipsec_tnls/fields/ecs.yml | 23 + .../transform/ipsec_tnls/fields/fields.yml | 76 + .../transform/ipsec_tnls/manifest.yml | 11 + .../transform/ipsec_tnls/transform.yml | 21 + .../keystores/fields/base-fields.yml | 38 + .../transform/keystores/fields/ecs.yml | 30 + .../transform/keystores/fields/fields.yml | 34 + .../transform/keystores/manifest.yml | 11 + .../transform/keystores/transform.yml | 21 + .../transform/macsec/fields/base-fields.yml | 10 + .../transform/macsec/fields/ecs.yml | 6 + .../transform/macsec/fields/fields.yml | 25 + .../transform/macsec/manifest.yml | 11 + .../transform/macsec/transform.yml | 21 + .../readiness/fields/base-fields.yml | 54 + .../transform/readiness/fields/ecs.yml | 144 ++ .../transform/readiness/fields/fields.yml | 351 ++++ .../transform/readiness/manifest.yml | 11 + .../transform/readiness/transform.yml | 21 + .../vpn_clients/fields/base-fields.yml | 38 + .../transform/vpn_clients/fields/ecs.yml | 32 + .../transform/vpn_clients/fields/fields.yml | 63 + .../transform/vpn_clients/manifest.yml | 11 + .../transform/vpn_clients/transform.yml | 21 + .../TQC_Application_Connections_Topology.png | Bin 0 -> 765085 bytes .../img/TQC_Application_Detail.png | Bin 0 -> 387057 bytes .../img/TQC_Application_Report.png | Bin 0 -> 219094 bytes .../img/TQC_Certificate_Report.png | Bin 0 -> 168169 bytes .../img/TQC_Cost_Analysis.png | Bin 0 -> 132934 bytes .../img/TQC_Inventory.png | Bin 0 -> 180360 bytes .../tychon_quantum_command/img/TychonLogo.svg | 59 + .../img/tychon-color.png | Bin 0 -> 8355 bytes ...-4ea4-8458-7c8a8b58987e-cost-analysis.json | 79 + ...0d80-4a28-9de7-55b2046f7c45-inventory.json | 63 + ...-b0b9-c675dd057e2f-application-report.json | 134 ++ ...-9410-7d8c01ff0d9a-application-detail.json | 113 ++ ...ea1b-application-connections-topology.json | 68 + ...3982-certificate-operations-dashboard.json | 92 ++ .../05179988-8b3d-4f26-9832-d83a1e769b2d.json | 25 + .../1dc9d581-4b38-4108-84e1-59a9fbcfbca5.json | 25 + .../852a2806-9a09-4c17-bcea-b54e7b69f3bc.json | 25 + ...4e80-9fe2-115c951fe43c-dod-omb-report.json | 81 + ...d3e40001-certificate-inventory-detail.json | 46 + ...-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json | 19 + ...-dacb217e-57b4-4296-8545-cbf6b5739344.json | 19 + ...-e9b715ba-5f19-4f99-b837-2c1a24143212.json | 19 + ...-01375d36-099a-405d-a513-b1a782190a1d.json | 24 + ...-1309bf24-a8af-43cb-8aae-cf88da1db46e.json | 35 + ...-1751052b-7016-4e89-b376-fd6a7064885f.json | 23 + ...-2022b217-3551-4a32-b5e9-b77c85a38492.json | 23 + ...-433bc733-a80c-4ca5-90a3-a667926206a1.json | 23 + ...-461557f7-e0d3-45bd-88d2-06962ca8c975.json | 35 + ...-8f02e394-d19d-419f-bd75-8a1984c41984.json | 23 + ...-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json | 35 + ...-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json | 22 + ...-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json | 23 + ...-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json | 22 + ...-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json | 24 + ...-ebdbafa8-2778-4098-b5df-fb2c23665551.json | 23 + ...-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json | 23 + packages/tychon_quantum_command/manifest.yml | 55 + .../tychon_quantum_command/sample_event.json | 37 + .../test_changelog.cpython-314.pyc | Bin 0 -> 2226 bytes .../test_kibana_assets.cpython-314.pyc | Bin 0 -> 13456 bytes .../test_manifest_assets.cpython-314.pyc | Bin 0 -> 3061 bytes .../__pycache__/test_readme.cpython-314.pyc | Bin 0 -> 2816 bytes .../test_stream_configuration.cpython-314.pyc | Bin 0 -> 5802 bytes .../tests/test_changelog.py | 28 + .../tests/test_kibana_assets.py | 534 ++++++ .../tests/test_manifest_assets.py | 40 + .../tests/test_publish_readiness.py | 65 + .../tests/test_readme.py | 65 + .../tests/test_stream_configuration.py | 230 +++ .../tychon_quantum_command/validation.yml | 6 + 131 files changed, 9769 insertions(+) create mode 100644 packages/tychon_quantum_command/LICENSE.txt create mode 100644 packages/tychon_quantum_command/_dev/build/docs/README.md create mode 100644 packages/tychon_quantum_command/changelog.yml create mode 100644 packages/tychon_quantum_command/data_stream/tychon_pqc/agent/stream/stream.yml.hbs create mode 100644 packages/tychon_quantum_command/data_stream/tychon_pqc/elasticsearch/ingest_pipeline/default.yml create mode 100644 packages/tychon_quantum_command/data_stream/tychon_pqc/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/data_stream/tychon_pqc/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/data_stream/tychon_pqc/fields/fields.yml create mode 100644 packages/tychon_quantum_command/data_stream/tychon_pqc/manifest.yml create mode 100644 packages/tychon_quantum_command/data_stream/tychon_pqc/sample_event.json create mode 100644 packages/tychon_quantum_command/docs/README.md create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/applications/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/applications/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/applications/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/applications/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/applications/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/archives/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/archives/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/archives/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/archives/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/archives/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/assets/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/assets/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/assets/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/assets/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/assets/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/browser_exts/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/browser_exts/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/certificates/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/certificates/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ciphers/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ciphers/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inst_apps/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inst_apps/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inventory/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/inventory/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/keystores/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/keystores/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/macsec/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/macsec/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/readiness/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/readiness/transform.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/base-fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/ecs.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/fields.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/manifest.yml create mode 100644 packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/transform.yml create mode 100644 packages/tychon_quantum_command/img/TQC_Application_Connections_Topology.png create mode 100644 packages/tychon_quantum_command/img/TQC_Application_Detail.png create mode 100644 packages/tychon_quantum_command/img/TQC_Application_Report.png create mode 100644 packages/tychon_quantum_command/img/TQC_Certificate_Report.png create mode 100644 packages/tychon_quantum_command/img/TQC_Cost_Analysis.png create mode 100644 packages/tychon_quantum_command/img/TQC_Inventory.png create mode 100644 packages/tychon_quantum_command/img/TychonLogo.svg create mode 100644 packages/tychon_quantum_command/img/tychon-color.png create mode 100644 packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json create mode 100644 packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json create mode 100644 packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json create mode 100644 packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json create mode 100644 packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json create mode 100644 packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json create mode 100644 packages/tychon_quantum_command/kibana/index_pattern/05179988-8b3d-4f26-9832-d83a1e769b2d.json create mode 100644 packages/tychon_quantum_command/kibana/index_pattern/1dc9d581-4b38-4108-84e1-59a9fbcfbca5.json create mode 100644 packages/tychon_quantum_command/kibana/index_pattern/852a2806-9a09-4c17-bcea-b54e7b69f3bc.json create mode 100644 packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json create mode 100644 packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json create mode 100644 packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json create mode 100644 packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json create mode 100644 packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json create mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json create mode 100644 packages/tychon_quantum_command/manifest.yml create mode 100644 packages/tychon_quantum_command/sample_event.json create mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_changelog.cpython-314.pyc create mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_kibana_assets.cpython-314.pyc create mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_manifest_assets.cpython-314.pyc create mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_readme.cpython-314.pyc create mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_stream_configuration.cpython-314.pyc create mode 100644 packages/tychon_quantum_command/tests/test_changelog.py create mode 100644 packages/tychon_quantum_command/tests/test_kibana_assets.py create mode 100644 packages/tychon_quantum_command/tests/test_manifest_assets.py create mode 100644 packages/tychon_quantum_command/tests/test_publish_readiness.py create mode 100644 packages/tychon_quantum_command/tests/test_readme.py create mode 100644 packages/tychon_quantum_command/tests/test_stream_configuration.py create mode 100644 packages/tychon_quantum_command/validation.yml diff --git a/packages/tychon_quantum_command/LICENSE.txt b/packages/tychon_quantum_command/LICENSE.txt new file mode 100644 index 00000000000..809108b857f --- /dev/null +++ b/packages/tychon_quantum_command/LICENSE.txt @@ -0,0 +1,93 @@ +Elastic License 2.0 + +URL: https://www.elastic.co/licensing/elastic-license + +## Acceptance + +By using the software, you agree to all of the terms and conditions below. + +## Copyright License + +The licensor grants you a non-exclusive, royalty-free, worldwide, +non-sublicensable, non-transferable license to use, copy, distribute, make +available, and prepare derivative works of the software, in each case subject to +the limitations and conditions below. + +## Limitations + +You may not provide the software to third parties as a hosted or managed +service, where the service provides users with access to any substantial set of +the features or functionality of the software. + +You may not move, change, disable, or circumvent the license key functionality +in the software, and you may not remove or obscure any functionality in the +software that is protected by the license key. + +You may not alter, remove, or obscure any licensing, copyright, or other notices +of the licensor in the software. Any use of the licensor’s trademarks is subject +to applicable law. + +## Patents + +The licensor grants you a license, under any patent claims the licensor can +license, or becomes able to license, to make, have made, use, sell, offer for +sale, import and have imported the software, in each case subject to the +limitations and conditions in this license. This license does not cover any +patent claims that you cause to be infringed by modifications or additions to +the software. If you or your company make any written claim that the software +infringes or contributes to infringement of any patent, your patent license for +the software granted under these terms ends immediately. If your company makes +such a claim, your patent license ends immediately for work on behalf of your +company. + +## Notices + +You must ensure that anyone who gets a copy of any part of the software from you +also gets a copy of these terms. + +If you modify the software, you must include in any modified copies of the +software prominent notices stating that you have modified the software. + +## No Other Rights + +These terms do not imply any licenses other than those expressly granted in +these terms. + +## Termination + +If you use the software in violation of these terms, such use is not licensed, +and your licenses will automatically terminate. If the licensor provides you +with a notice of your violation, and you cease all violation of this license no +later than 30 days after you receive that notice, your licenses will be +reinstated retroactively. However, if you violate these terms after such +reinstatement, any additional violation of these terms will cause your licenses +to terminate automatically and permanently. + +## No Liability + +*As far as the law allows, the software comes as is, without any warranty or +condition, and the licensor will not be liable to you for any damages arising +out of these terms or the use or nature of the software, under any kind of +legal claim.* + +## Definitions + +The **licensor** is the entity offering these terms, and the **software** is the +software the licensor makes available under these terms, including any portion +of it. + +**you** refers to the individual or entity agreeing to these terms. + +**your company** is any legal entity, sole proprietorship, or other kind of +organization that you work for, plus all organizations that have control over, +are under the control of, or are under common control with that +organization. **control** means ownership of substantially all the assets of an +entity, or the power to direct its management and policies by vote, contract, or +otherwise. Control can be direct or indirect. + +**your licenses** are all the licenses granted to you for the software under +these terms. + +**use** means anything you do with the software requiring one of your licenses. + +**trademark** means trademarks, service marks, and similar rights. diff --git a/packages/tychon_quantum_command/_dev/build/docs/README.md b/packages/tychon_quantum_command/_dev/build/docs/README.md new file mode 100644 index 00000000000..b90f70665f4 --- /dev/null +++ b/packages/tychon_quantum_command/_dev/build/docs/README.md @@ -0,0 +1,1104 @@ +{{ generatedHeader }} + + +# TYCHON Quantum Command Integration for Elastic + +## Overview + +[TYCHON Quantum Command](https://tychon.io/products/tychon/pqc-management-module/) helps organizations inventory cryptographic implementations, assess post-quantum exposure, and prioritize remediation across endpoints, applications, certificates, network services, key stores, and platform readiness. This integration ingests TYCHON Quantum Command output files into Elastic, normalizes the source stream, and publishes entity-focused transform destinations for dashboards, search, and reporting. + +### Compatibility + +* Intended for environments where TYCHON Quantum Command produces NDJSON or JSON output files on Windows, Linux, or macOS systems. +* Requires a valid TYCHON Quantum Command license. +* Requires Elastic Stack / Fleet compatible with package version `2.0.4` and the package manifest constraint `^8.11.0`. + +### How it works + +1. TYCHON Quantum Command writes scan results to local `.ndjson` or `.json` files. +2. Elastic Agent collects those files through the `filestream` input in the `tychon_pqc` data stream. +3. The ingest pipeline stores the raw events in the namespace-specific source data stream `logs-tychon_quantum_command.tychon_pqc-`. +4. Elasticsearch transforms filter the combined source stream by `tychon.index` and publish dataset-specific destination indices such as `tychon-pqc-inventory`, `tychon-pqc-certificates`, and `tychon-pqc-system-readiness`. +5. Kibana dashboards and saved objects query both the raw and transformed views for operational analysis. + +## What data does this integration collect? + +The integration collects file-based TYCHON Quantum Command output in NDJSON or JSON form. The package is designed around one primary ingest stream and multiple analytical transforms. + +### Primary ingest stream + +* Data stream: `tychon_pqc` +* Data stream type: `logs` +* Expected source formats: NDJSON and JSON records written by TYCHON Quantum Command +* Collection method: Elastic Agent `filestream` +* Namespace-safe source data stream pattern used by transforms: `logs-tychon_quantum_command.tychon_pqc-*` +* Index template used by the source data stream: `logs-tychon_quantum_command.tychon_pqc` +* Backing index naming pattern for the source data stream: `.ds-logs-tychon_quantum_command.tychon_pqc--YYYY.MM.DD-000001` + +### Analytical datasets produced by transforms + +The package currently publishes the following destination indices from the shared source stream: + +* `tychon-pqc-applications` +* `tychon-pqc-archives` +* `tychon-pqc-assets` +* `tychon-pqc-certificates` +* `tychon-pqc-ciphers` +* `tychon-pqc-crypto-libraries` +* `tychon-pqc-installed-apps` +* `tychon-pqc-installed-browser-extensions` +* `tychon-pqc-inventory` +* `tychon-pqc-ipsec-tunnels` +* `tychon-pqc-keystores` +* `tychon-pqc-macsec` +* `tychon-pqc-system-readiness` +* `tychon-pqc-vpn-clients` + +### Supported use cases + +* Build a cryptographic inventory across endpoints and applications. +* Identify classical algorithms, deprecated protocols, and post-quantum readiness gaps. +* Review certificate and keystore exposure, including signature and key algorithm posture. +* Track TLS, VPN, IPsec, MACsec, and related network cryptography risk. +* Estimate remediation readiness and cost through the `system-readiness` transform. +* Drive dashboards for inventory, application reporting, certificate operations, and cost analysis. + +## What do I need to use this integration? + +* Elastic Agent enrolled in Fleet. +* Access to the host or file share where TYCHON Quantum Command writes scan output. +* File system permissions that allow Elastic Agent to read the output directory. +* A deployment decision for the Fleet namespace. The package supports any namespace; transforms read from `logs-tychon_quantum_command.tychon_pqc-*`. +* Enough Elasticsearch capacity for the raw source stream plus the transform destination indices. + +## How do I deploy this integration? + +### Agent-based deployment + +Install Elastic Agent on a host that can read the TYCHON Quantum Command output files. For Elastic Agent installation guidance, see the Elastic Agent [installation instructions](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html). + +### Set up steps in TYCHON Quantum Command + +1. Configure TYCHON Quantum Command to export scan results in NDJSON format. JSON-formatted records can also be ingested when they are emitted one record per event. +2. Choose a stable output location that Elastic Agent can read. +3. Ensure scan results are written with file permissions that allow the Elastic Agent service account to read them. +4. If you separate environments by namespace in Fleet, keep the TYCHON output pathing and the Elastic policy aligned with the intended namespace. +5. Preserve enough scan history on disk for Elastic Agent to pick up new files reliably. + +#### Vendor resources + +* [TYCHON Quantum Command product page](https://tychon.io/products/tychon/pqc-management-module/) +* [TYCHON Quantum Command portal](https://acdiscanner.tychon.io/) +* [TYCHON support portal](https://support.tychon.io/) +* [TYCHON contact page](https://tychon.io/products/tychon/pqc-management-module/#ContactUs) + +### Set up steps in Kibana + +1. Open **Integrations** and install **TYCHON Quantum Command**. +2. Add the integration to an Elastic Agent policy. +3. Set the Windows paths, Linux paths, and any additional custom paths that contain TYCHON output files. +4. Choose the target namespace for the integration policy. +5. Save and deploy the policy. +6. Confirm that documents are arriving in `logs-tychon_quantum_command.tychon_pqc-`. +7. Wait for the managed transforms to populate the destination indices. +8. Open the packaged dashboards to validate the transformed views. + +### Validation + +Use the following checks after deployment: + +* Confirm raw ingest by querying `logs-tychon_quantum_command.tychon_pqc-` for recent events. +* Confirm dataset routing by checking the `tychon.index` values present in the source stream. +* Confirm transform output by verifying documents appear in indices such as `tychon-pqc-inventory`, `tychon-pqc-certificates`, and `tychon-pqc-system-readiness`. +* Open the packaged dashboards and verify charts populate without missing data view errors. +* Review a few representative documents to confirm timestamps, observer metadata, and TYCHON-specific fields were parsed as expected. + + +## Troubleshooting + +* No data in the source stream: verify the file path settings, file permissions, and that TYCHON is actually writing new files. +* Data in the source stream but empty dashboards: verify transforms are running and that the relevant `tychon.index` values exist in the raw events. +* Expected namespace has no transformed data: verify documents are landing in the intended namespace and that transforms can read the shared source pattern `logs-tychon_quantum_command.tychon_pqc-*`. +* Parsing issues: inspect `error.message`, malformed JSON records, and any unexpected multiline output in the source files. +* Duplicate or stale transformed records: review the transform `latest.unique_key` behavior and verify the top-level `id` values remain stable across rescans. +* Certificate or readiness documents feel oversized: review large text fields such as PEM content and detailed reports before production retention policies are finalized. + +## Performance and scaling + +This package stores both the raw ingest stream and multiple transformed destination indices. Capacity planning should account for: + +* Raw source event volume from TYCHON scans. +* Transform frequency, sync delay, and destination index growth. +* Retention requirements for both source and transformed data. +* Dashboard workloads that query multiple destination indices. + +For broader scaling guidance, see Elastic's [Ingest Architectures](https://www.elastic.co/docs/manage-data/ingest/ingest-reference-architectures) documentation. + +## Reference + +### Inputs used + +These inputs can be used with this integration: + +
+filestream + +### Setup + +For more details about the Filestream input settings, see the [Filebeat filestream input documentation](https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-filestream). + +### Collecting logs with filestream + +Configure the input with one or more paths that point to TYCHON Quantum Command output files. + +Default package path variables: + +* Windows paths: + * `C:\Program Files\Tychon\*.ndjson` + * `C:\ProgramData\Tychon\*.ndjson` +* Linux paths: + * `/var/log/tychon/*.ndjson` + * `/opt/tychon/*.ndjson` +* Additional custom paths: + * Any extra directories where TYCHON scan exports are written. + +Optional package settings: + +* `preserve_original_event`: copies the original message to `event.original` before ingest processing. +* `tags`: appends custom tags to collected events. + +
+ +### API usage + +This integration does not call a TYCHON vendor API. It is a file-based integration that ingests TYCHON Quantum Command output written to disk. + +### Vendor documentation links + +* [TYCHON Quantum Command product page](https://tychon.io/products/tychon/pqc-management-module/) +* [TYCHON support portal](https://support.tychon.io/) +* [Elastic Agent installation](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html) +* [Elastic filestream input reference](https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-filestream) + +### Data streams + +#### `tychon_pqc` + +The `tychon_pqc` data stream receives TYCHON Quantum Command output files collected through the `filestream` input. Source events are stored in the namespace-specific stream `logs-tychon_quantum_command.tychon_pqc-` and then filtered by transforms using the `tychon.index` discriminator. + +This stream can contain multiple TYCHON record families in one place, including inventory, certificates, ciphers, applications, crypto libraries, readiness, keystores, VPN client findings, IPsec tunnel findings, MACsec findings, installed application data, browser extension data, archives, and other supporting scan artifacts. + +### Data streams using ILM policies + +This package does not define a custom package-level ILM policy in `docs/README.md`. Apply retention and lifecycle controls according to your deployment standards for both the raw source stream and the transform destination indices. +### Transforms used + +#### applications +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-applications + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| host.hostname | | keyword | +| host.id | | keyword | +| id | Tychon unique document identifier for the application record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.domain | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.os.build | | keyword | +| observer.os.family | | keyword | +| observer.os.kernel | | keyword | +| observer.os.name | | keyword | +| observer.os.platform | | keyword | +| observer.os.version | | keyword | +| observer.software_version | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.application.app_root | | keyword | +| tychon.application.connected_to_count | | long | +| tychon.application.crypto_library_count | | long | +| tychon.application.in_memory_cert_count | | long | +| tychon.application.keychain_identity_count | | long | +| tychon.application.keystore_count | | long | +| tychon.application.name | | keyword | +| tychon.application.path | | keyword | +| tychon.application.pid | | long | +| tychon.application.port_count | | long | +| tychon.application.private_key_count | | long | +| tychon.application.service_display_name | | keyword | +| tychon.application.service_name | | keyword | +| tychon.application.source | | keyword | +| tychon.index | | keyword | +| tychon.library.crypt32_pqc_status | | keyword | +| tychon.library.crypt32_version | | keyword | +| tychon.library.openssl_pqc_status | | keyword | +| tychon.library.openssl_version | | keyword | +| tychon.library.uses_crypt32 | | boolean | +| tychon.library.uses_openssl | | boolean | +| tychon.library.uses_windows_cng | | boolean | +| tychon.library.windows_cng_pqc_status | | keyword | +| tychon.library.windows_cng_version | | keyword | +| tychon.type | | keyword | + +#### archives +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-archives + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| archive.encryption.strength | | keyword | +| archive.encryption.type | | keyword | +| archive.format.version | | keyword | +| archive.type | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the archive record. | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### assets +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-assets + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| config.config_file | | keyword | +| config.property_key | | keyword | +| config.ref_type | | keyword | +| config.resolved_path | | keyword | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.name | | keyword | +| file.path | | keyword | +| id | Tychon unique document identifier for the asset record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| process.name | | keyword | +| process.path | | keyword | +| process.pid | | long | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### browser_exts +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-installed-browser-extensions + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the browser extension record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| package.description | | keyword | +| package.name | | keyword | +| package.version | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.browser_extension.browser | | keyword | +| tychon.browser_extension.extension_id | | keyword | +| tychon.browser_extension.permissions | | keyword | +| tychon.browser_extension.profile_path | | keyword | +| tychon.browser_extension.quantum_ready | | boolean | +| tychon.index | | keyword | +| tychon.scan_mode | | keyword | +| tychon.type | | keyword | + +#### certificates +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-certificates + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| certificate.basic_constraints.is_ca | | boolean | +| certificate.basic_constraints.max_path_len | | long | +| certificate.basic_constraints.max_path_len_zero | | boolean | +| certificate.file_details.attributes | | keyword | +| certificate.file_details.extension | | keyword | +| certificate.file_details.group | | keyword | +| certificate.file_details.md5_hash | | keyword | +| certificate.file_details.name | | keyword | +| certificate.file_details.owner | | keyword | +| certificate.file_details.path | | keyword | +| certificate.file_details.sha1_hash | | keyword | +| certificate.file_details.sha256_hash | | keyword | +| certificate.file_details.size | | long | +| certificate.is_csr | | boolean | +| certificate.is_private_key | | boolean | +| certificate.is_self_signed | | boolean | +| certificate.issuer | | keyword | +| certificate.issuer_common_name | | keyword | +| certificate.key_usage | | keyword | +| certificate.not_after | | date | +| certificate.not_before | | date | +| certificate.pqc_vulnerable | | boolean | +| certificate.raw_pem_certificate | | match_only_text | +| certificate.serial_number | | keyword | +| certificate.sha1_fingerprint | | keyword | +| certificate.sha256_fingerprint | | keyword | +| certificate.signature_algorithm | | keyword | +| certificate.source_file_path | | keyword | +| certificate.source_id | | keyword | +| certificate.subject | | keyword | +| certificate.subject_common_name | | keyword | +| certificate.subject_public_key_info.algorithm | | keyword | +| certificate.subject_public_key_info.bit_size | | long | +| certificate.subject_public_key_info.rsa_exponent | | long | +| certificate.subject_public_key_info.rsa_modulus_hex | | wildcard | +| certificate.universal_id | | keyword | +| certificate.validity.duration_days | | keyword | +| certificate.version | | long | +| crypto.key_algorithm | | keyword | +| crypto.key_size | | long | +| crypto.signature_algorithm | | keyword | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.extension | | keyword | +| file.group.name | | keyword | +| file.mtime | | date | +| file.name | | keyword | +| file.owner.name | | keyword | +| file.path | | keyword | +| file.permissions | | keyword | +| file.size | | long | +| hash.sha256_certificate | | keyword | +| id | Tychon unique document identifier for the certificate record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| omb.sig_tier | | keyword | +| pqc.vulnerable | | boolean | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | +| x509.is_valid | | boolean | +| x509.issuer.common_name | | keyword | +| x509.issuer.distinguished_name | | keyword | +| x509.public_key_algorithm | | keyword | +| x509.public_key_size | | long | +| x509.serial_number | | keyword | +| x509.signature_algorithm | | keyword | +| x509.subject.common_name | | keyword | +| x509.subject.distinguished_name | | keyword | +| x509.validity.not_after | | date | +| x509.validity.not_before | | date | +| x509.version_number | | long | + +#### ciphers +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-ciphers + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| error.message | | match_only_text | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| hash.sha1_certificate | | keyword | +| hash.sha256_certificate | | keyword | +| id | Tychon unique document identifier for the cipher record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| omb.additional_notes | | wildcard | +| omb.block_cipher_key_lengths | | keyword | +| omb.block_cipher_modes | | keyword | +| omb.block_ciphers | | keyword | +| omb.certifications | | keyword | +| omb.crqc_vulnerable_algos | | keyword | +| omb.dsa_algorithms | | keyword | +| omb.hash_algorithms | | keyword | +| omb.kem_algorithms | | keyword | +| omb.kex_ciphersuites | | keyword | +| omb.kex_protocols | | keyword | +| omb.mac_algorithms | | keyword | +| omb.module_name | | keyword | +| omb.operating_system | | keyword | +| omb.other_crypto_details | | keyword | +| omb.other_protocols | | keyword | +| omb.pqc_algos | | keyword | +| omb.software_package_name | | keyword | +| omb.software_package_version | | keyword | +| omb.symmetric_algos | | keyword | +| omb.vulnerability_status | | keyword | +| port.number | | long | +| port.protocol_detected | | keyword | +| port.status_overall | | keyword | +| process.command_line | | wildcard | +| process.executable | | keyword | +| process.executable_directory | | keyword | +| process.name | | keyword | +| process.pid | | long | +| process.username | | keyword | +| quantum_ready | | boolean | +| quantum_ready_cert | | boolean | +| quantum_ready_cipher | | boolean | +| quantum_ready_kx | | boolean | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| server.address | | keyword | +| server.ip | | ip | +| server.port | | long | +| service.name | | keyword | +| service.state | | keyword | +| target_host.address | | keyword | +| target_host.domain | | keyword | +| target_host.ip | | ip | +| target_host.ipv4 | | ip | +| tychon.cipher.config_source | | keyword | +| tychon.cipher.insecure_ciphers | | keyword | +| tychon.cipher.is_encrypted | | boolean | +| tychon.cipher.migration_priority | | keyword | +| tychon.cipher.port | | long | +| tychon.cipher.pqc_readiness | | keyword | +| tychon.cipher.pqc_vulnerable | | boolean | +| tychon.cipher.protocol | | keyword | +| tychon.cipher.quantum_risk | | keyword | +| tychon.cipher.recommended_action | | keyword | +| tychon.cipher.supported_ciphers | | keyword | +| tychon.crypto.cipher | | keyword | +| tychon.crypto.pqc_readiness | | keyword | +| tychon.crypto.pqc_vulnerable | | boolean | +| tychon.crypto.protocol | | keyword | +| tychon.crypto.quantum_risk | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | +| x509.issuer.common_name | | keyword | +| x509.issuer.distinguished_name | | keyword | +| x509.public_key_algorithm | | keyword | +| x509.public_key_size | | long | +| x509.serial_number | | keyword | +| x509.signature_algorithm | | keyword | +| x509.subject.common_name | | keyword | +| x509.subject.distinguished_name | | keyword | + +#### crypto_libs +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-crypto-libraries + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| id | Tychon unique document identifier for the crypto library record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| process.executable | | keyword | +| process.executable_directory | | keyword | +| process.name | | keyword | +| process.pid | | long | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.library.crypto_type | | keyword | +| tychon.library.name | | keyword | +| tychon.library.openssl_version | | keyword | +| tychon.library.pqc_status | | keyword | +| tychon.library.uses_openssl | | boolean | +| tychon.library.uses_windows_cng | | boolean | +| tychon.library.windows_cng_version | | keyword | +| tychon.type | | keyword | +| vulnerability.assessed_at | | date | +| vulnerability.is_vulnerable | | boolean | +| vulnerability.risk_level | | keyword | +| vulnerability.risk_reason | | keyword | + +#### inst_apps +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-installed-apps + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the installed application record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| package.description | | keyword | +| package.install_directory | | keyword | +| package.name | | keyword | +| package.path | | keyword | +| package.version | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.installed_app.crypto_library_count | | long | +| tychon.scan_mode | | keyword | +| tychon.type | | keyword | + +#### inventory +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-inventory + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| destination.domain | | keyword | +| destination.ip | | ip | +| destination.port | | long | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| host.architecture | | keyword | +| host.hostname | | keyword | +| host.id | | keyword | +| host.ip | | keyword | +| host.os_category | | keyword | +| host.os_pqc_tier | | keyword | +| id | Tychon unique document identifier for the inventory record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.database_schema_version | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.output_schema_version | | keyword | +| observer.tychon_client_id | | keyword | +| observer.type | | keyword | +| observer.vendor | | keyword | +| observer.version | | keyword | +| observer.windows_server_role | | keyword | +| omb.kex_primary | | keyword | +| omb.kex_primary_quantum_safe | | boolean | +| omb.kex_secondary | | keyword | +| omb.kex_tier | | keyword | +| omb.protocol_tier | | keyword | +| omb.sig_tier | | keyword | +| process.command_line | | wildcard | +| process.executable | | keyword | +| process.executable_directory | | keyword | +| process.name | | keyword | +| process.pid | | long | +| process.start | | date | +| process.user_name | | keyword | +| quantum_ready | | boolean | +| quantum_ready_cert | | boolean | +| quantum_ready_cipher | | boolean | +| quantum_ready_kx | | boolean | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| scan_type | | keyword | +| server.port | | long | +| server.protocol | | keyword | +| tls.duration_ms | | long | +| tls.insecure_cipher_count | | long | +| tls.insecure_ciphers | | keyword | +| tls.preferred_cipher | | keyword | +| tls.preferred_key_exchange | | keyword | +| tls.preferred_protocol | | keyword | +| tls.supported_key_exchange_count | | long | +| tls.supported_key_exchanges | | keyword | +| tls.supported_protocol_count | | long | +| tls.supported_protocols | | keyword | +| tls.total_probes | | long | +| tychon.index | | keyword | +| tychon.type | | keyword | +| x509.issuer_cn | | keyword | +| x509.key_bits | | long | +| x509.key_type | | keyword | +| x509.key_usage | | keyword | +| x509.not_after | | date | +| x509.not_before | | date | +| x509.serial_number | | keyword | +| x509.sha256_fingerprint | | keyword | +| x509.sig_algorithm | | keyword | +| x509.subject_cn | | keyword | + +#### ipsec_tnls +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-ipsec-tunnels + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| id | Tychon unique document identifier for the IPSec tunnel record. | keyword | +| ipsec_tunnel.active | | boolean | +| ipsec_tunnel.config_path | | keyword | +| ipsec_tunnel.detection_confidence | | keyword | +| ipsec_tunnel.detection_method | | keyword | +| ipsec_tunnel.first_detected | | date | +| ipsec_tunnel.implementation | | keyword | +| ipsec_tunnel.last_seen | | date | +| ipsec_tunnel.name | | keyword | +| ipsec_tunnel.source_id | | keyword | +| ipsec_tunnel.status | | keyword | +| ipsec_tunnel.version | | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| pqc.is_pqc_ready | | boolean | +| pqc.pqc_migration_status | | keyword | +| pqc.quantum_resistance | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| security.known_vulnerabilities | | keyword | +| security.perfect_forward_secrecy | | boolean | +| security.pqc_support | | boolean | +| security.pqc_vulnerable | | boolean | +| security.risk_level | | keyword | +| security.score | | long | +| security.security_score | | long | +| security.vulnerable | | boolean | +| security.weak_crypto | | boolean | +| security.weak_dh_group | | boolean | +| tunnel_details.auth_method | | keyword | +| tunnel_details.dh_group | | keyword | +| tunnel_details.encryption_algorithm | | keyword | +| tunnel_details.integrity_algorithm | | keyword | +| tunnel_details.mode | | keyword | +| tunnel_details.nat_traversal | | boolean | +| tunnel_details.perfect_forward_secrecy | | boolean | +| tunnel_details.protocol | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### keystores +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-keystores + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.name | | keyword | +| file.path | | keyword | +| id | Tychon unique document identifier for the keystore record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| keystore.accessible | | boolean | +| keystore.cert_count | | long | +| keystore.path | | keyword | +| keystore.requires_auth | | boolean | +| keystore.stats.certificate_types.ca | | long | +| keystore.stats.expired_certificates | | long | +| keystore.stats.key_algorithms.ECDSA | | long | +| keystore.stats.key_algorithms.RSA | | long | +| keystore.stats.pqc_vulnerable_certificates | | long | +| keystore.stats.vulnerable_certificates | | long | +| keystore.type | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### macsec +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-macsec + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the MACsec record. | keyword | +| macsec.cipher_suite | | keyword | +| macsec.detection_confidence | | keyword | +| macsec.detection_method | | keyword | +| macsec.implementation | | keyword | +| macsec.interface_name | | keyword | +| macsec.key_agreement_method | | keyword | +| macsec.parent_interface | | keyword | +| macsec.risk_level | | keyword | +| macsec.sci | | keyword | +| macsec.status | | keyword | +| macsec.validation_mode | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### readiness +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-system-readiness + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Timestamp when the readiness event occurred. | date | +| data_stream.dataset | Data stream dataset of the source event. | constant_keyword | +| data_stream.namespace | Data stream namespace of the source event. | constant_keyword | +| data_stream.type | Data stream type of the source event. | constant_keyword | +| ecs.version | ECS version of the transformed event. | keyword | +| error.message | Error message captured during readiness collection or processing. | match_only_text | +| event.action | Action captured for the readiness event. | keyword | +| event.category | Event category for the readiness event. | keyword | +| event.dataset | Event dataset of the source readiness record. | keyword | +| event.ingested | Timestamp when the event was ingested into Elasticsearch. | date | +| event.kind | Event kind for the readiness record. | keyword | +| id | Tychon unique document identifier for the system readiness record. | keyword | +| kerberos.config_source | Source of Kerberos encryption configuration. | keyword | +| kerberos.has_aes128 | Indicates whether AES128 Kerberos support is enabled. | boolean | +| kerberos.has_aes256 | Indicates whether AES256 Kerberos support is enabled. | boolean | +| kerberos.has_des | Indicates whether DES Kerberos support is enabled. | boolean | +| kerberos.has_rc4 | Indicates whether RC4 Kerberos support is enabled. | boolean | +| kerberos.is_explicitly_configured | Indicates whether Kerberos encryption settings are explicitly configured. | boolean | +| kerberos.is_quantum_safe | Indicates whether the Kerberos configuration is considered post-quantum safe. | boolean | +| kerberos.raw_bitmask | Windows Kerberos encryption type bitmask, when available. | long | +| kerberos.supported_types | Supported Kerberos encryption types as reported by the host. | keyword | +| observer.bigfix_client_installed | Indicates whether a BigFix client is installed on the observer host. | boolean | +| observer.bios_serial_number | BIOS serial number reported by the observer host. | keyword | +| observer.cpu_cores | Number of physical CPU cores reported by the observer host. | long | +| observer.cpu_logical_cores | Number of logical CPU cores reported by the observer host. | long | +| observer.cpu_model_name | CPU model name reported by the observer host. | keyword | +| observer.cpu_vendor_id | CPU vendor identifier reported by the observer host. | keyword | +| observer.current_user | Current user context used by the observer when scanning. | keyword | +| observer.domain | Domain associated with the observer host. | keyword | +| observer.fips_mode_enabled | Indicates whether FIPS mode is enabled on the observer host. | boolean | +| observer.hostname | Hostname of the observer host. | keyword | +| observer.id | Unique observer identifier. | keyword | +| observer.ip_addresses | IP addresses reported by the observer host. | keyword | +| observer.is_vdi_environment | Indicates whether the observer is running in a VDI environment. | boolean | +| observer.kernel_arch | Kernel architecture reported by the observer host. | keyword | +| observer.kernel_version | Kernel version reported by the observer host. | keyword | +| observer.machine_serial_number | Machine serial number reported by the observer host. | keyword | +| observer.organization | Organization associated with the observer host. | keyword | +| observer.os.build | Observer operating system build identifier. | keyword | +| observer.os.family | Observer operating system family. | keyword | +| observer.os.kernel | Observer operating system kernel string. | keyword | +| observer.os.name | Observer operating system name. | keyword | +| observer.os.platform | Observer operating system platform. | keyword | +| observer.os.version | Observer operating system version. | keyword | +| observer.platform_version | Platform-specific version string reported by the observer host. | keyword | +| observer.ram_used_percent | Percent of RAM in use on the observer host. | float | +| observer.software_version | Tychon software version on the observer host. | keyword | +| observer.system_uptime_seconds | System uptime in seconds on the observer host. | long | +| observer.total_ram_bytes | Total RAM bytes on the observer host. | long | +| observer.tychon_client_id | Tychon client identifier reported on Windows endpoints. | keyword | +| observer.user_gid | Current user group identifier on the observer host. | keyword | +| observer.user_home_dir | Home directory of the current user on the observer host. | keyword | +| observer.user_uid | Current user identifier on the observer host. | keyword | +| observer.vdi_identity_source | Source used to determine VDI identity. | keyword | +| observer.windows_server_role | Windows server role or workstation role of the observer host. | keyword | +| quantum_readiness.assessment_duration_ms | Duration of the readiness assessment in milliseconds. | long | +| quantum_readiness.assessment_id | Unique assessment identifier emitted by TQC. | keyword | +| quantum_readiness.assessment_type | Type of readiness assessment performed. | keyword | +| quantum_readiness.compliance.common_criteria | Indicates whether Common Criteria readiness is met. | boolean | +| quantum_readiness.compliance.compliance_notes | Compliance notes reported by the readiness assessment. | wildcard | +| quantum_readiness.compliance.fips_ready | Indicates whether FIPS readiness requirements are met. | boolean | +| quantum_readiness.compliance.nist_ready | Indicates whether NIST readiness requirements are met. | boolean | +| quantum_readiness.cost_analysis.labor_rate_used | Labor rate used for cost analysis. | float | +| quantum_readiness.cost_analysis.os_category | Operating system category used in cost analysis. | keyword | +| quantum_readiness.cost_analysis.os_hardware_cost_usd | Hardware cost for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_labor_cost_usd | Labor cost for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_labor_hours | Labor hours for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_license_cost_usd | License cost for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_tier | Operating system tier classification for cost analysis. | keyword | +| quantum_readiness.cost_analysis.os_total_cost_usd | Total operating system remediation cost. | float | +| quantum_readiness.cost_analysis.os_upgrade_target | Target operating system identified for remediation. | keyword | +| quantum_readiness.cost_analysis.total_cost_usd | Total estimated remediation cost. | float | +| quantum_readiness.cost_analysis.total_hardware_cost_usd | Total estimated hardware cost. | float | +| quantum_readiness.cost_analysis.total_labor_cost_usd | Total estimated labor cost. | float | +| quantum_readiness.cost_analysis.total_labor_hours | Total estimated labor hours. | float | +| quantum_readiness.cost_analysis.total_license_cost_usd | Total estimated license cost. | float | +| quantum_readiness.crypto_libraries.fips_mode | Indicates whether FIPS mode is enabled for system crypto libraries. | boolean | +| quantum_readiness.crypto_libraries.legacy_libraries_present | Indicates whether legacy crypto libraries were detected. | boolean | +| quantum_readiness.crypto_libraries.max_score | Maximum score available for crypto libraries. | long | +| quantum_readiness.crypto_libraries.openssl_max_score | Maximum score assigned to OpenSSL readiness. | long | +| quantum_readiness.crypto_libraries.openssl_score | OpenSSL readiness score. | long | +| quantum_readiness.crypto_libraries.openssl_version | OpenSSL version detected on the system. | keyword | +| quantum_readiness.crypto_libraries.oqs_provider | Indicates whether an OQS provider was detected. | boolean | +| quantum_readiness.crypto_libraries.pqc_support | Indicates whether post-quantum crypto support was detected. | boolean | +| quantum_readiness.crypto_libraries.system_crypto_max_score | Maximum score available for the system crypto stack. | long | +| quantum_readiness.crypto_libraries.system_crypto_score | Score assigned to the system crypto stack. | long | +| quantum_readiness.crypto_libraries.system_libraries | System crypto libraries detected during the assessment. | keyword | +| quantum_readiness.crypto_libraries.total_score | Total crypto library readiness score. | long | +| quantum_readiness.crypto_libraries.uses_openssl | Indicates whether OpenSSL was detected in the system crypto stack. | boolean | +| quantum_readiness.detailed_report | Markdown-formatted detailed readiness report. | match_only_text | +| quantum_readiness.hardware.architecture | Hardware architecture evaluated by the readiness assessment. | keyword | +| quantum_readiness.hardware.available_ram_gb | Available RAM in gigabytes. | float | +| quantum_readiness.hardware.base_frequency_ghz | Base CPU frequency in gigahertz. | float | +| quantum_readiness.hardware.cores | Number of CPU cores evaluated. | long | +| quantum_readiness.hardware.cpu_max_score | Maximum possible CPU score. | long | +| quantum_readiness.hardware.cpu_score | CPU score assigned by the assessment. | long | +| quantum_readiness.hardware.has_aes_ni | Indicates whether AES-NI instructions are available. | boolean | +| quantum_readiness.hardware.has_avx2 | Indicates whether AVX2 instructions are available. | boolean | +| quantum_readiness.hardware.has_hsm | Indicates whether a hardware security module is available. | boolean | +| quantum_readiness.hardware.has_neon | Indicates whether NEON instructions are available. | boolean | +| quantum_readiness.hardware.has_secure_boot | Indicates whether secure boot support is available. | boolean | +| quantum_readiness.hardware.has_tpm | Indicates whether TPM support is available. | boolean | +| quantum_readiness.hardware.instruction_sets | Instruction sets detected on the host. | keyword | +| quantum_readiness.hardware.logical_cores | Number of logical CPU cores evaluated. | long | +| quantum_readiness.hardware.max_score | Maximum hardware score. | long | +| quantum_readiness.hardware.memory_max_score | Maximum memory score. | long | +| quantum_readiness.hardware.memory_score | Memory score assigned by the assessment. | long | +| quantum_readiness.hardware.security_hw_max_score | Maximum security hardware score. | long | +| quantum_readiness.hardware.security_hw_score | Security hardware score assigned by the assessment. | long | +| quantum_readiness.hardware.total_ram_gb | Total RAM in gigabytes. | float | +| quantum_readiness.hardware.total_score | Total hardware readiness score. | long | +| quantum_readiness.hardware.tpm_version | TPM version detected on the host. | keyword | +| quantum_readiness.max_possible_score | Maximum possible score for the readiness assessment. | long | +| quantum_readiness.network.bandwidth_max_score | Maximum bandwidth score. | long | +| quantum_readiness.network.bandwidth_score | Bandwidth score assigned by the assessment. | long | +| quantum_readiness.network.estimated_bandwidth_mbps | Estimated network bandwidth in megabits per second. | long | +| quantum_readiness.network.ipv6_support | Indicates whether IPv6 support is available. | boolean | +| quantum_readiness.network.latency_ms | Estimated network latency in milliseconds. | long | +| quantum_readiness.network.max_score | Maximum network score. | long | +| quantum_readiness.network.modern_cipher_support | Indicates whether modern network ciphers are supported. | boolean | +| quantum_readiness.network.mtu | Network MTU detected during assessment. | long | +| quantum_readiness.network.protocol_max_score | Maximum network protocol score. | long | +| quantum_readiness.network.protocol_score | Network protocol score assigned by the assessment. | long | +| quantum_readiness.network.tls13_capable | Indicates whether TLS 1.3 capability is present. | boolean | +| quantum_readiness.network.total_score | Total network readiness score. | long | +| quantum_readiness.operating_system.build | Operating system build reported by the assessment. | keyword | +| quantum_readiness.operating_system.crypto_api_max_score | Maximum operating system crypto API score. | long | +| quantum_readiness.operating_system.crypto_api_score | Operating system crypto API score assigned by the assessment. | long | +| quantum_readiness.operating_system.crypto_framework | Native crypto framework detected on the operating system. | keyword | +| quantum_readiness.operating_system.family | Operating system family evaluated by the assessment. | keyword | +| quantum_readiness.operating_system.fips_mode_enabled | Indicates whether operating system FIPS mode is enabled. | boolean | +| quantum_readiness.operating_system.kernel_version | Kernel version evaluated by the assessment. | keyword | +| quantum_readiness.operating_system.max_score | Maximum operating system score. | long | +| quantum_readiness.operating_system.modern_crypto_api | Indicates whether a modern crypto API is available. | boolean | +| quantum_readiness.operating_system.native_pqc_support | Indicates whether native post-quantum support is available. | boolean | +| quantum_readiness.operating_system.os_version_max_score | Maximum operating system version score. | long | +| quantum_readiness.operating_system.os_version_score | Operating system version score assigned by the assessment. | long | +| quantum_readiness.operating_system.pqc_framework | Post-quantum framework detected on the operating system. | keyword | +| quantum_readiness.operating_system.symcrypt_present | Indicates whether SymCrypt is present. | boolean | +| quantum_readiness.operating_system.total_score | Total operating system readiness score. | long | +| quantum_readiness.operating_system.version | Operating system version evaluated by the assessment. | keyword | +| quantum_readiness.overall_score | Overall readiness score. | long | +| quantum_readiness.readiness_status | High-level readiness status returned by the assessment. | keyword | +| quantum_readiness.ready_timeline | Estimated timeline to reach readiness. | keyword | +| quantum_readiness.recommendations | Readiness recommendations summarized by TQC. | keyword | +| quantum_readiness.status_color | UI-oriented status color assigned by TQC. | keyword | +| quantum_readiness.system_classification.criticality_level | System criticality level assigned by TQC. | keyword | +| quantum_readiness.system_classification.detection_reason | Reason used to classify the system role and type. | keyword | +| quantum_readiness.system_classification.role | System role assigned by the readiness assessment. | keyword | +| quantum_readiness.system_classification.type | System type assigned by the readiness assessment. | keyword | +| quantum_readiness.timestamp | Native readiness timestamp emitted by TQC. | date | +| quantum_readiness.upgrade_pathway.action | Recommended remediation action. | keyword | +| quantum_readiness.upgrade_pathway.component | Component targeted by the remediation action. | keyword | +| quantum_readiness.upgrade_pathway.description | Description of the recommended remediation step. | keyword | +| quantum_readiness.upgrade_pathway.estimated_time_weeks | Estimated time in weeks for the remediation step. | long | +| quantum_readiness.upgrade_pathway.order | Ordered step number in the upgrade pathway. | long | +| quantum_readiness.upgrade_pathway.priority | Priority assigned to the remediation step. | keyword | +| scan.target_input | Original scan target input supplied to TQC. | keyword | +| scan.timestamp | Timestamp emitted by the scanner for this record. | date | +| scan.type | Scan mode used to collect the readiness record. | keyword | +| tags | Tags preserved on the transformed readiness document. | keyword | +| tychon.index | Tychon dataset discriminator used by the source event. | keyword | +| tychon.type | Tychon record type. | keyword | + +#### vpn_clients +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-vpn-clients + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.path | | keyword | +| id | Tychon unique document identifier for the VPN client record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| security.pqc_support | | boolean | +| security.pqc_vulnerable | | boolean | +| security.risk_level | | keyword | +| security.score | | long | +| security.security_score | | long | +| security.vulnerable | | boolean | +| security.weak_crypto | | boolean | +| service.name | | keyword | +| service.state | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | +| vpn_client.active | | boolean | +| vpn_client.config_path | | keyword | +| vpn_client.detection_confidence | | keyword | +| vpn_client.detection_method | | keyword | +| vpn_client.executable_path | | keyword | +| vpn_client.first_detected | | date | +| vpn_client.install_path | | keyword | +| vpn_client.last_seen | | date | +| vpn_client.name | | keyword | +| vpn_client.service_name | | keyword | +| vpn_client.status | | keyword | +| vpn_client.vendor | | keyword | +| vpn_client.version | | keyword | +| vpn_config.auto_reconnect | | boolean | +| vpn_config.config_encrypted | | boolean | +| vpn_config.dns_leak_protection | | boolean | +| vpn_config.ipv6_leak_protection | | boolean | +| vpn_config.kill_switch | | boolean | +| vpn_config.logging_enabled | | boolean | +| vpn_config.split_tunneling | | boolean | diff --git a/packages/tychon_quantum_command/changelog.yml b/packages/tychon_quantum_command/changelog.yml new file mode 100644 index 00000000000..deeb8714e22 --- /dev/null +++ b/packages/tychon_quantum_command/changelog.yml @@ -0,0 +1,5 @@ +- version: 2.0.4 + changes: + - description: Initial release of the TYCHON Quantum Command integration package. + type: enhancement + link: https://github.com/tychonllc/tychon_quantum_command/issues/1 diff --git a/packages/tychon_quantum_command/data_stream/tychon_pqc/agent/stream/stream.yml.hbs b/packages/tychon_quantum_command/data_stream/tychon_pqc/agent/stream/stream.yml.hbs new file mode 100644 index 00000000000..e776f9b81fd --- /dev/null +++ b/packages/tychon_quantum_command/data_stream/tychon_pqc/agent/stream/stream.yml.hbs @@ -0,0 +1,44 @@ +paths: +{{#each windows_paths}} + - {{this}} +{{/each}} +{{#each linux_paths}} + - {{this}} +{{/each}} +{{#each paths}} + - {{this}} +{{/each}} + +prospector.scanner.exclude_files: ['.gz$'] + +tags: +{{#if preserve_original_event}} + - preserve_original_event +{{/if}} +{{#if tags}} +{{#each tags}} + - {{this}} +{{/each}} +{{else}} + - tychon + - quantum +{{/if}} + +fields_under_root: true + +parsers: + - ndjson: + target: "" + overwrite_keys: true + expand_keys: true + +processors: + - add_locale: ~ +{{#if preserve_original_event}} + - copy_fields: + fields: + - from: message + to: event.original + fail_on_error: false + ignore_missing: true +{{/if}} diff --git a/packages/tychon_quantum_command/data_stream/tychon_pqc/elasticsearch/ingest_pipeline/default.yml b/packages/tychon_quantum_command/data_stream/tychon_pqc/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 00000000000..49ce3e92983 --- /dev/null +++ b/packages/tychon_quantum_command/data_stream/tychon_pqc/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,627 @@ +--- +description: Main ingest pipeline for Tychon Quantum Command. +processors: + - set: + field: ecs.version + value: 8.17.0 + + - json: + field: message + add_to_root: true + if: ctx.tychon == null && ctx.message != null + ignore_failure: true + + - rename: + field: timestamp + target_field: "@timestamp" + ignore_missing: true + ignore_failure: true + + - date: + field: "@timestamp" + formats: + - ISO8601 + ignore_failure: true + + - set: + field: event.ingested + value: "{{_ingest.timestamp}}" + + - script: + lang: painless + description: Preserve flat event.* fields before event defaults are applied. + source: > + if (ctx.event == null || !(ctx.event instanceof Map)) { + ctx.event = [:]; + } + if (ctx.event.dataset == null && ctx.containsKey('event.dataset')) { + ctx.event.dataset = ctx['event.dataset']; + ctx.remove('event.dataset'); + } + if (ctx.event.kind == null && ctx.containsKey('event.kind')) { + ctx.event.kind = ctx['event.kind']; + ctx.remove('event.kind'); + } + if (ctx.event.action == null && ctx.containsKey('event.action')) { + ctx.event.action = ctx['event.action']; + ctx.remove('event.action'); + } + if (ctx.event.type == null && ctx.containsKey('event.type')) { + ctx.event.type = ctx['event.type']; + ctx.remove('event.type'); + } + if (ctx.event.category == null && ctx.containsKey('event.category')) { + def category = ctx['event.category']; + if (category instanceof List) { + ctx.event.category = category; + } else if (category instanceof String && category.contains(',')) { + List categories = new ArrayList(); + for (String item : category.splitOnToken(',')) { + String trimmed = item.trim(); + if (trimmed.length() > 0) { + categories.add(trimmed); + } + } + ctx.event.category = categories; + } else { + ctx.event.category = [category]; + } + ctx.remove('event.category'); + } + + - set: + field: event.kind + value: event + if: ctx.event == null || ctx.event.kind == null + + - set: + field: event.category + value: + - configuration + if: ctx.event == null || ctx.event.category == null + + - script: + lang: painless + source: > + if (ctx.event == null || !(ctx.event instanceof Map)) { + ctx.event = [:]; + } + def tychonIndex = null; + if (ctx.containsKey('tychon') && ctx.tychon instanceof Map && ctx.tychon.containsKey('index') && ctx.tychon.index != null) { + tychonIndex = ctx.tychon.index.toString(); + } + def eventAction = ctx.event.action != null ? ctx.event.action.toString() : null; + def genericDataset = tychonIndex != null ? 'tychon_quantum_command.' + tychonIndex : null; + def currentDataset = ctx.event.dataset; + def shouldDeriveDataset = ( + currentDataset == null || + currentDataset == 'tychon_quantum_command.tychon_pqc' || + currentDataset == 'tychon_pqc' || + (genericDataset != null && currentDataset == genericDataset) || + (genericDataset != null && currentDataset instanceof List && currentDataset.contains(genericDataset)) + ); + if (shouldDeriveDataset) { + def dataset = 'tychon_quantum_command.tychon_pqc'; + if (tychonIndex != null) { + if (tychonIndex == 'applications') { + dataset = 'tychon.application'; + } else if (tychonIndex == 'installed-apps') { + dataset = 'tychon.installed_app'; + } else if (tychonIndex == 'installed-browser-extensions') { + dataset = 'tychon.browser_extension'; + } else if (tychonIndex == 'ciphers') { + dataset = 'tychon.cipher'; + } else if (tychonIndex == 'system-readiness') { + if (eventAction == 'quantum_assessment_app_group') { + dataset = 'quantum_assessment.app_group'; + } else { + dataset = 'quantum_assessment'; + } + } else { + dataset = genericDataset; + } + } + ctx.event.dataset = dataset; + } + + - set: + field: data_stream.type + value: logs + + - set: + field: data_stream.dataset + value: tychon_pqc + + - set: + field: tychon.pipeline.processed + value: true + + - remove: + field: host.ipv4 + ignore_missing: true + if: ctx?.host?.ipv4 instanceof String && ctx.host.ipv4.trim().length() == 0 + + - remove: + field: host.ipv6 + ignore_missing: true + if: ctx?.host?.ipv6 instanceof String && ctx.host.ipv6.trim().length() == 0 + + - dot_expander: + field: "*" + ignore_failure: true + + - split: + field: tls.supported_protocols + separator: ",\\s*" + ignore_missing: true + + - split: + field: tls.supported_ciphers + separator: ",\\s*" + ignore_missing: true + + - split: + field: tls.supported_key_exchanges + separator: ",\\s*" + ignore_missing: true + + - split: + field: tls.previous_supported_protocols + separator: ",\\s*" + ignore_missing: true + + - split: + field: tls.previous_supported_ciphers + separator: ",\\s*" + ignore_missing: true + + - split: + field: tls.previous_supported_key_exchanges + separator: ",\\s*" + ignore_missing: true + + - split: + field: tychon.cipher_quick.supported_protocols + separator: ",\\s*" + ignore_missing: true + + - split: + field: tychon.cipher_quick.supported_cipher_suites + separator: ",\\s*" + ignore_missing: true + + - split: + field: tychon.cipher_quick.supported_key_exchanges + separator: ",\\s*" + ignore_missing: true + + - split: + field: tls.insecure_ciphers + separator: ",\\s*" + ignore_missing: true + + - split: + field: tls.weak_ciphers + separator: ",\\s*" + ignore_missing: true + + - split: + field: tychon.cipher_quick.insecure_ciphers + separator: ",\\s*" + ignore_missing: true + + - split: + field: tychon.cipher_quick.weak_ciphers + separator: ",\\s*" + ignore_missing: true + + - split: + field: host.ip + separator: ",\\s*" + ignore_missing: true + if: ctx?.host?.ip instanceof String + + - split: + field: tychon.routing.original.host_ip + separator: ",\\s*" + ignore_missing: true + if: ctx?.tychon?.routing?.original?.host_ip instanceof String + + - split: + field: tychon.routing.target.ip + separator: ",\\s*" + ignore_missing: true + if: ctx?.tychon?.routing?.target?.ip instanceof String + + - split: + field: tychon.tags + separator: ",\\s*" + ignore_missing: true + + - split: + field: tychon.installed_app.crypto_libraries + separator: ",\\s*" + ignore_missing: true + + - script: + lang: painless + description: Normalize host.ip from literal dotted field or comma-delimited string. + source: > + if (ctx.containsKey('host.ip')) { + def dottedHostIp = ctx['host.ip']; + if (dottedHostIp instanceof String && dottedHostIp.contains(',')) { + List ips = new ArrayList(); + for (String ip : dottedHostIp.splitOnToken(',')) { + String trimmed = ip.trim(); + if (trimmed.length() > 0) { + ips.add(trimmed); + } + } + if (ctx.host == null) { + ctx.host = [:]; + } + if (ctx.host.ip == null) { + ctx.host.ip = ips; + } + } else if (ctx.host == null) { + ctx.host = ['ip': dottedHostIp]; + } else if (ctx.host.ip == null) { + ctx.host.ip = dottedHostIp; + } + ctx.remove('host.ip'); + } + if (ctx?.host?.ip instanceof String && ctx.host.ip.contains(',')) { + List ips = new ArrayList(); + for (String ip : ctx.host.ip.splitOnToken(',')) { + String trimmed = ip.trim(); + if (trimmed.length() > 0) { + ips.add(trimmed); + } + } + ctx.host.ip = ips; + } + + - script: + lang: painless + description: Reconstruct tychon.certificate_leaf_details from certificate fields. + if: ctx?.certificate != null && ctx?.tychon?.certificate_leaf_details == null + source: > + if (ctx.tychon == null) { + ctx.tychon = [:]; + } + Map leafDetails = [:]; + Map subject = [:]; + if (ctx.certificate.subject_common_name != null) { subject.common_name = ctx.certificate.subject_common_name; } + if (ctx.certificate.subject_country != null) { subject.country = ctx.certificate.subject_country; } + if (ctx.certificate.subject_locality != null) { subject.locality = ctx.certificate.subject_locality; } + if (ctx.certificate.subject_organization != null) { subject.organization = ctx.certificate.subject_organization; } + if (ctx.certificate.subject_organizational_unit != null) { subject.organizational_unit = ctx.certificate.subject_organizational_unit; } + if (ctx.certificate.subject_province != null) { subject.province = ctx.certificate.subject_province; } + if (ctx.certificate.subject != null) { subject.raw_string = ctx.certificate.subject; } + if (!subject.isEmpty()) { leafDetails.subject = subject; } + Map issuer = [:]; + if (ctx.certificate.issuer_common_name != null) { issuer.common_name = ctx.certificate.issuer_common_name; } + if (ctx.certificate.issuer_country != null) { issuer.country = ctx.certificate.issuer_country; } + if (ctx.certificate.issuer_locality != null) { issuer.locality = ctx.certificate.issuer_locality; } + if (ctx.certificate.issuer_organization != null) { issuer.organization = ctx.certificate.issuer_organization; } + if (ctx.certificate.issuer_organizational_unit != null) { issuer.organizational_unit = ctx.certificate.issuer_organizational_unit; } + if (ctx.certificate.issuer_province != null) { issuer.province = ctx.certificate.issuer_province; } + if (ctx.certificate.issuer != null) { issuer.raw_string = ctx.certificate.issuer; } + if (!issuer.isEmpty()) { leafDetails.issuer = issuer; } + Map validity = [:]; + if (ctx.certificate.not_before != null) { validity.not_before = ctx.certificate.not_before; } + if (ctx.certificate.not_after != null) { validity.not_after = ctx.certificate.not_after; } + if (ctx.certificate.validity != null && ctx.certificate.validity instanceof Map && ctx.certificate.validity.duration_days != null) { validity.duration_days = ctx.certificate.validity.duration_days; } + if (!validity.isEmpty()) { leafDetails.validity = validity; } + if (ctx.certificate.serial_number != null) { leafDetails.serial_number = ctx.certificate.serial_number; } + if (ctx.certificate.signature_algorithm != null) { leafDetails.signature_algorithm = ctx.certificate.signature_algorithm; } + if (ctx.certificate.signature_hex != null) { leafDetails.signature_hex = ctx.certificate.signature_hex; } + if (ctx.certificate.version != null) { leafDetails.version = ctx.certificate.version; } + if (ctx.certificate.is_csr != null) { leafDetails.is_csr = ctx.certificate.is_csr; } + if (ctx.certificate.is_private_key != null) { leafDetails.is_private_key = ctx.certificate.is_private_key; } + if (ctx.certificate.is_self_signed != null) { leafDetails.is_self_signed = ctx.certificate.is_self_signed; } + if (ctx.certificate.key_usage != null) { leafDetails.key_usage = ctx.certificate.key_usage; } + if (ctx.certificate.extended_key_usage != null) { leafDetails.extended_key_usage = ctx.certificate.extended_key_usage; } + if (ctx.certificate.basic_constraints != null) { leafDetails.basic_constraints = ctx.certificate.basic_constraints; } + if (ctx.certificate.subject_public_key_info != null) { leafDetails.subject_public_key_info = ctx.certificate.subject_public_key_info; } + if (ctx.certificate.sha256_fingerprint != null) { leafDetails.sha256_fingerprint = ctx.certificate.sha256_fingerprint; } + if (ctx.certificate.sha1_fingerprint != null) { leafDetails.sha1_fingerprint = ctx.certificate.sha1_fingerprint; } + if (ctx.certificate.subject_key_id != null) { leafDetails.subject_key_id = ctx.certificate.subject_key_id; } + if (ctx.certificate.pqc_vulnerable != null) { leafDetails.pqc_vulnerable = ctx.certificate.pqc_vulnerable; } + if (ctx.certificate.raw_pem_certificate != null) { leafDetails.raw_pem_certificate = ctx.certificate.raw_pem_certificate; } + if (ctx.certificate.source_id != null) { leafDetails.source_id = ctx.certificate.source_id; } + ctx.tychon.certificate_leaf_details = leafDetails; + + - script: + lang: painless + description: Reconstruct tychon.cipher_negotiation from cipher fields. + if: ctx?.cipher != null + source: > + if (ctx.tychon == null) { + ctx.tychon = [:]; + } + Map cipherNeg = [:]; + if (ctx.cipher.cipher_suite != null) { cipherNeg.cipher_suite = ctx.cipher.cipher_suite; } + if (ctx.cipher.protocol != null) { cipherNeg.protocol = ctx.cipher.protocol; } + if (ctx.cipher.key_length_bits != null) { cipherNeg.key_length_bits = ctx.cipher.key_length_bits; } + if (ctx.cipher.is_preferred != null) { cipherNeg.is_preferred = ctx.cipher.is_preferred; } + if (ctx.cipher.active != null) { cipherNeg.active = ctx.cipher.active; } + if (ctx.cipher.source != null) { cipherNeg.source = ctx.cipher.source; } + if (ctx.cipher.source_id != null) { cipherNeg.source_id = ctx.cipher.source_id; } + if (ctx.cipher.universal_id != null) { cipherNeg.universal_id = ctx.cipher.universal_id; } + if (ctx.cipher.session_id != null) { cipherNeg.session_id = ctx.cipher.session_id; } + if (ctx.cipher.compression_method != null) { cipherNeg.compression_method = ctx.cipher.compression_method; } + if (ctx.cipher.alpn_protocol != null) { cipherNeg.alpn_protocol = ctx.cipher.alpn_protocol; } + if (ctx.cipher.last_seen != null) { cipherNeg.last_seen = ctx.cipher.last_seen; } + if (ctx.cipher.session_ticket_lifetime_hint_seconds != null) { cipherNeg.session_ticket_lifetime_hint_seconds = ctx.cipher.session_ticket_lifetime_hint_seconds; } + if (ctx.cipher.intel != null) { cipherNeg.intel = ctx.cipher.intel; } + ctx.tychon.cipher_negotiation = cipherNeg; + + - script: + lang: painless + description: Convert cipher vulnerability strings into arrays. + if: ctx?.tychon?.cipher_negotiation?.intel?.vulnerabilities != null + source: > + if (ctx.tychon.cipher_negotiation.intel.vulnerabilities instanceof String) { + String vulnString = ctx.tychon.cipher_negotiation.intel.vulnerabilities; + List vulnList = new ArrayList(); + String[] parts = vulnString.splitOnToken(','); + for (String part : parts) { + String trimmed = part.trim(); + if (trimmed.length() > 0) { + vulnList.add(trimmed); + } + } + ctx.tychon.cipher_negotiation.intel.vulnerabilities = vulnList; + } + + - script: + lang: painless + description: Default app-group instance counts without leaking app-family fields into root assessments. + if: ctx?.quantum_readiness?.cost_analysis != null && ctx?.event?.dataset == 'quantum_assessment.app_group' + source: > + if (ctx.quantum_readiness.cost_analysis instanceof Map) { + Map costAnalysis = ctx.quantum_readiness.cost_analysis; + if (costAnalysis.instance_count == null) { + costAnalysis.instance_count = 1; + } + } + + - set: + field: x509.subject.common_name + value: "{{certificate.subject_common_name}}" + if: ctx?.certificate?.subject_common_name != null + + - set: + field: x509.issuer.common_name + value: "{{certificate.issuer_common_name}}" + if: ctx?.certificate?.issuer_common_name != null + + - set: + field: x509.issuer.organization + value: "{{certificate.issuer_organization}}" + if: ctx?.certificate?.issuer_organization != null + + - set: + field: x509.subject.organization + value: "{{certificate.subject_organization}}" + if: ctx?.certificate?.subject_organization != null + + - set: + field: x509.serial_number + value: "{{certificate.serial_number}}" + if: ctx?.certificate?.serial_number != null + + - set: + field: x509.signature_algorithm + value: "{{certificate.signature_algorithm}}" + if: ctx?.certificate?.signature_algorithm != null + + - set: + field: x509.not_before + value: "{{certificate.not_before}}" + if: ctx?.certificate?.not_before != null + + - set: + field: x509.not_after + value: "{{certificate.not_after}}" + if: ctx?.certificate?.not_after != null + + - set: + field: x509.public_key_algorithm + value: "{{certificate.subject_public_key_info.algorithm}}" + if: ctx?.certificate?.subject_public_key_info?.algorithm != null + + - set: + field: x509.public_key_size + value: "{{certificate.subject_public_key_info.bit_size}}" + if: ctx?.certificate?.subject_public_key_info?.bit_size != null + + - set: + field: x509.public_key_curve + value: "{{certificate.subject_public_key_info.curve}}" + if: ctx?.certificate?.subject_public_key_info?.curve != null + + - date: + field: certificate.not_before + target_field: certificate.not_before + formats: + - ISO8601 + - yyyy-MM-dd'T'HH:mm:ssXXX + - yyyy-MM-dd'T'HH:mm:ss.SSSXXX + - yyyy-MM-dd HH:mm:ss + - MMM dd HH:mm:ss yyyy 'GMT' + if: ctx?.certificate?.not_before != null + on_failure: + - append: + field: error.pipeline + value: "Failed to parse certificate.not_before: {{_ingest.on_failure_message}}" + + - date: + field: certificate.not_after + target_field: certificate.not_after + formats: + - ISO8601 + - yyyy-MM-dd'T'HH:mm:ssXXX + - yyyy-MM-dd'T'HH:mm:ss.SSSXXX + - yyyy-MM-dd HH:mm:ss + - MMM dd HH:mm:ss yyyy 'GMT' + if: ctx?.certificate?.not_after != null + on_failure: + - append: + field: error.pipeline + value: "Failed to parse certificate.not_after: {{_ingest.on_failure_message}}" + + - date: + field: cipher.last_seen + target_field: cipher.last_seen + formats: + - ISO8601 + - yyyy-MM-dd'T'HH:mm:ssXXX + - yyyy-MM-dd'T'HH:mm:ss.SSSXXX + if: ctx?.cipher?.last_seen != null + on_failure: + - append: + field: error.pipeline + value: "Failed to parse cipher.last_seen: {{_ingest.on_failure_message}}" + + - set: + field: host.hostname + value: "{{tychon.routing.original.host_hostname}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_hostname != null && ctx.tychon.routing.original.host_hostname != '' + + - set: + field: host.domain + value: "{{observer.domain}}" + ignore_empty_value: true + if: ctx?.host?.domain == null && ctx?.observer?.domain != null && ctx.observer.domain != '' + + - set: + field: host.id + value: "{{tychon.routing.original.host_id}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_id != null && ctx.tychon.routing.original.host_id != '' + + - set: + field: host.ip + copy_from: tychon.routing.original.host_ip + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_ip != null + + - set: + field: host.ipv4 + value: "{{tychon.routing.original.host_ipv4}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_ipv4 != null && ctx.tychon.routing.original.host_ipv4 != '' + + - set: + field: host.ipv6 + value: "{{tychon.routing.original.host_ipv6}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_ipv6 != null && ctx.tychon.routing.original.host_ipv6 != '' + + - set: + field: host.architecture + value: "{{tychon.routing.original.host_architecture}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_architecture != null && ctx.tychon.routing.original.host_architecture != '' + + - set: + field: host.os.name + value: "{{tychon.routing.original.host_os_name}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_os_name != null && ctx.tychon.routing.original.host_os_name != '' + + - set: + field: host.os.platform + value: "{{tychon.routing.original.host_os_platform}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_os_platform != null && ctx.tychon.routing.original.host_os_platform != '' + + - set: + field: host.os.family + value: "{{tychon.routing.original.host_os_family}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_os_family != null && ctx.tychon.routing.original.host_os_family != '' + + - set: + field: host.os.version + value: "{{tychon.routing.original.host_os_version}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.original?.host_os_version != null && ctx.tychon.routing.original.host_os_version != '' + + - set: + field: source.user.id + value: "{{tychon.routing.source.observer_id}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.source?.observer_id != null && ctx.tychon.routing.source.observer_id != '' + + - set: + field: source.domain + value: "{{tychon.routing.source.hostname}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.source?.hostname != null && ctx.tychon.routing.source.hostname != '' + + - set: + field: destination.address + value: "{{tychon.routing.target.address}}" + ignore_empty_value: true + if: ctx?.tychon?.routing?.target?.address != null && ctx.tychon.routing.target.address != '' + + - set: + field: destination.ip + copy_from: tychon.routing.target.ip + ignore_empty_value: true + if: ctx?.tychon?.routing?.target?.ip != null + + - set: + field: network.protocol + value: "{{port.protocol_detected}}" + ignore_empty_value: true + if: ctx?.network?.protocol == null && ctx?.port?.protocol_detected != null && ctx.port.protocol_detected != '' + + - set: + field: network.protocol + value: "{{tychon.application.protocol_detected}}" + ignore_empty_value: true + if: ctx?.network?.protocol == null && ctx?.tychon?.application?.protocol_detected != null && ctx.tychon.application.protocol_detected != '' + + - convert: + field: tychon.application.port + type: long + ignore_missing: true + ignore_failure: true + + - convert: + field: tychon.application.port_quantum_grade.score + type: float + ignore_missing: true + ignore_failure: true + + - remove: + field: message + ignore_missing: true + if: (ctx.tychon != null || ctx.containsKey('tychon.index')) && (ctx.event == null || ctx.event.original == null) + + - remove: + field: message + ignore_missing: true + if: ctx.event != null && ctx.event.original != null + +on_failure: + - set: + field: tychon.pipeline.failed + value: true + - set: + field: error.message + value: "{{{ _ingest.on_failure_message }}}" + - set: + field: error.processor_type + value: "{{{ _ingest.on_failure_processor_type }}}" + - set: + field: error.processor_tag + value: "{{{ _ingest.on_failure_processor_tag }}}" + - set: + field: error.pipeline + value: "{{{ _ingest.on_failure_pipeline }}}" diff --git a/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/base-fields.yml b/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/base-fields.yml new file mode 100644 index 00000000000..5f3be129606 --- /dev/null +++ b/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/base-fields.yml @@ -0,0 +1,44 @@ +- name: "@timestamp" + type: date + +- name: id + type: keyword + +- name: quantum_ready + type: boolean + +- name: quantum_ready_cert + type: boolean + +- name: quantum_ready_cipher + type: boolean + +- name: quantum_ready_kx + type: boolean + +- name: scan_type + type: keyword + +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword + +- name: package + type: group + fields: + - name: description + type: keyword + - name: install_directory + type: keyword + - name: name + type: keyword + - name: path + type: keyword + - name: version + type: keyword diff --git a/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/ecs.yml b/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/ecs.yml new file mode 100644 index 00000000000..7cffead21a1 --- /dev/null +++ b/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/ecs.yml @@ -0,0 +1,329 @@ +- name: data_stream + type: group + fields: + - name: type + type: constant_keyword + - name: dataset + type: constant_keyword + - name: namespace + type: constant_keyword + +- name: ecs + type: group + fields: + - name: version + type: keyword + +- name: destination + type: group + fields: + - name: address + type: keyword + - name: domain + type: keyword + - name: ip + type: ip + - name: port + type: long + +- name: error + type: group + fields: + - name: message + type: match_only_text + - name: pipeline + type: keyword + - name: processor_tag + type: keyword + - name: processor_type + type: keyword + +- name: event + type: group + fields: + - name: action + type: keyword + - name: category + type: keyword + - name: dataset + type: keyword + - name: ingested + type: date + - name: kind + type: keyword + - name: original + type: match_only_text + - name: type + type: keyword + +- name: file + type: group + fields: + - name: extension + type: keyword + - name: mtime + type: date + - name: name + type: keyword + - name: path + type: keyword + - name: permissions + type: keyword + - name: size + type: long + - name: group + type: group + fields: + - name: name + type: keyword + - name: owner + type: group + fields: + - name: name + type: keyword + +- name: hash + type: group + fields: + - name: sha1_certificate + type: keyword + - name: sha256_certificate + type: keyword + +- name: host + type: group + fields: + - name: architecture + type: keyword + - name: domain + type: keyword + - name: hostname + type: keyword + - name: id + type: keyword + - name: ip + type: ip + - name: ipv4 + type: ip + - name: ipv6 + type: ip + - name: os_category + type: keyword + - name: os_pqc_tier + type: keyword + - name: cpu + type: group + fields: + - name: cores + type: long + - name: memory + type: group + fields: + - name: total + type: long + - name: os + type: group + fields: + - name: family + type: keyword + - name: kernel + type: keyword + - name: name + type: keyword + - name: platform + type: keyword + - name: version + type: keyword + +- name: network + type: group + fields: + - name: protocol + type: keyword + +- name: observer + type: group + fields: + - name: bigfix_client_installed + type: boolean + - name: bios_serial_number + type: keyword + - name: cpu_cores + type: long + - name: cpu_logical_cores + type: long + - name: cpu_model_name + type: keyword + - name: cpu_vendor_id + type: keyword + - name: current_user + type: keyword + - name: database_schema_version + type: keyword + - name: domain + type: keyword + - name: error + type: keyword + - name: fips_mode_enabled + type: boolean + - name: hostname + type: keyword + - name: id + type: keyword + - name: ip_addresses + type: keyword + - name: is_vdi_environment + type: boolean + - name: kernel_arch + type: keyword + - name: kernel_version + type: keyword + - name: machine_serial_number + type: keyword + - name: organization + type: keyword + - name: output_schema_version + type: keyword + - name: platform_version + type: keyword + - name: ram_used_percent + type: float + - name: software_version + type: keyword + - name: system_uptime_seconds + type: long + - name: total_ram_bytes + type: long + - name: tychon_client_id + type: keyword + - name: type + type: keyword + - name: user_gid + type: keyword + - name: user_home_dir + type: keyword + - name: user_uid + type: keyword + - name: vdi_identity_source + type: keyword + - name: vendor + type: keyword + - name: version + type: keyword + - name: windows_server_role + type: keyword + - name: os + type: group + fields: + - name: build + type: keyword + - name: family + type: keyword + - name: kernel + type: keyword + - name: name + type: keyword + - name: platform + type: keyword + - name: version + type: keyword + +- name: process + type: group + fields: + - name: command_line + type: wildcard + - name: executable + type: keyword + - name: executable_directory + type: keyword + - name: name + type: keyword + - name: path + type: keyword + - name: pid + type: long + - name: start + type: date + - name: user_name + type: keyword + - name: username + type: keyword + - name: executable_file + type: group + fields: + - name: attributes + type: keyword + - name: company_name + type: keyword + - name: extension + type: keyword + - name: file_version + type: keyword + - name: group + type: keyword + - name: md5_hash + type: keyword + - name: name + type: keyword + - name: owner + type: keyword + - name: path + type: keyword + - name: product_name + type: keyword + - name: product_version + type: keyword + - name: sha1_hash + type: keyword + - name: sha256_hash + type: keyword + - name: size + type: long + - name: hash + type: group + fields: + - name: sha256 + type: keyword + - name: service_info + type: group + fields: + - name: description + type: keyword + - name: display_name + type: keyword + - name: name + type: keyword + - name: state + type: keyword + +- name: server + type: group + fields: + - name: address + type: keyword + - name: ip + type: ip + - name: port + type: long + - name: protocol + type: keyword + +- name: service + type: group + fields: + - name: name + type: keyword + - name: state + type: keyword + +- name: source + type: group + fields: + - name: domain + type: keyword + - name: user + type: group + fields: + - name: id + type: keyword diff --git a/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/fields.yml b/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/fields.yml new file mode 100644 index 00000000000..59dc5560200 --- /dev/null +++ b/packages/tychon_quantum_command/data_stream/tychon_pqc/fields/fields.yml @@ -0,0 +1,1450 @@ +- name: tychon + title: Tychon + type: group + fields: + - name: index + type: keyword + - name: asset_type + type: keyword + - name: scan_mode + type: keyword + - name: type + type: keyword + - name: pqc_readiness + type: keyword + - name: quantum_risk + type: keyword + - name: migration_priority + type: keyword + - name: scanner_version + type: keyword + - name: pipeline + type: group + fields: + - name: failed + type: boolean + - name: processed + type: boolean + - name: routing + type: group + fields: + - name: original + type: group + fields: + - name: host_architecture + type: keyword + - name: host_hostname + type: keyword + - name: host_id + type: keyword + - name: host_ip + type: ip + - name: host_ipv4 + type: ip + - name: host_ipv6 + type: ip + - name: host_os_family + type: keyword + - name: host_os_name + type: keyword + - name: host_os_platform + type: keyword + - name: host_os_version + type: keyword + - name: source + type: group + fields: + - name: hostname + type: keyword + - name: observer_id + type: keyword + - name: target + type: group + fields: + - name: address + type: keyword + - name: ip + type: ip + - name: application + type: group + fields: + - name: app_root + type: keyword + - name: company_name + type: keyword + - name: connected_to_count + type: long + - name: crypto_library_count + type: long + - name: file_version + type: keyword + - name: in_memory_cert_count + type: long + - name: insecure_ciphers + type: keyword + - name: keychain_identity_count + type: long + - name: keystore_count + type: long + - name: name + type: keyword + - name: path + type: keyword + - name: pid + type: long + - name: port + type: long + - name: port_count + type: long + - name: preferred_cipher + type: keyword + - name: preferred_key_exchange + type: keyword + - name: preferred_protocol + type: keyword + - name: private_key_count + type: long + - name: product_name + type: keyword + - name: product_version + type: keyword + - name: protocol_detected + type: keyword + - name: quantum_ready + type: boolean + - name: service_display_name + type: keyword + - name: service_name + type: keyword + - name: software_package_names + type: keyword + - name: software_package_versions + type: keyword + - name: source + type: keyword + - name: supported_cipher_suites + type: keyword + - name: supported_key_exchanges + type: keyword + - name: supported_protocols + type: keyword + - name: weak_ciphers + type: keyword + - name: port_quantum_grade + type: group + fields: + - name: grade + type: keyword + - name: score + type: float + - name: quantum_grade + type: group + fields: + - name: best_port_score + type: float + - name: grade + type: keyword + - name: os_deductions + type: float + - name: score + type: float + - name: worst_port_score + type: float + - name: browser_extension + type: group + fields: + - name: browser + type: keyword + - name: extension_id + type: keyword + - name: permissions + type: keyword + - name: profile_path + type: keyword + - name: quantum_ready + type: boolean + - name: cipher_negotiation + type: group + fields: + - name: active + type: boolean + - name: alpn_protocol + type: keyword + - name: cipher_suite + type: keyword + - name: compression_method + type: keyword + - name: is_preferred + type: boolean + - name: key_length_bits + type: long + - name: last_seen + type: date + - name: protocol + type: keyword + - name: session_id + type: keyword + - name: session_ticket_lifetime_hint_seconds + type: long + - name: source + type: keyword + - name: source_id + type: keyword + - name: universal_id + type: keyword + - name: intel + type: group + fields: + - name: vulnerabilities + type: keyword + - name: certificate_leaf_details + type: group + fields: + - name: extended_key_usage + type: keyword + - name: is_csr + type: boolean + - name: is_private_key + type: boolean + - name: is_self_signed + type: boolean + - name: key_usage + type: keyword + - name: pqc_vulnerable + type: boolean + - name: raw_pem_certificate + type: match_only_text + - name: serial_number + type: keyword + - name: sha1_fingerprint + type: keyword + - name: sha256_fingerprint + type: keyword + - name: signature_algorithm + type: keyword + - name: signature_hex + type: wildcard + - name: source_id + type: keyword + - name: subject_key_id + type: keyword + - name: version + type: long + - name: basic_constraints + type: group + fields: + - name: is_ca + type: boolean + - name: max_path_len_zero + type: boolean + - name: issuer + type: group + fields: + - name: common_name + type: keyword + - name: country + type: keyword + - name: locality + type: keyword + - name: organization + type: keyword + - name: organizational_unit + type: keyword + - name: province + type: keyword + - name: raw_string + type: keyword + - name: subject + type: group + fields: + - name: common_name + type: keyword + - name: country + type: keyword + - name: locality + type: keyword + - name: organization + type: keyword + - name: organizational_unit + type: keyword + - name: province + type: keyword + - name: raw_string + type: keyword + - name: subject_public_key_info + type: group + fields: + - name: algorithm + type: keyword + - name: bit_size + type: long + - name: curve + type: keyword + - name: ecdsa_x_hex + type: wildcard + - name: ecdsa_y_hex + type: wildcard + - name: rsa_exponent + type: long + - name: rsa_modulus_hex + type: wildcard + - name: validity + type: group + fields: + - name: duration_days + type: keyword + - name: not_after + type: date + - name: not_before + type: date + - name: cipher + type: group + fields: + - name: config_source + type: keyword + - name: insecure_ciphers + type: keyword + - name: is_encrypted + type: boolean + - name: migration_priority + type: keyword + - name: port + type: long + - name: pqc_readiness + type: keyword + - name: pqc_vulnerable + type: boolean + - name: protocol + type: keyword + - name: quantum_risk + type: keyword + - name: recommended_action + type: keyword + - name: supported_ciphers + type: keyword + - name: cipher_quick + type: group + fields: + - name: duration_ms + type: long + - name: insecure_cipher_count + type: long + - name: insecure_ciphers + type: keyword + - name: preferred_cipher + type: keyword + - name: preferred_key_exchange + type: keyword + - name: preferred_protocol + type: keyword + - name: supported_cipher_count + type: long + - name: supported_cipher_suites + type: keyword + - name: supported_key_exchange_count + type: long + - name: supported_key_exchanges + type: keyword + - name: supported_protocol_count + type: long + - name: supported_protocols + type: keyword + - name: total_probes + type: long + - name: weak_cipher_count + type: long + - name: weak_ciphers + type: keyword + - name: crypto + type: group + fields: + - name: auth + type: keyword + - name: certificate + type: keyword + - name: cipher + type: keyword + - name: grade + type: keyword + - name: grade_score + type: float + - name: key_exchange + type: keyword + - name: mac + type: keyword + - name: pqc_readiness + type: keyword + - name: pqc_vulnerable + type: boolean + - name: protocol + type: keyword + - name: protocol_version + type: keyword + - name: quantum_risk + type: keyword + - name: installed_app + type: group + fields: + - name: crypto_libraries + type: keyword + - name: crypto_library_count + type: long + - name: library + type: group + fields: + - name: crypt32_pqc_status + type: keyword + - name: crypt32_version + type: keyword + - name: crypto_type + type: keyword + - name: gnutls_pqc_status + type: keyword + - name: gnutls_version + type: keyword + - name: name + type: keyword + - name: nss_pqc_status + type: keyword + - name: openssl_pqc_status + type: keyword + - name: openssl_version + type: keyword + - name: pqc_algorithms + type: keyword + - name: pqc_status + type: keyword + - name: schannel_pqc_status + type: keyword + - name: schannel_version + type: keyword + - name: uses_crypt32 + type: boolean + - name: uses_gnutls + type: boolean + - name: uses_nss + type: boolean + - name: uses_openssl + type: boolean + - name: uses_schannel + type: boolean + - name: uses_windows_cng + type: boolean + - name: windows_cng_pqc_status + type: keyword + - name: windows_cng_version + type: keyword + +- name: certificate + type: group + fields: + - name: alias + type: keyword + - name: authority_key_id + type: keyword + - name: chain_complete + type: boolean + - name: crl_distribution_points + type: keyword + - name: cve_list + type: keyword + - name: ext_key_usage + type: keyword + - name: extended_key_usage + type: keyword + - name: has_private_key + type: boolean + - name: is_ca + type: boolean + - name: is_csr + type: boolean + - name: is_private_key + type: boolean + - name: is_self_signed + type: boolean + - name: issuer + type: keyword + - name: issuer_common_name + type: keyword + - name: issuer_country + type: keyword + - name: issuer_locality + type: keyword + - name: issuer_organization + type: keyword + - name: issuer_organizational_unit + type: keyword + - name: issuer_province + type: keyword + - name: issuing_certificate_urls + type: keyword + - name: key_algorithm + type: keyword + - name: key_size + type: long + - name: key_strength_assessment + type: keyword + - name: key_usage + type: keyword + - name: migration_priority + type: keyword + - name: not_after + type: date + - name: not_before + type: date + - name: ocsp_servers + type: keyword + - name: policy_identifiers + type: keyword + - name: pqc_readiness + type: keyword + - name: pqc_reason + type: wildcard + - name: pqc_vulnerable + type: boolean + - name: quantum_risk + type: keyword + - name: raw_pem_certificate + type: match_only_text + - name: recommended_action + type: keyword + - name: risk_level + type: keyword + - name: risk_reason + type: wildcard + - name: serial_number + type: keyword + - name: sha1_fingerprint + type: keyword + - name: sha256_fingerprint + type: keyword + - name: signature_algorithm + type: keyword + - name: signature_hex + type: wildcard + - name: source_file_path + type: keyword + - name: source_id + type: keyword + - name: subject + type: keyword + - name: subject_common_name + type: keyword + - name: subject_country + type: keyword + - name: subject_key_id + type: keyword + - name: subject_locality + type: keyword + - name: subject_organization + type: keyword + - name: subject_organizational_unit + type: keyword + - name: subject_province + type: keyword + - name: thumbprint + type: keyword + - name: universal_id + type: keyword + - name: version + type: long + - name: vulnerable + type: boolean + - name: basic_constraints + type: group + fields: + - name: is_ca + type: boolean + - name: max_path_len + type: long + - name: max_path_len_zero + type: boolean + - name: file_details + type: group + fields: + - name: attributes + type: keyword + - name: extension + type: keyword + - name: group + type: keyword + - name: md5_hash + type: keyword + - name: name + type: keyword + - name: owner + type: keyword + - name: path + type: keyword + - name: sha1_hash + type: keyword + - name: sha256_hash + type: keyword + - name: size + type: long + - name: subject_alternative_names + type: group + fields: + - name: dns_names + type: keyword + - name: email_addresses + type: keyword + - name: ip_addresses + type: keyword + - name: subject_public_key_info + type: group + fields: + - name: algorithm + type: keyword + - name: bit_size + type: long + - name: curve + type: keyword + - name: ecdsa_x_hex + type: wildcard + - name: ecdsa_y_hex + type: wildcard + - name: rsa_exponent + type: long + - name: rsa_modulus_hex + type: wildcard + - name: validity + type: group + fields: + - name: duration_days + type: keyword + +- name: config + type: group + fields: + - name: config_file + type: keyword + - name: property_key + type: keyword + - name: ref_type + type: keyword + - name: resolved_path + type: keyword + +- name: crypto + type: group + fields: + - name: key_algorithm + type: keyword + - name: key_size + type: long + - name: signature_algorithm + type: keyword + +- name: ipsec_tunnel + type: group + fields: + - name: active + type: boolean + - name: config_path + type: keyword + - name: detection_confidence + type: keyword + - name: detection_method + type: keyword + - name: first_detected + type: date + - name: implementation + type: keyword + - name: last_seen + type: date + - name: name + type: keyword + - name: source_id + type: keyword + - name: status + type: keyword + - name: version + type: keyword + +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_explicitly_configured + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword + +- name: keystore + type: group + fields: + - name: accessible + type: boolean + - name: cert_count + type: long + - name: error_message + type: keyword + - name: path + type: keyword + - name: permissions + type: keyword + - name: requires_auth + type: boolean + - name: size + type: long + - name: type + type: keyword + - name: encryption + type: group + fields: + - name: iterations + type: long + - name: mac + type: keyword + - name: salt_length + type: long + - name: vulnerable + type: boolean + - name: stats + type: group + fields: + - name: expired_certificates + type: long + - name: pqc_vulnerable_certificates + type: long + - name: vulnerable_certificates + type: long + - name: certificate_types + type: group + fields: + - name: ca + type: long + - name: end_entity + type: long + - name: key_algorithms + type: group + fields: + - name: ECDSA + type: long + - name: RSA + type: long + +- name: omb + type: group + fields: + - name: additional_notes + type: wildcard + - name: block_cipher_key_lengths + type: keyword + - name: block_cipher_modes + type: keyword + - name: block_ciphers + type: keyword + - name: certifications + type: keyword + - name: crqc_vulnerable_algos + type: keyword + - name: dsa_algorithms + type: keyword + - name: dsa_hash_algorithms + type: keyword + - name: dsa_parameters + type: keyword + - name: hash_algorithm_parameters + type: keyword + - name: hash_algorithms + type: keyword + - name: kem_algorithms + type: keyword + - name: kem_parameters + type: keyword + - name: kex_ciphersuites + type: keyword + - name: kex_primary + type: keyword + - name: kex_primary_quantum_safe + type: boolean + - name: kex_protocols + type: keyword + - name: kex_secondary + type: keyword + - name: kex_tier + type: keyword + - name: mac_algorithm_parameters + type: keyword + - name: mac_algorithms + type: keyword + - name: module_name + type: keyword + - name: operating_system + type: keyword + - name: other_crypto_details + type: keyword + - name: other_protocols + type: keyword + - name: other_protocols_params + type: keyword + - name: pqc_algos + type: keyword + - name: protocol_tier + type: keyword + - name: sig_tier + type: keyword + - name: software_package_name + type: keyword + - name: software_package_version + type: keyword + - name: symmetric_algos + type: keyword + - name: vendor + type: keyword + - name: vulnerability_status + type: keyword + +- name: port + type: group + fields: + - name: number + type: long + - name: protocol_detected + type: keyword + - name: status_overall + type: keyword + +- name: pqc + type: group + fields: + - name: is_pqc_ready + type: boolean + - name: key_strength + type: keyword + - name: migration_priority + type: keyword + - name: pqc_migration_status + type: keyword + - name: quantum_resistance + type: keyword + - name: quantum_risk + type: keyword + - name: readiness + type: keyword + - name: reason + type: wildcard + - name: recommended_action + type: keyword + - name: vulnerable + type: boolean + +- name: quantum_readiness + type: group + fields: + - name: assessment_duration_ms + type: long + - name: assessment_id + type: keyword + - name: assessment_type + type: keyword + - name: detailed_report + type: match_only_text + - name: max_possible_score + type: long + - name: overall_score + type: long + - name: readiness_status + type: keyword + - name: ready_timeline + type: keyword + - name: recommendations + type: keyword + - name: status_color + type: keyword + - name: timestamp + type: date + - name: compliance + type: group + fields: + - name: common_criteria + type: boolean + - name: compliance_notes + type: wildcard + - name: fips_ready + type: boolean + - name: nist_ready + type: boolean + - name: cost_analysis + type: group + fields: + - name: app_family + type: keyword + - name: labor_rate_used + type: float + - name: hardware_cost_usd + type: float + - name: instance_count + type: long + - name: labor_cost_usd + type: float + - name: license_cost_usd + type: float + - name: os_category + type: keyword + - name: os_hardware_cost_usd + type: float + - name: os_labor_cost_usd + type: float + - name: os_labor_hours + type: float + - name: os_license_cost_usd + type: float + - name: os_tier + type: keyword + - name: os_total_cost_usd + type: float + - name: os_upgrade_target + type: keyword + - name: tier + type: keyword + - name: total_cost_usd + type: float + - name: total_hardware_cost_usd + type: float + - name: total_labor_cost_usd + type: float + - name: total_labor_hours + type: float + - name: total_license_cost_usd + type: float + - name: crypto_libraries + type: group + fields: + - name: fips_mode + type: boolean + - name: legacy_libraries_present + type: boolean + - name: max_score + type: long + - name: openssl_max_score + type: long + - name: openssl_score + type: long + - name: openssl_version + type: keyword + - name: oqs_provider + type: boolean + - name: pqc_support + type: boolean + - name: system_crypto_max_score + type: long + - name: system_crypto_score + type: long + - name: system_libraries + type: keyword + - name: total_score + type: long + - name: uses_openssl + type: boolean + - name: hardware + type: group + fields: + - name: architecture + type: keyword + - name: available_ram_gb + type: float + - name: base_frequency_ghz + type: float + - name: cores + type: long + - name: cpu_max_score + type: long + - name: cpu_score + type: long + - name: has_aes_ni + type: boolean + - name: has_avx2 + type: boolean + - name: has_hsm + type: boolean + - name: has_neon + type: boolean + - name: has_secure_boot + type: boolean + - name: has_tpm + type: boolean + - name: instruction_sets + type: keyword + - name: logical_cores + type: long + - name: max_score + type: long + - name: memory_max_score + type: long + - name: memory_score + type: long + - name: security_hw_max_score + type: long + - name: security_hw_score + type: long + - name: total_ram_gb + type: float + - name: total_score + type: long + - name: tpm_version + type: keyword + - name: network + type: group + fields: + - name: bandwidth_max_score + type: long + - name: bandwidth_score + type: long + - name: estimated_bandwidth_mbps + type: long + - name: ipv6_support + type: boolean + - name: latency_ms + type: long + - name: max_score + type: long + - name: modern_cipher_support + type: boolean + - name: mtu + type: long + - name: protocol_max_score + type: long + - name: protocol_score + type: long + - name: tls13_capable + type: boolean + - name: total_score + type: long + - name: operating_system + type: group + fields: + - name: build + type: keyword + - name: crypto_api_max_score + type: long + - name: crypto_api_score + type: long + - name: crypto_framework + type: keyword + - name: family + type: keyword + - name: fips_mode_enabled + type: boolean + - name: kernel_version + type: keyword + - name: max_score + type: long + - name: modern_crypto_api + type: boolean + - name: native_pqc_support + type: boolean + - name: os_version_max_score + type: long + - name: os_version_score + type: long + - name: pqc_framework + type: keyword + - name: symcrypt_present + type: boolean + - name: total_score + type: long + - name: version + type: keyword + - name: system_classification + type: group + fields: + - name: criticality_level + type: keyword + - name: detection_reason + type: keyword + - name: role + type: keyword + - name: type + type: keyword + - name: upgrade_pathway + type: group + fields: + - name: action + type: keyword + - name: component + type: keyword + - name: description + type: keyword + - name: estimated_time_weeks + type: long + - name: order + type: long + - name: priority + type: keyword + +- name: security + type: group + fields: + - name: known_vulnerabilities + type: keyword + - name: perfect_forward_secrecy + type: boolean + - name: pqc_support + type: boolean + - name: pqc_vulnerable + type: boolean + - name: risk_level + type: keyword + - name: score + type: long + - name: security_score + type: long + - name: vulnerable + type: boolean + - name: weak_crypto + type: boolean + - name: weak_dh_group + type: boolean + +- name: ssh + type: group + fields: + - name: banner + type: keyword + - name: status + type: keyword + - name: algorithms + type: group + fields: + - name: client_offered_ciphers + type: keyword + - name: client_offered_host_key_algos + type: keyword + - name: client_offered_kex + type: keyword + - name: client_offered_macs + type: keyword + - name: negotiated_cipher_c2s + type: keyword + - name: negotiated_cipher_s2c + type: keyword + - name: negotiated_host_key_algo + type: keyword + - name: negotiated_kex + type: keyword + - name: negotiated_mac_c2s + type: keyword + - name: negotiated_mac_s2c + type: keyword + - name: server_offered_ciphers_c2s + type: keyword + - name: server_offered_ciphers_s2c + type: keyword + - name: server_offered_host_key_algos + type: keyword + - name: server_offered_kex + type: keyword + - name: server_offered_macs_c2s + type: keyword + - name: server_offered_macs_s2c + type: keyword + - name: host_key + type: group + fields: + - name: bits + type: long + - name: fingerprint_sha256 + type: keyword + - name: public_key + type: match_only_text + - name: type + type: keyword + - name: x509_certificate + type: group + fields: + - name: is_csr + type: boolean + - name: is_private_key + type: boolean + - name: is_self_signed + type: boolean + - name: pqc_vulnerable + type: boolean + - name: serial_number + type: keyword + - name: source_file_path + type: keyword + - name: issuer + type: group + fields: + - name: common_name + type: keyword + - name: subject + type: group + fields: + - name: common_name + type: keyword + - name: subject_public_key_info + type: group + fields: + - name: algorithm + type: keyword + - name: bit_size + type: long + - name: server + type: group + fields: + - name: encryption_ciphers + type: keyword + - name: host_key_algorithms + type: keyword + - name: kex_algorithms + type: keyword + - name: mac_algorithms + type: keyword + +- name: target_host + type: group + fields: + - name: address + type: keyword + - name: domain + type: keyword + - name: ip + type: ip + - name: ipv4 + type: ip + +- name: tls + type: group + fields: + - name: duration_ms + type: long + - name: insecure_cipher_count + type: long + - name: insecure_ciphers + type: keyword + - name: preferred_cipher + type: keyword + - name: preferred_key_exchange + type: keyword + - name: preferred_protocol + type: keyword + - name: supported_cipher_count + type: long + - name: supported_ciphers + type: keyword + - name: supported_key_exchange_count + type: long + - name: supported_key_exchanges + type: keyword + - name: supported_protocol_count + type: long + - name: supported_protocols + type: keyword + - name: total_probes + type: long + - name: weak_cipher_count + type: long + - name: weak_ciphers + type: keyword + - name: certificate + type: group + fields: + - name: extended_key_usage + type: keyword + - name: issuer + type: keyword + - name: not_after + type: date + - name: not_before + type: date + - name: serial_number + type: keyword + - name: subject + type: keyword + - name: server + type: group + fields: + - name: cipher_count + type: long + - name: issuer + type: keyword + - name: not_after + type: date + - name: not_before + type: date + - name: serial_number + type: keyword + - name: subject + type: keyword + - name: supported_ciphers + type: keyword + - name: supported_protocols + type: keyword + - name: hash + type: group + fields: + - name: sha1 + type: keyword + +- name: tunnel_details + type: group + fields: + - name: auth_method + type: keyword + - name: dh_group + type: keyword + - name: encryption_algorithm + type: keyword + - name: integrity_algorithm + type: keyword + - name: mode + type: keyword + - name: nat_traversal + type: boolean + - name: perfect_forward_secrecy + type: boolean + - name: protocol + type: keyword + +- name: vpn_client + type: group + fields: + - name: active + type: boolean + - name: config_path + type: keyword + - name: detection_confidence + type: keyword + - name: detection_method + type: keyword + - name: executable_path + type: keyword + - name: first_detected + type: date + - name: install_path + type: keyword + - name: last_seen + type: date + - name: name + type: keyword + - name: service_name + type: keyword + - name: status + type: keyword + - name: vendor + type: keyword + - name: version + type: keyword + +- name: vpn_config + type: group + fields: + - name: auto_reconnect + type: boolean + - name: config_encrypted + type: boolean + - name: dns_leak_protection + type: boolean + - name: ipv6_leak_protection + type: boolean + - name: kill_switch + type: boolean + - name: logging_enabled + type: boolean + - name: split_tunneling + type: boolean + +- name: vulnerability + type: group + fields: + - name: assessed_at + type: date + - name: cve_list + type: keyword + - name: is_vulnerable + type: boolean + - name: risk_level + type: keyword + - name: risk_reason + type: wildcard + +- name: x509 + type: group + fields: + - name: fingerprint_sha256 + type: keyword + - name: is_ca + type: boolean + - name: is_self_signed + type: boolean + - name: is_valid + type: boolean + - name: is_weak_signature + type: boolean + - name: issuer_cn + type: keyword + - name: issuer_org + type: keyword + - name: key_bits + type: long + - name: key_type + type: keyword + - name: key_usage + type: keyword + - name: not_after + type: date + - name: not_before + type: date + - name: public_key_algorithm + type: keyword + - name: public_key_curve + type: keyword + - name: public_key_size + type: long + - name: serial_number + type: keyword + - name: sha256_fingerprint + type: keyword + - name: sig_algorithm + type: keyword + - name: signature_algorithm + type: keyword + - name: subject_cn + type: keyword + - name: subject_org + type: keyword + - name: version_number + type: long + - name: issuer + type: group + fields: + - name: common_name + type: keyword + - name: distinguished_name + type: keyword + - name: organization + type: keyword + - name: subject + type: group + fields: + - name: common_name + type: keyword + - name: distinguished_name + type: keyword + - name: organization + type: keyword + - name: validity + type: group + fields: + - name: not_after + type: date + - name: not_before + type: date diff --git a/packages/tychon_quantum_command/data_stream/tychon_pqc/manifest.yml b/packages/tychon_quantum_command/data_stream/tychon_pqc/manifest.yml new file mode 100644 index 00000000000..b49363e19bb --- /dev/null +++ b/packages/tychon_quantum_command/data_stream/tychon_pqc/manifest.yml @@ -0,0 +1,46 @@ +title: Tychon Quantum Command +type: logs +streams: + - input: filestream + title: Tychon Quantum Command logs + description: Collect TQC NDJSON output files. + template_path: stream.yml.hbs + vars: + - name: paths + type: text + title: Additional paths + multi: true + required: false + show_user: true + default: [] + - name: windows_paths + type: text + title: Windows paths + multi: true + required: false + show_user: true + default: + - C:\Program Files\Tychon\*.ndjson + - C:\ProgramData\Tychon\*.ndjson + - name: linux_paths + type: text + title: Linux paths + multi: true + required: false + show_user: true + default: + - /var/log/tychon/*.ndjson + - /opt/tychon/*.ndjson + - name: preserve_original_event + type: bool + title: Preserve original event + required: true + show_user: true + default: false + - name: tags + type: text + title: Tags + multi: true + required: false + show_user: true + default: [] diff --git a/packages/tychon_quantum_command/data_stream/tychon_pqc/sample_event.json b/packages/tychon_quantum_command/data_stream/tychon_pqc/sample_event.json new file mode 100644 index 00000000000..477c749dbeb --- /dev/null +++ b/packages/tychon_quantum_command/data_stream/tychon_pqc/sample_event.json @@ -0,0 +1,37 @@ +{ + "@timestamp": "2026-06-11T12:00:00Z", + "event": { + "kind": "event", + "category": ["configuration"], + "dataset": "tychon_quantum_command.tychon_pqc" + }, + "data_stream": { + "type": "logs", + "dataset": "tychon_quantum_command.tychon_pqc", + "namespace": "default" + }, + "ecs": { + "version": "8.17.0" + }, + "host": { + "hostname": "server01" + }, + "tychon": { + "index": "applications", + "asset_type": "application", + "scan_mode": "quantum_command", + "pqc_readiness": "partial", + "quantum_risk": "medium", + "application": { + "name": "Example Service", + "port": 443, + "preferred_protocol": "TLSv1.3", + "preferred_cipher": "TLS_AES_256_GCM_SHA384", + "preferred_key_exchange": "ECDHE", + "port_quantum_grade": { + "grade": "B", + "score": 82.5 + } + } + } +} diff --git a/packages/tychon_quantum_command/docs/README.md b/packages/tychon_quantum_command/docs/README.md new file mode 100644 index 00000000000..81f57c3c2ff --- /dev/null +++ b/packages/tychon_quantum_command/docs/README.md @@ -0,0 +1,1105 @@ + + + + +# TYCHON Quantum Command Integration for Elastic + +## Overview + +[TYCHON Quantum Command](https://tychon.io/products/tychon/pqc-management-module/) helps organizations inventory cryptographic implementations, assess post-quantum exposure, and prioritize remediation across endpoints, applications, certificates, network services, key stores, and platform readiness. This integration ingests TYCHON Quantum Command output files into Elastic, normalizes the source stream, and publishes entity-focused transform destinations for dashboards, search, and reporting. + +### Compatibility + +* Intended for environments where TYCHON Quantum Command produces NDJSON or JSON output files on Windows, Linux, or macOS systems. +* Requires a valid TYCHON Quantum Command license. +* Requires Elastic Stack / Fleet compatible with package version `2.0.4` and the package manifest constraint `^8.11.0`. + +### How it works + +1. TYCHON Quantum Command writes scan results to local `.ndjson` or `.json` files. +2. Elastic Agent collects those files through the `filestream` input in the `tychon_pqc` data stream. +3. The ingest pipeline stores the raw events in the namespace-specific source data stream `logs-tychon_quantum_command.tychon_pqc-`. +4. Elasticsearch transforms filter the combined source stream by `tychon.index` and publish dataset-specific destination indices such as `tychon-pqc-inventory`, `tychon-pqc-certificates`, and `tychon-pqc-system-readiness`. +5. Kibana dashboards and saved objects query both the raw and transformed views for operational analysis. + +## What data does this integration collect? + +The integration collects file-based TYCHON Quantum Command output in NDJSON or JSON form. The package is designed around one primary ingest stream and multiple analytical transforms. + +### Primary ingest stream + +* Data stream: `tychon_pqc` +* Data stream type: `logs` +* Expected source formats: NDJSON and JSON records written by TYCHON Quantum Command +* Collection method: Elastic Agent `filestream` +* Namespace-safe source data stream pattern used by transforms: `logs-tychon_quantum_command.tychon_pqc-*` +* Index template used by the source data stream: `logs-tychon_quantum_command.tychon_pqc` +* Backing index naming pattern for the source data stream: `.ds-logs-tychon_quantum_command.tychon_pqc--YYYY.MM.DD-000001` + +### Analytical datasets produced by transforms + +The package currently publishes the following destination indices from the shared source stream: + +* `tychon-pqc-applications` +* `tychon-pqc-archives` +* `tychon-pqc-assets` +* `tychon-pqc-certificates` +* `tychon-pqc-ciphers` +* `tychon-pqc-crypto-libraries` +* `tychon-pqc-installed-apps` +* `tychon-pqc-installed-browser-extensions` +* `tychon-pqc-inventory` +* `tychon-pqc-ipsec-tunnels` +* `tychon-pqc-keystores` +* `tychon-pqc-macsec` +* `tychon-pqc-system-readiness` +* `tychon-pqc-vpn-clients` + +### Supported use cases + +* Build a cryptographic inventory across endpoints and applications. +* Identify classical algorithms, deprecated protocols, and post-quantum readiness gaps. +* Review certificate and keystore exposure, including signature and key algorithm posture. +* Track TLS, VPN, IPsec, MACsec, and related network cryptography risk. +* Estimate remediation readiness and cost through the `system-readiness` transform. +* Drive dashboards for inventory, application reporting, certificate operations, and cost analysis. + +## What do I need to use this integration? + +* Elastic Agent enrolled in Fleet. +* Access to the host or file share where TYCHON Quantum Command writes scan output. +* File system permissions that allow Elastic Agent to read the output directory. +* A deployment decision for the Fleet namespace. The package supports any namespace; transforms read from `logs-tychon_quantum_command.tychon_pqc-*`. +* Enough Elasticsearch capacity for the raw source stream plus the transform destination indices. + +## How do I deploy this integration? + +### Agent-based deployment + +Install Elastic Agent on a host that can read the TYCHON Quantum Command output files. For Elastic Agent installation guidance, see the Elastic Agent [installation instructions](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html). + +### Set up steps in TYCHON Quantum Command + +1. Configure TYCHON Quantum Command to export scan results in NDJSON format. JSON-formatted records can also be ingested when they are emitted one record per event. +2. Choose a stable output location that Elastic Agent can read. +3. Ensure scan results are written with file permissions that allow the Elastic Agent service account to read them. +4. If you separate environments by namespace in Fleet, keep the TYCHON output pathing and the Elastic policy aligned with the intended namespace. +5. Preserve enough scan history on disk for Elastic Agent to pick up new files reliably. + +#### Vendor resources + +* [TYCHON Quantum Command product page](https://tychon.io/products/tychon/pqc-management-module/) +* [TYCHON Quantum Command portal](https://acdiscanner.tychon.io/) +* [TYCHON support portal](https://support.tychon.io/) +* [TYCHON contact page](https://tychon.io/products/tychon/pqc-management-module/#ContactUs) + +### Set up steps in Kibana + +1. Open **Integrations** and install **TYCHON Quantum Command**. +2. Add the integration to an Elastic Agent policy. +3. Set the Windows paths, Linux paths, and any additional custom paths that contain TYCHON output files. +4. Choose the target namespace for the integration policy. +5. Save and deploy the policy. +6. Confirm that documents are arriving in `logs-tychon_quantum_command.tychon_pqc-`. +7. Wait for the managed transforms to populate the destination indices. +8. Open the packaged dashboards to validate the transformed views. + +### Validation + +Use the following checks after deployment: + +* Confirm raw ingest by querying `logs-tychon_quantum_command.tychon_pqc-` for recent events. +* Confirm dataset routing by checking the `tychon.index` values present in the source stream. +* Confirm transform output by verifying documents appear in indices such as `tychon-pqc-inventory`, `tychon-pqc-certificates`, and `tychon-pqc-system-readiness`. +* Open the packaged dashboards and verify charts populate without missing data view errors. +* Review a few representative documents to confirm timestamps, observer metadata, and TYCHON-specific fields were parsed as expected. + + +## Troubleshooting + +* No data in the source stream: verify the file path settings, file permissions, and that TYCHON is actually writing new files. +* Data in the source stream but empty dashboards: verify transforms are running and that the relevant `tychon.index` values exist in the raw events. +* Expected namespace has no transformed data: verify documents are landing in the intended namespace and that transforms can read the shared source pattern `logs-tychon_quantum_command.tychon_pqc-*`. +* Parsing issues: inspect `error.message`, malformed JSON records, and any unexpected multiline output in the source files. +* Duplicate or stale transformed records: review the transform `latest.unique_key` behavior and verify the top-level `id` values remain stable across rescans. +* Certificate or readiness documents feel oversized: review large text fields such as PEM content and detailed reports before production retention policies are finalized. + +## Performance and scaling + +This package stores both the raw ingest stream and multiple transformed destination indices. Capacity planning should account for: + +* Raw source event volume from TYCHON scans. +* Transform frequency, sync delay, and destination index growth. +* Retention requirements for both source and transformed data. +* Dashboard workloads that query multiple destination indices. + +For broader scaling guidance, see Elastic's [Ingest Architectures](https://www.elastic.co/docs/manage-data/ingest/ingest-reference-architectures) documentation. + +## Reference + +### Inputs used + +These inputs can be used with this integration: + +
+filestream + +### Setup + +For more details about the Filestream input settings, see the [Filebeat filestream input documentation](https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-filestream). + +### Collecting logs with filestream + +Configure the input with one or more paths that point to TYCHON Quantum Command output files. + +Default package path variables: + +* Windows paths: + * `C:\Program Files\Tychon\*.ndjson` + * `C:\ProgramData\Tychon\*.ndjson` +* Linux paths: + * `/var/log/tychon/*.ndjson` + * `/opt/tychon/*.ndjson` +* Additional custom paths: + * Any extra directories where TYCHON scan exports are written. + +Optional package settings: + +* `preserve_original_event`: copies the original message to `event.original` before ingest processing. +* `tags`: appends custom tags to collected events. + +
+ +### API usage + +This integration does not call a TYCHON vendor API. It is a file-based integration that ingests TYCHON Quantum Command output written to disk. + +### Vendor documentation links + +* [TYCHON Quantum Command product page](https://tychon.io/products/tychon/pqc-management-module/) +* [TYCHON support portal](https://support.tychon.io/) +* [Elastic Agent installation](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html) +* [Elastic filestream input reference](https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-filestream) + +### Data streams + +#### `tychon_pqc` + +The `tychon_pqc` data stream receives TYCHON Quantum Command output files collected through the `filestream` input. Source events are stored in the namespace-specific stream `logs-tychon_quantum_command.tychon_pqc-` and then filtered by transforms using the `tychon.index` discriminator. + +This stream can contain multiple TYCHON record families in one place, including inventory, certificates, ciphers, applications, crypto libraries, readiness, keystores, VPN client findings, IPsec tunnel findings, MACsec findings, installed application data, browser extension data, archives, and other supporting scan artifacts. + +### Data streams using ILM policies + +This package does not define a custom package-level ILM policy in `docs/README.md`. Apply retention and lifecycle controls according to your deployment standards for both the raw source stream and the transform destination indices. +### Transforms used + +#### applications +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-applications + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| host.hostname | | keyword | +| host.id | | keyword | +| id | Tychon unique document identifier for the application record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.domain | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.os.build | | keyword | +| observer.os.family | | keyword | +| observer.os.kernel | | keyword | +| observer.os.name | | keyword | +| observer.os.platform | | keyword | +| observer.os.version | | keyword | +| observer.software_version | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.application.app_root | | keyword | +| tychon.application.connected_to_count | | long | +| tychon.application.crypto_library_count | | long | +| tychon.application.in_memory_cert_count | | long | +| tychon.application.keychain_identity_count | | long | +| tychon.application.keystore_count | | long | +| tychon.application.name | | keyword | +| tychon.application.path | | keyword | +| tychon.application.pid | | long | +| tychon.application.port_count | | long | +| tychon.application.private_key_count | | long | +| tychon.application.service_display_name | | keyword | +| tychon.application.service_name | | keyword | +| tychon.application.source | | keyword | +| tychon.index | | keyword | +| tychon.library.crypt32_pqc_status | | keyword | +| tychon.library.crypt32_version | | keyword | +| tychon.library.openssl_pqc_status | | keyword | +| tychon.library.openssl_version | | keyword | +| tychon.library.uses_crypt32 | | boolean | +| tychon.library.uses_openssl | | boolean | +| tychon.library.uses_windows_cng | | boolean | +| tychon.library.windows_cng_pqc_status | | keyword | +| tychon.library.windows_cng_version | | keyword | +| tychon.type | | keyword | + +#### archives +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-archives + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| archive.encryption.strength | | keyword | +| archive.encryption.type | | keyword | +| archive.format.version | | keyword | +| archive.type | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the archive record. | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### assets +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-assets + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| config.config_file | | keyword | +| config.property_key | | keyword | +| config.ref_type | | keyword | +| config.resolved_path | | keyword | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.name | | keyword | +| file.path | | keyword | +| id | Tychon unique document identifier for the asset record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| process.name | | keyword | +| process.path | | keyword | +| process.pid | | long | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### browser_exts +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-installed-browser-extensions + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the browser extension record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| package.description | | keyword | +| package.name | | keyword | +| package.version | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.browser_extension.browser | | keyword | +| tychon.browser_extension.extension_id | | keyword | +| tychon.browser_extension.permissions | | keyword | +| tychon.browser_extension.profile_path | | keyword | +| tychon.browser_extension.quantum_ready | | boolean | +| tychon.index | | keyword | +| tychon.scan_mode | | keyword | +| tychon.type | | keyword | + +#### certificates +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-certificates + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| certificate.basic_constraints.is_ca | | boolean | +| certificate.basic_constraints.max_path_len | | long | +| certificate.basic_constraints.max_path_len_zero | | boolean | +| certificate.file_details.attributes | | keyword | +| certificate.file_details.extension | | keyword | +| certificate.file_details.group | | keyword | +| certificate.file_details.md5_hash | | keyword | +| certificate.file_details.name | | keyword | +| certificate.file_details.owner | | keyword | +| certificate.file_details.path | | keyword | +| certificate.file_details.sha1_hash | | keyword | +| certificate.file_details.sha256_hash | | keyword | +| certificate.file_details.size | | long | +| certificate.is_csr | | boolean | +| certificate.is_private_key | | boolean | +| certificate.is_self_signed | | boolean | +| certificate.issuer | | keyword | +| certificate.issuer_common_name | | keyword | +| certificate.key_usage | | keyword | +| certificate.not_after | | date | +| certificate.not_before | | date | +| certificate.pqc_vulnerable | | boolean | +| certificate.raw_pem_certificate | | match_only_text | +| certificate.serial_number | | keyword | +| certificate.sha1_fingerprint | | keyword | +| certificate.sha256_fingerprint | | keyword | +| certificate.signature_algorithm | | keyword | +| certificate.source_file_path | | keyword | +| certificate.source_id | | keyword | +| certificate.subject | | keyword | +| certificate.subject_common_name | | keyword | +| certificate.subject_public_key_info.algorithm | | keyword | +| certificate.subject_public_key_info.bit_size | | long | +| certificate.subject_public_key_info.rsa_exponent | | long | +| certificate.subject_public_key_info.rsa_modulus_hex | | wildcard | +| certificate.universal_id | | keyword | +| certificate.validity.duration_days | | keyword | +| certificate.version | | long | +| crypto.key_algorithm | | keyword | +| crypto.key_size | | long | +| crypto.signature_algorithm | | keyword | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.extension | | keyword | +| file.group.name | | keyword | +| file.mtime | | date | +| file.name | | keyword | +| file.owner.name | | keyword | +| file.path | | keyword | +| file.permissions | | keyword | +| file.size | | long | +| hash.sha256_certificate | | keyword | +| id | Tychon unique document identifier for the certificate record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| omb.sig_tier | | keyword | +| pqc.vulnerable | | boolean | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | +| x509.is_valid | | boolean | +| x509.issuer.common_name | | keyword | +| x509.issuer.distinguished_name | | keyword | +| x509.public_key_algorithm | | keyword | +| x509.public_key_size | | long | +| x509.serial_number | | keyword | +| x509.signature_algorithm | | keyword | +| x509.subject.common_name | | keyword | +| x509.subject.distinguished_name | | keyword | +| x509.validity.not_after | | date | +| x509.validity.not_before | | date | +| x509.version_number | | long | + +#### ciphers +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-ciphers + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| error.message | | match_only_text | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| hash.sha1_certificate | | keyword | +| hash.sha256_certificate | | keyword | +| id | Tychon unique document identifier for the cipher record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| omb.additional_notes | | wildcard | +| omb.block_cipher_key_lengths | | keyword | +| omb.block_cipher_modes | | keyword | +| omb.block_ciphers | | keyword | +| omb.certifications | | keyword | +| omb.crqc_vulnerable_algos | | keyword | +| omb.dsa_algorithms | | keyword | +| omb.hash_algorithms | | keyword | +| omb.kem_algorithms | | keyword | +| omb.kex_ciphersuites | | keyword | +| omb.kex_protocols | | keyword | +| omb.mac_algorithms | | keyword | +| omb.module_name | | keyword | +| omb.operating_system | | keyword | +| omb.other_crypto_details | | keyword | +| omb.other_protocols | | keyword | +| omb.pqc_algos | | keyword | +| omb.software_package_name | | keyword | +| omb.software_package_version | | keyword | +| omb.symmetric_algos | | keyword | +| omb.vulnerability_status | | keyword | +| port.number | | long | +| port.protocol_detected | | keyword | +| port.status_overall | | keyword | +| process.command_line | | wildcard | +| process.executable | | keyword | +| process.executable_directory | | keyword | +| process.name | | keyword | +| process.pid | | long | +| process.username | | keyword | +| quantum_ready | | boolean | +| quantum_ready_cert | | boolean | +| quantum_ready_cipher | | boolean | +| quantum_ready_kx | | boolean | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| server.address | | keyword | +| server.ip | | ip | +| server.port | | long | +| service.name | | keyword | +| service.state | | keyword | +| target_host.address | | keyword | +| target_host.domain | | keyword | +| target_host.ip | | ip | +| target_host.ipv4 | | ip | +| tychon.cipher.config_source | | keyword | +| tychon.cipher.insecure_ciphers | | keyword | +| tychon.cipher.is_encrypted | | boolean | +| tychon.cipher.migration_priority | | keyword | +| tychon.cipher.port | | long | +| tychon.cipher.pqc_readiness | | keyword | +| tychon.cipher.pqc_vulnerable | | boolean | +| tychon.cipher.protocol | | keyword | +| tychon.cipher.quantum_risk | | keyword | +| tychon.cipher.recommended_action | | keyword | +| tychon.cipher.supported_ciphers | | keyword | +| tychon.crypto.cipher | | keyword | +| tychon.crypto.pqc_readiness | | keyword | +| tychon.crypto.pqc_vulnerable | | boolean | +| tychon.crypto.protocol | | keyword | +| tychon.crypto.quantum_risk | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | +| x509.issuer.common_name | | keyword | +| x509.issuer.distinguished_name | | keyword | +| x509.public_key_algorithm | | keyword | +| x509.public_key_size | | long | +| x509.serial_number | | keyword | +| x509.signature_algorithm | | keyword | +| x509.subject.common_name | | keyword | +| x509.subject.distinguished_name | | keyword | + +#### crypto_libs +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-crypto-libraries + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| id | Tychon unique document identifier for the crypto library record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| process.executable | | keyword | +| process.executable_directory | | keyword | +| process.name | | keyword | +| process.pid | | long | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.library.crypto_type | | keyword | +| tychon.library.name | | keyword | +| tychon.library.openssl_version | | keyword | +| tychon.library.pqc_status | | keyword | +| tychon.library.uses_openssl | | boolean | +| tychon.library.uses_windows_cng | | boolean | +| tychon.library.windows_cng_version | | keyword | +| tychon.type | | keyword | +| vulnerability.assessed_at | | date | +| vulnerability.is_vulnerable | | boolean | +| vulnerability.risk_level | | keyword | +| vulnerability.risk_reason | | keyword | + +#### inst_apps +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-installed-apps + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the installed application record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| package.description | | keyword | +| package.install_directory | | keyword | +| package.name | | keyword | +| package.path | | keyword | +| package.version | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.installed_app.crypto_library_count | | long | +| tychon.scan_mode | | keyword | +| tychon.type | | keyword | + +#### inventory +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-inventory + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| destination.domain | | keyword | +| destination.ip | | ip | +| destination.port | | long | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| host.architecture | | keyword | +| host.hostname | | keyword | +| host.id | | keyword | +| host.ip | | keyword | +| host.os_category | | keyword | +| host.os_pqc_tier | | keyword | +| id | Tychon unique document identifier for the inventory record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.database_schema_version | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.output_schema_version | | keyword | +| observer.tychon_client_id | | keyword | +| observer.type | | keyword | +| observer.vendor | | keyword | +| observer.version | | keyword | +| observer.windows_server_role | | keyword | +| omb.kex_primary | | keyword | +| omb.kex_primary_quantum_safe | | boolean | +| omb.kex_secondary | | keyword | +| omb.kex_tier | | keyword | +| omb.protocol_tier | | keyword | +| omb.sig_tier | | keyword | +| process.command_line | | wildcard | +| process.executable | | keyword | +| process.executable_directory | | keyword | +| process.name | | keyword | +| process.pid | | long | +| process.start | | date | +| process.user_name | | keyword | +| quantum_ready | | boolean | +| quantum_ready_cert | | boolean | +| quantum_ready_cipher | | boolean | +| quantum_ready_kx | | boolean | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| scan_type | | keyword | +| server.port | | long | +| server.protocol | | keyword | +| tls.duration_ms | | long | +| tls.insecure_cipher_count | | long | +| tls.insecure_ciphers | | keyword | +| tls.preferred_cipher | | keyword | +| tls.preferred_key_exchange | | keyword | +| tls.preferred_protocol | | keyword | +| tls.supported_key_exchange_count | | long | +| tls.supported_key_exchanges | | keyword | +| tls.supported_protocol_count | | long | +| tls.supported_protocols | | keyword | +| tls.total_probes | | long | +| tychon.index | | keyword | +| tychon.type | | keyword | +| x509.issuer_cn | | keyword | +| x509.key_bits | | long | +| x509.key_type | | keyword | +| x509.key_usage | | keyword | +| x509.not_after | | date | +| x509.not_before | | date | +| x509.serial_number | | keyword | +| x509.sha256_fingerprint | | keyword | +| x509.sig_algorithm | | keyword | +| x509.subject_cn | | keyword | + +#### ipsec_tnls +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-ipsec-tunnels + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| id | Tychon unique document identifier for the IPSec tunnel record. | keyword | +| ipsec_tunnel.active | | boolean | +| ipsec_tunnel.config_path | | keyword | +| ipsec_tunnel.detection_confidence | | keyword | +| ipsec_tunnel.detection_method | | keyword | +| ipsec_tunnel.first_detected | | date | +| ipsec_tunnel.implementation | | keyword | +| ipsec_tunnel.last_seen | | date | +| ipsec_tunnel.name | | keyword | +| ipsec_tunnel.source_id | | keyword | +| ipsec_tunnel.status | | keyword | +| ipsec_tunnel.version | | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| pqc.is_pqc_ready | | boolean | +| pqc.pqc_migration_status | | keyword | +| pqc.quantum_resistance | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| security.known_vulnerabilities | | keyword | +| security.perfect_forward_secrecy | | boolean | +| security.pqc_support | | boolean | +| security.pqc_vulnerable | | boolean | +| security.risk_level | | keyword | +| security.score | | long | +| security.security_score | | long | +| security.vulnerable | | boolean | +| security.weak_crypto | | boolean | +| security.weak_dh_group | | boolean | +| tunnel_details.auth_method | | keyword | +| tunnel_details.dh_group | | keyword | +| tunnel_details.encryption_algorithm | | keyword | +| tunnel_details.integrity_algorithm | | keyword | +| tunnel_details.mode | | keyword | +| tunnel_details.nat_traversal | | boolean | +| tunnel_details.perfect_forward_secrecy | | boolean | +| tunnel_details.protocol | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### keystores +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-keystores + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.name | | keyword | +| file.path | | keyword | +| id | Tychon unique document identifier for the keystore record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| keystore.accessible | | boolean | +| keystore.cert_count | | long | +| keystore.path | | keyword | +| keystore.requires_auth | | boolean | +| keystore.stats.certificate_types.ca | | long | +| keystore.stats.expired_certificates | | long | +| keystore.stats.key_algorithms.ECDSA | | long | +| keystore.stats.key_algorithms.RSA | | long | +| keystore.stats.pqc_vulnerable_certificates | | long | +| keystore.stats.vulnerable_certificates | | long | +| keystore.type | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### macsec +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-macsec + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.dataset | | keyword | +| event.ingested | | date | +| id | Tychon unique document identifier for the MACsec record. | keyword | +| macsec.cipher_suite | | keyword | +| macsec.detection_confidence | | keyword | +| macsec.detection_method | | keyword | +| macsec.implementation | | keyword | +| macsec.interface_name | | keyword | +| macsec.key_agreement_method | | keyword | +| macsec.parent_interface | | keyword | +| macsec.risk_level | | keyword | +| macsec.sci | | keyword | +| macsec.status | | keyword | +| macsec.validation_mode | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | + +#### readiness +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-system-readiness + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Timestamp when the readiness event occurred. | date | +| data_stream.dataset | Data stream dataset of the source event. | constant_keyword | +| data_stream.namespace | Data stream namespace of the source event. | constant_keyword | +| data_stream.type | Data stream type of the source event. | constant_keyword | +| ecs.version | ECS version of the transformed event. | keyword | +| error.message | Error message captured during readiness collection or processing. | match_only_text | +| event.action | Action captured for the readiness event. | keyword | +| event.category | Event category for the readiness event. | keyword | +| event.dataset | Event dataset of the source readiness record. | keyword | +| event.ingested | Timestamp when the event was ingested into Elasticsearch. | date | +| event.kind | Event kind for the readiness record. | keyword | +| id | Tychon unique document identifier for the system readiness record. | keyword | +| kerberos.config_source | Source of Kerberos encryption configuration. | keyword | +| kerberos.has_aes128 | Indicates whether AES128 Kerberos support is enabled. | boolean | +| kerberos.has_aes256 | Indicates whether AES256 Kerberos support is enabled. | boolean | +| kerberos.has_des | Indicates whether DES Kerberos support is enabled. | boolean | +| kerberos.has_rc4 | Indicates whether RC4 Kerberos support is enabled. | boolean | +| kerberos.is_explicitly_configured | Indicates whether Kerberos encryption settings are explicitly configured. | boolean | +| kerberos.is_quantum_safe | Indicates whether the Kerberos configuration is considered post-quantum safe. | boolean | +| kerberos.raw_bitmask | Windows Kerberos encryption type bitmask, when available. | long | +| kerberos.supported_types | Supported Kerberos encryption types as reported by the host. | keyword | +| observer.bigfix_client_installed | Indicates whether a BigFix client is installed on the observer host. | boolean | +| observer.bios_serial_number | BIOS serial number reported by the observer host. | keyword | +| observer.cpu_cores | Number of physical CPU cores reported by the observer host. | long | +| observer.cpu_logical_cores | Number of logical CPU cores reported by the observer host. | long | +| observer.cpu_model_name | CPU model name reported by the observer host. | keyword | +| observer.cpu_vendor_id | CPU vendor identifier reported by the observer host. | keyword | +| observer.current_user | Current user context used by the observer when scanning. | keyword | +| observer.domain | Domain associated with the observer host. | keyword | +| observer.fips_mode_enabled | Indicates whether FIPS mode is enabled on the observer host. | boolean | +| observer.hostname | Hostname of the observer host. | keyword | +| observer.id | Unique observer identifier. | keyword | +| observer.ip_addresses | IP addresses reported by the observer host. | keyword | +| observer.is_vdi_environment | Indicates whether the observer is running in a VDI environment. | boolean | +| observer.kernel_arch | Kernel architecture reported by the observer host. | keyword | +| observer.kernel_version | Kernel version reported by the observer host. | keyword | +| observer.machine_serial_number | Machine serial number reported by the observer host. | keyword | +| observer.organization | Organization associated with the observer host. | keyword | +| observer.os.build | Observer operating system build identifier. | keyword | +| observer.os.family | Observer operating system family. | keyword | +| observer.os.kernel | Observer operating system kernel string. | keyword | +| observer.os.name | Observer operating system name. | keyword | +| observer.os.platform | Observer operating system platform. | keyword | +| observer.os.version | Observer operating system version. | keyword | +| observer.platform_version | Platform-specific version string reported by the observer host. | keyword | +| observer.ram_used_percent | Percent of RAM in use on the observer host. | float | +| observer.software_version | Tychon software version on the observer host. | keyword | +| observer.system_uptime_seconds | System uptime in seconds on the observer host. | long | +| observer.total_ram_bytes | Total RAM bytes on the observer host. | long | +| observer.tychon_client_id | Tychon client identifier reported on Windows endpoints. | keyword | +| observer.user_gid | Current user group identifier on the observer host. | keyword | +| observer.user_home_dir | Home directory of the current user on the observer host. | keyword | +| observer.user_uid | Current user identifier on the observer host. | keyword | +| observer.vdi_identity_source | Source used to determine VDI identity. | keyword | +| observer.windows_server_role | Windows server role or workstation role of the observer host. | keyword | +| quantum_readiness.assessment_duration_ms | Duration of the readiness assessment in milliseconds. | long | +| quantum_readiness.assessment_id | Unique assessment identifier emitted by TQC. | keyword | +| quantum_readiness.assessment_type | Type of readiness assessment performed. | keyword | +| quantum_readiness.compliance.common_criteria | Indicates whether Common Criteria readiness is met. | boolean | +| quantum_readiness.compliance.compliance_notes | Compliance notes reported by the readiness assessment. | wildcard | +| quantum_readiness.compliance.fips_ready | Indicates whether FIPS readiness requirements are met. | boolean | +| quantum_readiness.compliance.nist_ready | Indicates whether NIST readiness requirements are met. | boolean | +| quantum_readiness.cost_analysis.labor_rate_used | Labor rate used for cost analysis. | float | +| quantum_readiness.cost_analysis.os_category | Operating system category used in cost analysis. | keyword | +| quantum_readiness.cost_analysis.os_hardware_cost_usd | Hardware cost for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_labor_cost_usd | Labor cost for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_labor_hours | Labor hours for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_license_cost_usd | License cost for the operating system upgrade path. | float | +| quantum_readiness.cost_analysis.os_tier | Operating system tier classification for cost analysis. | keyword | +| quantum_readiness.cost_analysis.os_total_cost_usd | Total operating system remediation cost. | float | +| quantum_readiness.cost_analysis.os_upgrade_target | Target operating system identified for remediation. | keyword | +| quantum_readiness.cost_analysis.total_cost_usd | Total estimated remediation cost. | float | +| quantum_readiness.cost_analysis.total_hardware_cost_usd | Total estimated hardware cost. | float | +| quantum_readiness.cost_analysis.total_labor_cost_usd | Total estimated labor cost. | float | +| quantum_readiness.cost_analysis.total_labor_hours | Total estimated labor hours. | float | +| quantum_readiness.cost_analysis.total_license_cost_usd | Total estimated license cost. | float | +| quantum_readiness.crypto_libraries.fips_mode | Indicates whether FIPS mode is enabled for system crypto libraries. | boolean | +| quantum_readiness.crypto_libraries.legacy_libraries_present | Indicates whether legacy crypto libraries were detected. | boolean | +| quantum_readiness.crypto_libraries.max_score | Maximum score available for crypto libraries. | long | +| quantum_readiness.crypto_libraries.openssl_max_score | Maximum score assigned to OpenSSL readiness. | long | +| quantum_readiness.crypto_libraries.openssl_score | OpenSSL readiness score. | long | +| quantum_readiness.crypto_libraries.openssl_version | OpenSSL version detected on the system. | keyword | +| quantum_readiness.crypto_libraries.oqs_provider | Indicates whether an OQS provider was detected. | boolean | +| quantum_readiness.crypto_libraries.pqc_support | Indicates whether post-quantum crypto support was detected. | boolean | +| quantum_readiness.crypto_libraries.system_crypto_max_score | Maximum score available for the system crypto stack. | long | +| quantum_readiness.crypto_libraries.system_crypto_score | Score assigned to the system crypto stack. | long | +| quantum_readiness.crypto_libraries.system_libraries | System crypto libraries detected during the assessment. | keyword | +| quantum_readiness.crypto_libraries.total_score | Total crypto library readiness score. | long | +| quantum_readiness.crypto_libraries.uses_openssl | Indicates whether OpenSSL was detected in the system crypto stack. | boolean | +| quantum_readiness.detailed_report | Markdown-formatted detailed readiness report. | match_only_text | +| quantum_readiness.hardware.architecture | Hardware architecture evaluated by the readiness assessment. | keyword | +| quantum_readiness.hardware.available_ram_gb | Available RAM in gigabytes. | float | +| quantum_readiness.hardware.base_frequency_ghz | Base CPU frequency in gigahertz. | float | +| quantum_readiness.hardware.cores | Number of CPU cores evaluated. | long | +| quantum_readiness.hardware.cpu_max_score | Maximum possible CPU score. | long | +| quantum_readiness.hardware.cpu_score | CPU score assigned by the assessment. | long | +| quantum_readiness.hardware.has_aes_ni | Indicates whether AES-NI instructions are available. | boolean | +| quantum_readiness.hardware.has_avx2 | Indicates whether AVX2 instructions are available. | boolean | +| quantum_readiness.hardware.has_hsm | Indicates whether a hardware security module is available. | boolean | +| quantum_readiness.hardware.has_neon | Indicates whether NEON instructions are available. | boolean | +| quantum_readiness.hardware.has_secure_boot | Indicates whether secure boot support is available. | boolean | +| quantum_readiness.hardware.has_tpm | Indicates whether TPM support is available. | boolean | +| quantum_readiness.hardware.instruction_sets | Instruction sets detected on the host. | keyword | +| quantum_readiness.hardware.logical_cores | Number of logical CPU cores evaluated. | long | +| quantum_readiness.hardware.max_score | Maximum hardware score. | long | +| quantum_readiness.hardware.memory_max_score | Maximum memory score. | long | +| quantum_readiness.hardware.memory_score | Memory score assigned by the assessment. | long | +| quantum_readiness.hardware.security_hw_max_score | Maximum security hardware score. | long | +| quantum_readiness.hardware.security_hw_score | Security hardware score assigned by the assessment. | long | +| quantum_readiness.hardware.total_ram_gb | Total RAM in gigabytes. | float | +| quantum_readiness.hardware.total_score | Total hardware readiness score. | long | +| quantum_readiness.hardware.tpm_version | TPM version detected on the host. | keyword | +| quantum_readiness.max_possible_score | Maximum possible score for the readiness assessment. | long | +| quantum_readiness.network.bandwidth_max_score | Maximum bandwidth score. | long | +| quantum_readiness.network.bandwidth_score | Bandwidth score assigned by the assessment. | long | +| quantum_readiness.network.estimated_bandwidth_mbps | Estimated network bandwidth in megabits per second. | long | +| quantum_readiness.network.ipv6_support | Indicates whether IPv6 support is available. | boolean | +| quantum_readiness.network.latency_ms | Estimated network latency in milliseconds. | long | +| quantum_readiness.network.max_score | Maximum network score. | long | +| quantum_readiness.network.modern_cipher_support | Indicates whether modern network ciphers are supported. | boolean | +| quantum_readiness.network.mtu | Network MTU detected during assessment. | long | +| quantum_readiness.network.protocol_max_score | Maximum network protocol score. | long | +| quantum_readiness.network.protocol_score | Network protocol score assigned by the assessment. | long | +| quantum_readiness.network.tls13_capable | Indicates whether TLS 1.3 capability is present. | boolean | +| quantum_readiness.network.total_score | Total network readiness score. | long | +| quantum_readiness.operating_system.build | Operating system build reported by the assessment. | keyword | +| quantum_readiness.operating_system.crypto_api_max_score | Maximum operating system crypto API score. | long | +| quantum_readiness.operating_system.crypto_api_score | Operating system crypto API score assigned by the assessment. | long | +| quantum_readiness.operating_system.crypto_framework | Native crypto framework detected on the operating system. | keyword | +| quantum_readiness.operating_system.family | Operating system family evaluated by the assessment. | keyword | +| quantum_readiness.operating_system.fips_mode_enabled | Indicates whether operating system FIPS mode is enabled. | boolean | +| quantum_readiness.operating_system.kernel_version | Kernel version evaluated by the assessment. | keyword | +| quantum_readiness.operating_system.max_score | Maximum operating system score. | long | +| quantum_readiness.operating_system.modern_crypto_api | Indicates whether a modern crypto API is available. | boolean | +| quantum_readiness.operating_system.native_pqc_support | Indicates whether native post-quantum support is available. | boolean | +| quantum_readiness.operating_system.os_version_max_score | Maximum operating system version score. | long | +| quantum_readiness.operating_system.os_version_score | Operating system version score assigned by the assessment. | long | +| quantum_readiness.operating_system.pqc_framework | Post-quantum framework detected on the operating system. | keyword | +| quantum_readiness.operating_system.symcrypt_present | Indicates whether SymCrypt is present. | boolean | +| quantum_readiness.operating_system.total_score | Total operating system readiness score. | long | +| quantum_readiness.operating_system.version | Operating system version evaluated by the assessment. | keyword | +| quantum_readiness.overall_score | Overall readiness score. | long | +| quantum_readiness.readiness_status | High-level readiness status returned by the assessment. | keyword | +| quantum_readiness.ready_timeline | Estimated timeline to reach readiness. | keyword | +| quantum_readiness.recommendations | Readiness recommendations summarized by TQC. | keyword | +| quantum_readiness.status_color | UI-oriented status color assigned by TQC. | keyword | +| quantum_readiness.system_classification.criticality_level | System criticality level assigned by TQC. | keyword | +| quantum_readiness.system_classification.detection_reason | Reason used to classify the system role and type. | keyword | +| quantum_readiness.system_classification.role | System role assigned by the readiness assessment. | keyword | +| quantum_readiness.system_classification.type | System type assigned by the readiness assessment. | keyword | +| quantum_readiness.timestamp | Native readiness timestamp emitted by TQC. | date | +| quantum_readiness.upgrade_pathway.action | Recommended remediation action. | keyword | +| quantum_readiness.upgrade_pathway.component | Component targeted by the remediation action. | keyword | +| quantum_readiness.upgrade_pathway.description | Description of the recommended remediation step. | keyword | +| quantum_readiness.upgrade_pathway.estimated_time_weeks | Estimated time in weeks for the remediation step. | long | +| quantum_readiness.upgrade_pathway.order | Ordered step number in the upgrade pathway. | long | +| quantum_readiness.upgrade_pathway.priority | Priority assigned to the remediation step. | keyword | +| scan.target_input | Original scan target input supplied to TQC. | keyword | +| scan.timestamp | Timestamp emitted by the scanner for this record. | date | +| scan.type | Scan mode used to collect the readiness record. | keyword | +| tags | Tags preserved on the transformed readiness document. | keyword | +| tychon.index | Tychon dataset discriminator used by the source event. | keyword | +| tychon.type | Tychon record type. | keyword | + +#### vpn_clients +* Source Index: logs-tychon_quantum_command.tychon_pqc-* +* Destination Index: tychon-pqc-vpn-clients + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | | date | +| event.action | | keyword | +| event.category | | keyword | +| event.dataset | | keyword | +| event.ingested | | date | +| event.kind | | keyword | +| file.path | | keyword | +| id | Tychon unique document identifier for the VPN client record. | keyword | +| kerberos.config_source | | keyword | +| kerberos.has_aes128 | | boolean | +| kerberos.has_aes256 | | boolean | +| kerberos.has_des | | boolean | +| kerberos.has_rc4 | | boolean | +| kerberos.is_quantum_safe | | boolean | +| kerberos.raw_bitmask | | long | +| kerberos.supported_types | | keyword | +| observer.hostname | | keyword | +| observer.id | | keyword | +| observer.tychon_client_id | | keyword | +| observer.windows_server_role | | keyword | +| scan.target_input | | keyword | +| scan.timestamp | | date | +| scan.type | | keyword | +| security.pqc_support | | boolean | +| security.pqc_vulnerable | | boolean | +| security.risk_level | | keyword | +| security.score | | long | +| security.security_score | | long | +| security.vulnerable | | boolean | +| security.weak_crypto | | boolean | +| service.name | | keyword | +| service.state | | keyword | +| tychon.index | | keyword | +| tychon.type | | keyword | +| vpn_client.active | | boolean | +| vpn_client.config_path | | keyword | +| vpn_client.detection_confidence | | keyword | +| vpn_client.detection_method | | keyword | +| vpn_client.executable_path | | keyword | +| vpn_client.first_detected | | date | +| vpn_client.install_path | | keyword | +| vpn_client.last_seen | | date | +| vpn_client.name | | keyword | +| vpn_client.service_name | | keyword | +| vpn_client.status | | keyword | +| vpn_client.vendor | | keyword | +| vpn_client.version | | keyword | +| vpn_config.auto_reconnect | | boolean | +| vpn_config.config_encrypted | | boolean | +| vpn_config.dns_leak_protection | | boolean | +| vpn_config.ipv6_leak_protection | | boolean | +| vpn_config.kill_switch | | boolean | +| vpn_config.logging_enabled | | boolean | +| vpn_config.split_tunneling | | boolean | diff --git a/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/base-fields.yml new file mode 100644 index 00000000000..91acb663aba --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the application record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/ecs.yml new file mode 100644 index 00000000000..d0587c5b305 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/ecs.yml @@ -0,0 +1,42 @@ +- name: '@timestamp' + type: date +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: host.hostname + type: keyword +- name: host.id + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: domain + type: keyword + - name: software_version + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword + - name: os + type: group + fields: + - name: build + type: keyword + - name: family + type: keyword + - name: kernel + type: keyword + - name: name + type: keyword + - name: platform + type: keyword + - name: version + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/fields.yml new file mode 100644 index 00000000000..186cc0d149b --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/applications/fields/fields.yml @@ -0,0 +1,55 @@ +- name: tychon + type: group + fields: + - name: application + type: group + fields: + - name: app_root + type: keyword + - name: connected_to_count + type: long + - name: crypto_library_count + type: long + - name: in_memory_cert_count + type: long + - name: keychain_identity_count + type: long + - name: keystore_count + type: long + - name: name + type: keyword + - name: path + type: keyword + - name: pid + type: long + - name: port_count + type: long + - name: private_key_count + type: long + - name: service_display_name + type: keyword + - name: service_name + type: keyword + - name: source + type: keyword + - name: library + type: group + fields: + - name: crypt32_pqc_status + type: keyword + - name: crypt32_version + type: keyword + - name: openssl_pqc_status + type: keyword + - name: openssl_version + type: keyword + - name: uses_crypt32 + type: boolean + - name: uses_openssl + type: boolean + - name: uses_windows_cng + type: boolean + - name: windows_cng_pqc_status + type: keyword + - name: windows_cng_version + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/applications/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/applications/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/applications/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/applications/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/applications/transform.yml new file mode 100644 index 00000000000..c6d28f2ec91 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/applications/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "applications" +dest: + index: tychon-pqc-applications +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/base-fields.yml new file mode 100644 index 00000000000..12e14ee4c3d --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/base-fields.yml @@ -0,0 +1,10 @@ +- name: id + description: Tychon unique document identifier for the archive record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/ecs.yml new file mode 100644 index 00000000000..5f17d34b1ad --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/ecs.yml @@ -0,0 +1,6 @@ +- name: '@timestamp' + type: date +- name: event.dataset + type: keyword +- name: event.ingested + type: date diff --git a/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/fields.yml new file mode 100644 index 00000000000..14a01825090 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/archives/fields/fields.yml @@ -0,0 +1,17 @@ +- name: archive + type: group + fields: + - name: encryption + type: group + fields: + - name: strength + type: keyword + - name: type + type: keyword + - name: format + type: group + fields: + - name: version + type: keyword + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/archives/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/archives/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/archives/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/archives/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/archives/transform.yml new file mode 100644 index 00000000000..8349209fc26 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/archives/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "archives" +dest: + index: tychon-pqc-archives +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/base-fields.yml new file mode 100644 index 00000000000..2dc32701a5b --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the asset record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/ecs.yml new file mode 100644 index 00000000000..d9c0dd8ee12 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/ecs.yml @@ -0,0 +1,39 @@ +- name: '@timestamp' + type: date +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: event.kind + type: keyword +- name: file + type: group + fields: + - name: name + type: keyword + - name: path + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: process + type: group + fields: + - name: name + type: keyword + - name: path + type: keyword + - name: pid + type: long diff --git a/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/fields.yml new file mode 100644 index 00000000000..566cff53ef1 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/assets/fields/fields.yml @@ -0,0 +1,11 @@ +- name: config + type: group + fields: + - name: config_file + type: keyword + - name: property_key + type: keyword + - name: ref_type + type: keyword + - name: resolved_path + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/assets/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/assets/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/assets/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/assets/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/assets/transform.yml new file mode 100644 index 00000000000..b5f6ac0db92 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/assets/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "assets" +dest: + index: tychon-pqc-assets +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/base-fields.yml new file mode 100644 index 00000000000..989a84c2c1e --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/base-fields.yml @@ -0,0 +1,40 @@ +- name: id + description: Tychon unique document identifier for the browser extension record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword + - name: scan_mode + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/ecs.yml new file mode 100644 index 00000000000..dbb9f2a3188 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/ecs.yml @@ -0,0 +1,28 @@ +- name: '@timestamp' + type: date +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: package + type: group + fields: + - name: description + type: keyword + - name: name + type: keyword + - name: version + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/fields.yml new file mode 100644 index 00000000000..8dc40de6962 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/fields/fields.yml @@ -0,0 +1,16 @@ +- name: tychon + type: group + fields: + - name: browser_extension + type: group + fields: + - name: browser + type: keyword + - name: extension_id + type: keyword + - name: permissions + type: keyword + - name: profile_path + type: keyword + - name: quantum_ready + type: boolean diff --git a/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/transform.yml new file mode 100644 index 00000000000..25c289a4a2f --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/browser_exts/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "installed-browser-extensions" +dest: + index: tychon-pqc-installed-browser-extensions +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/base-fields.yml new file mode 100644 index 00000000000..26df41e519a --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the certificate record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/ecs.yml new file mode 100644 index 00000000000..5669154af3e --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/ecs.yml @@ -0,0 +1,89 @@ +- name: '@timestamp' + type: date +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: event.kind + type: keyword +- name: file + type: group + fields: + - name: extension + type: keyword + - name: group + type: group + fields: + - name: name + type: keyword + - name: mtime + type: date + - name: name + type: keyword + - name: owner + type: group + fields: + - name: name + type: keyword + - name: path + type: keyword + - name: permissions + type: keyword + - name: size + type: long +- name: hash + type: group + fields: + - name: sha256_certificate + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: x509 + type: group + fields: + - name: is_valid + type: boolean + - name: issuer + type: group + fields: + - name: common_name + type: keyword + - name: distinguished_name + type: keyword + - name: public_key_algorithm + type: keyword + - name: public_key_size + type: long + - name: serial_number + type: keyword + - name: signature_algorithm + type: keyword + - name: subject + type: group + fields: + - name: common_name + type: keyword + - name: distinguished_name + type: keyword + - name: validity + type: group + fields: + - name: not_after + type: date + - name: not_before + type: date + - name: version_number + type: long diff --git a/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/fields.yml new file mode 100644 index 00000000000..d4b1b15a821 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/certificates/fields/fields.yml @@ -0,0 +1,110 @@ +- name: certificate + type: group + fields: + - name: is_csr + type: boolean + - name: is_private_key + type: boolean + - name: is_self_signed + type: boolean + - name: issuer + type: keyword + - name: issuer_common_name + type: keyword + - name: key_usage + type: keyword + - name: not_after + type: date + - name: not_before + type: date + - name: pqc_vulnerable + type: boolean + - name: raw_pem_certificate + type: match_only_text + - name: serial_number + type: keyword + - name: sha1_fingerprint + type: keyword + - name: sha256_fingerprint + type: keyword + - name: signature_algorithm + type: keyword + - name: source_file_path + type: keyword + - name: source_id + type: keyword + - name: subject + type: keyword + - name: subject_common_name + type: keyword + - name: universal_id + type: keyword + - name: validity + type: group + fields: + - name: duration_days + type: keyword + - name: version + type: long + - name: basic_constraints + type: group + fields: + - name: is_ca + type: boolean + - name: max_path_len + type: long + - name: max_path_len_zero + type: boolean + - name: file_details + type: group + fields: + - name: attributes + type: keyword + - name: extension + type: keyword + - name: group + type: keyword + - name: md5_hash + type: keyword + - name: name + type: keyword + - name: owner + type: keyword + - name: path + type: keyword + - name: sha1_hash + type: keyword + - name: sha256_hash + type: keyword + - name: size + type: long + - name: subject_public_key_info + type: group + fields: + - name: algorithm + type: keyword + - name: bit_size + type: long + - name: rsa_exponent + type: long + - name: rsa_modulus_hex + type: wildcard +- name: crypto + type: group + fields: + - name: key_algorithm + type: keyword + - name: key_size + type: long + - name: signature_algorithm + type: keyword +- name: omb + type: group + fields: + - name: sig_tier + type: keyword +- name: pqc + type: group + fields: + - name: vulnerable + type: boolean diff --git a/packages/tychon_quantum_command/elasticsearch/transform/certificates/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/certificates/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/certificates/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/certificates/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/certificates/transform.yml new file mode 100644 index 00000000000..8c4fac88cff --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/certificates/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "certificates" +dest: + index: tychon-pqc-certificates +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/base-fields.yml new file mode 100644 index 00000000000..d0946e7ec63 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the cipher record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/ecs.yml new file mode 100644 index 00000000000..e531319ec17 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/ecs.yml @@ -0,0 +1,95 @@ +- name: '@timestamp' + type: date +- name: error.message + type: match_only_text +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: hash + type: group + fields: + - name: sha1_certificate + type: keyword + - name: sha256_certificate + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: port + type: group + fields: + - name: number + type: long + - name: protocol_detected + type: keyword + - name: status_overall + type: keyword +- name: process + type: group + fields: + - name: command_line + type: wildcard + - name: executable + type: keyword + - name: executable_directory + type: keyword + - name: name + type: keyword + - name: pid + type: long + - name: username + type: keyword +- name: server + type: group + fields: + - name: address + type: keyword + - name: ip + type: ip + - name: port + type: long +- name: service + type: group + fields: + - name: name + type: keyword + - name: state + type: keyword +- name: x509 + type: group + fields: + - name: issuer + type: group + fields: + - name: common_name + type: keyword + - name: distinguished_name + type: keyword + - name: public_key_algorithm + type: keyword + - name: public_key_size + type: long + - name: serial_number + type: keyword + - name: signature_algorithm + type: keyword + - name: subject + type: group + fields: + - name: common_name + type: keyword + - name: distinguished_name + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/fields.yml new file mode 100644 index 00000000000..871df8aa72d --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/fields/fields.yml @@ -0,0 +1,105 @@ +- name: omb + type: group + fields: + - name: additional_notes + type: wildcard + - name: block_cipher_key_lengths + type: keyword + - name: block_cipher_modes + type: keyword + - name: block_ciphers + type: keyword + - name: certifications + type: keyword + - name: crqc_vulnerable_algos + type: keyword + - name: dsa_algorithms + type: keyword + - name: hash_algorithms + type: keyword + - name: kem_algorithms + type: keyword + - name: kex_ciphersuites + type: keyword + - name: kex_protocols + type: keyword + - name: mac_algorithms + type: keyword + - name: module_name + type: keyword + - name: operating_system + type: keyword + - name: other_crypto_details + type: keyword + - name: other_protocols + type: keyword + - name: pqc_algos + type: keyword + - name: software_package_name + type: keyword + - name: software_package_version + type: keyword + - name: symmetric_algos + type: keyword + - name: vulnerability_status + type: keyword +- name: quantum_ready + type: boolean +- name: quantum_ready_cert + type: boolean +- name: quantum_ready_cipher + type: boolean +- name: quantum_ready_kx + type: boolean +- name: target_host + type: group + fields: + - name: address + type: keyword + - name: domain + type: keyword + - name: ip + type: ip + - name: ipv4 + type: ip +- name: tychon + type: group + fields: + - name: cipher + type: group + fields: + - name: config_source + type: keyword + - name: insecure_ciphers + type: keyword + - name: is_encrypted + type: boolean + - name: migration_priority + type: keyword + - name: port + type: long + - name: pqc_readiness + type: keyword + - name: pqc_vulnerable + type: boolean + - name: protocol + type: keyword + - name: quantum_risk + type: keyword + - name: recommended_action + type: keyword + - name: supported_ciphers + type: keyword + - name: crypto + type: group + fields: + - name: cipher + type: keyword + - name: pqc_readiness + type: keyword + - name: pqc_vulnerable + type: boolean + - name: protocol + type: keyword + - name: quantum_risk + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ciphers/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ciphers/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/transform.yml new file mode 100644 index 00000000000..3c1c7e83246 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ciphers/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "ciphers" +dest: + index: tychon-pqc-ciphers +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/base-fields.yml new file mode 100644 index 00000000000..28973532a0f --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the crypto library record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/ecs.yml new file mode 100644 index 00000000000..52fe0461a89 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/ecs.yml @@ -0,0 +1,34 @@ +- name: '@timestamp' + type: date +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: event.kind + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: process + type: group + fields: + - name: executable + type: keyword + - name: executable_directory + type: keyword + - name: name + type: keyword + - name: pid + type: long diff --git a/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/fields.yml new file mode 100644 index 00000000000..22c97638bc4 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/fields/fields.yml @@ -0,0 +1,31 @@ +- name: tychon + type: group + fields: + - name: library + type: group + fields: + - name: crypto_type + type: keyword + - name: name + type: keyword + - name: openssl_version + type: keyword + - name: pqc_status + type: keyword + - name: uses_openssl + type: boolean + - name: uses_windows_cng + type: boolean + - name: windows_cng_version + type: keyword +- name: vulnerability + type: group + fields: + - name: assessed_at + type: date + - name: is_vulnerable + type: boolean + - name: risk_level + type: keyword + - name: risk_reason + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/transform.yml new file mode 100644 index 00000000000..8d8cacd2f40 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/crypto_libs/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "crypto-libraries" +dest: + index: tychon-pqc-crypto-libraries +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/base-fields.yml new file mode 100644 index 00000000000..c5ceb0e43b0 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/base-fields.yml @@ -0,0 +1,40 @@ +- name: id + description: Tychon unique document identifier for the installed application record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword + - name: scan_mode + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/ecs.yml new file mode 100644 index 00000000000..2ed65cb8663 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/ecs.yml @@ -0,0 +1,32 @@ +- name: '@timestamp' + type: date +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: package + type: group + fields: + - name: description + type: keyword + - name: install_directory + type: keyword + - name: name + type: keyword + - name: path + type: keyword + - name: version + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/fields.yml new file mode 100644 index 00000000000..2c9e49de0d0 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/fields/fields.yml @@ -0,0 +1,8 @@ +- name: tychon + type: group + fields: + - name: installed_app + type: group + fields: + - name: crypto_library_count + type: long diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/transform.yml new file mode 100644 index 00000000000..8763591b07b --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inst_apps/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "installed-apps" +dest: + index: tychon-pqc-installed-apps +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/base-fields.yml new file mode 100644 index 00000000000..7913a50e156 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/base-fields.yml @@ -0,0 +1,40 @@ +- name: id + description: Tychon unique document identifier for the inventory record. + type: keyword +- name: scan_type + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/ecs.yml new file mode 100644 index 00000000000..e2bf28970ff --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/ecs.yml @@ -0,0 +1,81 @@ +- name: '@timestamp' + type: date +- name: destination + type: group + fields: + - name: domain + type: keyword + - name: ip + type: ip + - name: port + type: long +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: event.kind + type: keyword +- name: host + type: group + fields: + - name: architecture + type: keyword + - name: hostname + type: keyword + - name: id + type: keyword + - name: ip + type: keyword + - name: os_category + type: keyword + - name: os_pqc_tier + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: database_schema_version + type: keyword + - name: output_schema_version + type: keyword + - name: type + type: keyword + - name: vendor + type: keyword + - name: version + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: process + type: group + fields: + - name: command_line + type: wildcard + - name: executable + type: keyword + - name: executable_directory + type: keyword + - name: name + type: keyword + - name: pid + type: long + - name: start + type: date + - name: user_name + type: keyword +- name: server + type: group + fields: + - name: port + type: long + - name: protocol + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/fields.yml new file mode 100644 index 00000000000..ff4a43947a5 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inventory/fields/fields.yml @@ -0,0 +1,71 @@ +- name: omb + type: group + fields: + - name: kex_primary + type: keyword + - name: kex_primary_quantum_safe + type: boolean + - name: kex_secondary + type: keyword + - name: kex_tier + type: keyword + - name: protocol_tier + type: keyword + - name: sig_tier + type: keyword +- name: quantum_ready + type: boolean +- name: quantum_ready_cert + type: boolean +- name: quantum_ready_cipher + type: boolean +- name: quantum_ready_kx + type: boolean +- name: tls + type: group + fields: + - name: duration_ms + type: long + - name: insecure_cipher_count + type: long + - name: insecure_ciphers + type: keyword + - name: preferred_cipher + type: keyword + - name: preferred_key_exchange + type: keyword + - name: preferred_protocol + type: keyword + - name: supported_key_exchange_count + type: long + - name: supported_key_exchanges + type: keyword + - name: supported_protocol_count + type: long + - name: supported_protocols + type: keyword + - name: total_probes + type: long +- name: x509 + type: group + fields: + - name: issuer_cn + type: keyword + - name: key_bits + type: long + - name: key_type + type: keyword + - name: key_usage + type: keyword + - name: not_after + type: date + - name: not_before + type: date + - name: serial_number + type: keyword + - name: sha256_fingerprint + type: keyword + - name: sig_algorithm + type: keyword + - name: subject_cn + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inventory/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/inventory/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inventory/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/inventory/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/inventory/transform.yml new file mode 100644 index 00000000000..3711f3d08d6 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/inventory/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "inventory" +dest: + index: tychon-pqc-inventory +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/base-fields.yml new file mode 100644 index 00000000000..fb9752836c4 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the IPSec tunnel record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/ecs.yml new file mode 100644 index 00000000000..463d8ed4806 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/ecs.yml @@ -0,0 +1,23 @@ +- name: '@timestamp' + type: date +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: event.kind + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/fields.yml new file mode 100644 index 00000000000..48ac78c8070 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/fields/fields.yml @@ -0,0 +1,76 @@ +- name: ipsec_tunnel + type: group + fields: + - name: active + type: boolean + - name: config_path + type: keyword + - name: detection_confidence + type: keyword + - name: detection_method + type: keyword + - name: first_detected + type: date + - name: implementation + type: keyword + - name: last_seen + type: date + - name: name + type: keyword + - name: source_id + type: keyword + - name: status + type: keyword + - name: version + type: keyword +- name: pqc + type: group + fields: + - name: is_pqc_ready + type: boolean + - name: pqc_migration_status + type: keyword + - name: quantum_resistance + type: keyword +- name: security + type: group + fields: + - name: known_vulnerabilities + type: keyword + - name: perfect_forward_secrecy + type: boolean + - name: pqc_support + type: boolean + - name: pqc_vulnerable + type: boolean + - name: risk_level + type: keyword + - name: score + type: long + - name: security_score + type: long + - name: vulnerable + type: boolean + - name: weak_crypto + type: boolean + - name: weak_dh_group + type: boolean +- name: tunnel_details + type: group + fields: + - name: auth_method + type: keyword + - name: dh_group + type: keyword + - name: encryption_algorithm + type: keyword + - name: integrity_algorithm + type: keyword + - name: mode + type: keyword + - name: nat_traversal + type: boolean + - name: perfect_forward_secrecy + type: boolean + - name: protocol + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/transform.yml new file mode 100644 index 00000000000..98058b690c0 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/ipsec_tnls/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "ipsec-tunnels" +dest: + index: tychon-pqc-ipsec-tunnels +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/base-fields.yml new file mode 100644 index 00000000000..ce6d815c7a0 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the keystore record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/ecs.yml new file mode 100644 index 00000000000..84eae2c5697 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/ecs.yml @@ -0,0 +1,30 @@ +- name: '@timestamp' + type: date +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: event.kind + type: keyword +- name: file + type: group + fields: + - name: name + type: keyword + - name: path + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/fields.yml new file mode 100644 index 00000000000..a5ddc72b2de --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/keystores/fields/fields.yml @@ -0,0 +1,34 @@ +- name: keystore + type: group + fields: + - name: accessible + type: boolean + - name: cert_count + type: long + - name: path + type: keyword + - name: requires_auth + type: boolean + - name: type + type: keyword + - name: stats + type: group + fields: + - name: expired_certificates + type: long + - name: pqc_vulnerable_certificates + type: long + - name: vulnerable_certificates + type: long + - name: certificate_types + type: group + fields: + - name: ca + type: long + - name: key_algorithms + type: group + fields: + - name: ECDSA + type: long + - name: RSA + type: long diff --git a/packages/tychon_quantum_command/elasticsearch/transform/keystores/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/keystores/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/keystores/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/keystores/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/keystores/transform.yml new file mode 100644 index 00000000000..4ce57e1481d --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/keystores/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "keystores" +dest: + index: tychon-pqc-keystores +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/base-fields.yml new file mode 100644 index 00000000000..31034afabd0 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/base-fields.yml @@ -0,0 +1,10 @@ +- name: id + description: Tychon unique document identifier for the MACsec record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/ecs.yml new file mode 100644 index 00000000000..5f17d34b1ad --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/ecs.yml @@ -0,0 +1,6 @@ +- name: '@timestamp' + type: date +- name: event.dataset + type: keyword +- name: event.ingested + type: date diff --git a/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/fields.yml new file mode 100644 index 00000000000..91bde41fcff --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/macsec/fields/fields.yml @@ -0,0 +1,25 @@ +- name: macsec + type: group + fields: + - name: cipher_suite + type: keyword + - name: detection_confidence + type: keyword + - name: detection_method + type: keyword + - name: implementation + type: keyword + - name: interface_name + type: keyword + - name: key_agreement_method + type: keyword + - name: parent_interface + type: keyword + - name: risk_level + type: keyword + - name: sci + type: keyword + - name: status + type: keyword + - name: validation_mode + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/macsec/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/macsec/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/macsec/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/macsec/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/macsec/transform.yml new file mode 100644 index 00000000000..edf09dc935e --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/macsec/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "macsec" +dest: + index: tychon-pqc-macsec +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/base-fields.yml new file mode 100644 index 00000000000..c9dcef040fb --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/base-fields.yml @@ -0,0 +1,54 @@ +- name: id + description: Tychon unique document identifier for the system readiness record. + type: keyword +- name: tychon + type: group + fields: + - name: index + description: Tychon dataset discriminator used by the source event. + type: keyword + - name: type + description: Tychon record type. + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + description: Source of Kerberos encryption configuration. + type: keyword + - name: has_aes128 + description: Indicates whether AES128 Kerberos support is enabled. + type: boolean + - name: has_aes256 + description: Indicates whether AES256 Kerberos support is enabled. + type: boolean + - name: has_des + description: Indicates whether DES Kerberos support is enabled. + type: boolean + - name: has_rc4 + description: Indicates whether RC4 Kerberos support is enabled. + type: boolean + - name: is_explicitly_configured + description: Indicates whether Kerberos encryption settings are explicitly configured. + type: boolean + - name: is_quantum_safe + description: Indicates whether the Kerberos configuration is considered post-quantum safe. + type: boolean + - name: raw_bitmask + description: Windows Kerberos encryption type bitmask, when available. + type: long + - name: supported_types + description: Supported Kerberos encryption types as reported by the host. + type: keyword +- name: scan + type: group + fields: + - name: target_input + description: Original scan target input supplied to TQC. + type: keyword + - name: timestamp + description: Timestamp emitted by the scanner for this record. + type: date + - name: type + description: Scan mode used to collect the readiness record. + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/ecs.yml new file mode 100644 index 00000000000..e73e0f53ca9 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/ecs.yml @@ -0,0 +1,144 @@ +- name: '@timestamp' + description: Timestamp when the readiness event occurred. + type: date +- name: data_stream.dataset + description: Data stream dataset of the source event. + type: constant_keyword +- name: data_stream.namespace + description: Data stream namespace of the source event. + type: constant_keyword +- name: data_stream.type + description: Data stream type of the source event. + type: constant_keyword +- name: ecs.version + description: ECS version of the transformed event. + type: keyword +- name: event.action + description: Action captured for the readiness event. + type: keyword +- name: event.category + description: Event category for the readiness event. + type: keyword +- name: event.dataset + description: Event dataset of the source readiness record. + type: keyword +- name: event.ingested + description: Timestamp when the event was ingested into Elasticsearch. + type: date +- name: event.kind + description: Event kind for the readiness record. + type: keyword +- name: error.message + description: Error message captured during readiness collection or processing. + type: match_only_text +- name: observer + type: group + fields: + - name: bigfix_client_installed + description: Indicates whether a BigFix client is installed on the observer host. + type: boolean + - name: bios_serial_number + description: BIOS serial number reported by the observer host. + type: keyword + - name: cpu_cores + description: Number of physical CPU cores reported by the observer host. + type: long + - name: cpu_logical_cores + description: Number of logical CPU cores reported by the observer host. + type: long + - name: cpu_model_name + description: CPU model name reported by the observer host. + type: keyword + - name: cpu_vendor_id + description: CPU vendor identifier reported by the observer host. + type: keyword + - name: current_user + description: Current user context used by the observer when scanning. + type: keyword + - name: domain + description: Domain associated with the observer host. + type: keyword + - name: fips_mode_enabled + description: Indicates whether FIPS mode is enabled on the observer host. + type: boolean + - name: hostname + description: Hostname of the observer host. + type: keyword + - name: id + description: Unique observer identifier. + type: keyword + - name: ip_addresses + description: IP addresses reported by the observer host. + type: keyword + - name: is_vdi_environment + description: Indicates whether the observer is running in a VDI environment. + type: boolean + - name: kernel_arch + description: Kernel architecture reported by the observer host. + type: keyword + - name: kernel_version + description: Kernel version reported by the observer host. + type: keyword + - name: machine_serial_number + description: Machine serial number reported by the observer host. + type: keyword + - name: organization + description: Organization associated with the observer host. + type: keyword + - name: platform_version + description: Platform-specific version string reported by the observer host. + type: keyword + - name: ram_used_percent + description: Percent of RAM in use on the observer host. + type: float + - name: software_version + description: Tychon software version on the observer host. + type: keyword + - name: system_uptime_seconds + description: System uptime in seconds on the observer host. + type: long + - name: total_ram_bytes + description: Total RAM bytes on the observer host. + type: long + - name: tychon_client_id + description: Tychon client identifier reported on Windows endpoints. + type: keyword + - name: user_gid + description: Current user group identifier on the observer host. + type: keyword + - name: user_home_dir + description: Home directory of the current user on the observer host. + type: keyword + - name: user_uid + description: Current user identifier on the observer host. + type: keyword + - name: vdi_identity_source + description: Source used to determine VDI identity. + type: keyword + - name: windows_server_role + description: Windows server role or workstation role of the observer host. + type: keyword + - name: os + type: group + fields: + - name: build + description: Observer operating system build identifier. + type: keyword + - name: family + description: Observer operating system family. + type: keyword + - name: kernel + description: Observer operating system kernel string. + type: keyword + - name: name + description: Observer operating system name. + type: keyword + - name: platform + description: Observer operating system platform. + type: keyword + - name: version + description: Observer operating system version. + type: keyword +- name: tags + description: Tags preserved on the transformed readiness document. + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/fields.yml new file mode 100644 index 00000000000..89935d5aaae --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/readiness/fields/fields.yml @@ -0,0 +1,351 @@ +- name: quantum_readiness + type: group + fields: + - name: assessment_duration_ms + description: Duration of the readiness assessment in milliseconds. + type: long + - name: assessment_id + description: Unique assessment identifier emitted by TQC. + type: keyword + - name: assessment_type + description: Type of readiness assessment performed. + type: keyword + - name: detailed_report + description: Markdown-formatted detailed readiness report. + type: match_only_text + - name: max_possible_score + description: Maximum possible score for the readiness assessment. + type: long + - name: overall_score + description: Overall readiness score. + type: long + - name: readiness_status + description: High-level readiness status returned by the assessment. + type: keyword + - name: ready_timeline + description: Estimated timeline to reach readiness. + type: keyword + - name: recommendations + description: Readiness recommendations summarized by TQC. + type: keyword + - name: status_color + description: UI-oriented status color assigned by TQC. + type: keyword + - name: timestamp + description: Native readiness timestamp emitted by TQC. + type: date + - name: compliance + type: group + fields: + - name: common_criteria + description: Indicates whether Common Criteria readiness is met. + type: boolean + - name: compliance_notes + description: Compliance notes reported by the readiness assessment. + type: wildcard + - name: fips_ready + description: Indicates whether FIPS readiness requirements are met. + type: boolean + - name: nist_ready + description: Indicates whether NIST readiness requirements are met. + type: boolean + - name: cost_analysis + type: group + fields: + - name: app_family + description: Application family reported by app-group readiness cost analysis records. + type: keyword + - name: hardware_cost_usd + description: Hardware remediation cost for an app-group readiness record. + type: float + - name: instance_count + description: Number of application instances represented by an app-group readiness record. + type: long + - name: labor_rate_used + description: Labor rate used for cost analysis. + type: float + - name: labor_cost_usd + description: Labor remediation cost for an app-group readiness record. + type: float + - name: license_cost_usd + description: License remediation cost for an app-group readiness record. + type: float + - name: os_category + description: Operating system category used in cost analysis. + type: keyword + - name: os_hardware_cost_usd + description: Hardware cost for the operating system upgrade path. + type: float + - name: os_labor_cost_usd + description: Labor cost for the operating system upgrade path. + type: float + - name: os_labor_hours + description: Labor hours for the operating system upgrade path. + type: float + - name: os_license_cost_usd + description: License cost for the operating system upgrade path. + type: float + - name: os_tier + description: Operating system tier classification for cost analysis. + type: keyword + - name: os_total_cost_usd + description: Total operating system remediation cost. + type: float + - name: os_upgrade_target + description: Target operating system identified for remediation. + type: keyword + - name: tier + description: App-group remediation tier used by cost analysis dashboards. + type: keyword + - name: total_cost_usd + description: Total estimated remediation cost. + type: float + - name: total_hardware_cost_usd + description: Total estimated hardware cost. + type: float + - name: total_labor_cost_usd + description: Total estimated labor cost. + type: float + - name: total_labor_hours + description: Total estimated labor hours. + type: float + - name: total_license_cost_usd + description: Total estimated license cost. + type: float + - name: crypto_libraries + type: group + fields: + - name: fips_mode + description: Indicates whether FIPS mode is enabled for system crypto libraries. + type: boolean + - name: legacy_libraries_present + description: Indicates whether legacy crypto libraries were detected. + type: boolean + - name: max_score + description: Maximum score available for crypto libraries. + type: long + - name: openssl_max_score + description: Maximum score assigned to OpenSSL readiness. + type: long + - name: openssl_score + description: OpenSSL readiness score. + type: long + - name: openssl_version + description: OpenSSL version detected on the system. + type: keyword + - name: oqs_provider + description: Indicates whether an OQS provider was detected. + type: boolean + - name: pqc_support + description: Indicates whether post-quantum crypto support was detected. + type: boolean + - name: system_crypto_max_score + description: Maximum score available for the system crypto stack. + type: long + - name: system_crypto_score + description: Score assigned to the system crypto stack. + type: long + - name: system_libraries + description: System crypto libraries detected during the assessment. + type: keyword + - name: total_score + description: Total crypto library readiness score. + type: long + - name: uses_openssl + description: Indicates whether OpenSSL was detected in the system crypto stack. + type: boolean + - name: hardware + type: group + fields: + - name: architecture + description: Hardware architecture evaluated by the readiness assessment. + type: keyword + - name: available_ram_gb + description: Available RAM in gigabytes. + type: float + - name: base_frequency_ghz + description: Base CPU frequency in gigahertz. + type: float + - name: cores + description: Number of CPU cores evaluated. + type: long + - name: cpu_max_score + description: Maximum possible CPU score. + type: long + - name: cpu_score + description: CPU score assigned by the assessment. + type: long + - name: has_aes_ni + description: Indicates whether AES-NI instructions are available. + type: boolean + - name: has_avx2 + description: Indicates whether AVX2 instructions are available. + type: boolean + - name: has_hsm + description: Indicates whether a hardware security module is available. + type: boolean + - name: has_neon + description: Indicates whether NEON instructions are available. + type: boolean + - name: has_secure_boot + description: Indicates whether secure boot support is available. + type: boolean + - name: has_tpm + description: Indicates whether TPM support is available. + type: boolean + - name: instruction_sets + description: Instruction sets detected on the host. + type: keyword + - name: logical_cores + description: Number of logical CPU cores evaluated. + type: long + - name: max_score + description: Maximum hardware score. + type: long + - name: memory_max_score + description: Maximum memory score. + type: long + - name: memory_score + description: Memory score assigned by the assessment. + type: long + - name: security_hw_max_score + description: Maximum security hardware score. + type: long + - name: security_hw_score + description: Security hardware score assigned by the assessment. + type: long + - name: total_ram_gb + description: Total RAM in gigabytes. + type: float + - name: total_score + description: Total hardware readiness score. + type: long + - name: tpm_version + description: TPM version detected on the host. + type: keyword + - name: network + type: group + fields: + - name: bandwidth_max_score + description: Maximum bandwidth score. + type: long + - name: bandwidth_score + description: Bandwidth score assigned by the assessment. + type: long + - name: estimated_bandwidth_mbps + description: Estimated network bandwidth in megabits per second. + type: long + - name: ipv6_support + description: Indicates whether IPv6 support is available. + type: boolean + - name: latency_ms + description: Estimated network latency in milliseconds. + type: long + - name: max_score + description: Maximum network score. + type: long + - name: modern_cipher_support + description: Indicates whether modern network ciphers are supported. + type: boolean + - name: mtu + description: Network MTU detected during assessment. + type: long + - name: protocol_max_score + description: Maximum network protocol score. + type: long + - name: protocol_score + description: Network protocol score assigned by the assessment. + type: long + - name: tls13_capable + description: Indicates whether TLS 1.3 capability is present. + type: boolean + - name: total_score + description: Total network readiness score. + type: long + - name: operating_system + type: group + fields: + - name: build + description: Operating system build reported by the assessment. + type: keyword + - name: crypto_api_max_score + description: Maximum operating system crypto API score. + type: long + - name: crypto_api_score + description: Operating system crypto API score assigned by the assessment. + type: long + - name: crypto_framework + description: Native crypto framework detected on the operating system. + type: keyword + - name: family + description: Operating system family evaluated by the assessment. + type: keyword + - name: fips_mode_enabled + description: Indicates whether operating system FIPS mode is enabled. + type: boolean + - name: kernel_version + description: Kernel version evaluated by the assessment. + type: keyword + - name: max_score + description: Maximum operating system score. + type: long + - name: modern_crypto_api + description: Indicates whether a modern crypto API is available. + type: boolean + - name: native_pqc_support + description: Indicates whether native post-quantum support is available. + type: boolean + - name: os_version_max_score + description: Maximum operating system version score. + type: long + - name: os_version_score + description: Operating system version score assigned by the assessment. + type: long + - name: pqc_framework + description: Post-quantum framework detected on the operating system. + type: keyword + - name: symcrypt_present + description: Indicates whether SymCrypt is present. + type: boolean + - name: total_score + description: Total operating system readiness score. + type: long + - name: version + description: Operating system version evaluated by the assessment. + type: keyword + - name: system_classification + type: group + fields: + - name: criticality_level + description: System criticality level assigned by TQC. + type: keyword + - name: detection_reason + description: Reason used to classify the system role and type. + type: keyword + - name: role + description: System role assigned by the readiness assessment. + type: keyword + - name: type + description: System type assigned by the readiness assessment. + type: keyword + - name: upgrade_pathway + type: group + fields: + - name: action + description: Recommended remediation action. + type: keyword + - name: component + description: Component targeted by the remediation action. + type: keyword + - name: description + description: Description of the recommended remediation step. + type: keyword + - name: estimated_time_weeks + description: Estimated time in weeks for the remediation step. + type: long + - name: order + description: Ordered step number in the upgrade pathway. + type: long + - name: priority + description: Priority assigned to the remediation step. + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/readiness/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/readiness/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/readiness/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/readiness/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/readiness/transform.yml new file mode 100644 index 00000000000..593ed0236e2 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/readiness/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "system-readiness" +dest: + index: tychon-pqc-system-readiness +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/base-fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/base-fields.yml new file mode 100644 index 00000000000..1fdbf93ef3a --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/base-fields.yml @@ -0,0 +1,38 @@ +- name: id + description: Tychon unique document identifier for the VPN client record. + type: keyword +- name: tychon + type: group + fields: + - name: index + type: keyword + - name: type + type: keyword +- name: kerberos + type: group + fields: + - name: config_source + type: keyword + - name: has_aes128 + type: boolean + - name: has_aes256 + type: boolean + - name: has_des + type: boolean + - name: has_rc4 + type: boolean + - name: is_quantum_safe + type: boolean + - name: raw_bitmask + type: long + - name: supported_types + type: keyword +- name: scan + type: group + fields: + - name: target_input + type: keyword + - name: timestamp + type: date + - name: type + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/ecs.yml b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/ecs.yml new file mode 100644 index 00000000000..d0e48a2b191 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/ecs.yml @@ -0,0 +1,32 @@ +- name: '@timestamp' + type: date +- name: event.action + type: keyword +- name: event.category + type: keyword +- name: event.dataset + type: keyword +- name: event.ingested + type: date +- name: event.kind + type: keyword +- name: file.path + type: keyword +- name: observer + type: group + fields: + - name: hostname + type: keyword + - name: id + type: keyword + - name: tychon_client_id + type: keyword + - name: windows_server_role + type: keyword +- name: service + type: group + fields: + - name: name + type: keyword + - name: state + type: keyword diff --git a/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/fields.yml b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/fields.yml new file mode 100644 index 00000000000..0b70e22ea2e --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/fields/fields.yml @@ -0,0 +1,63 @@ +- name: security + type: group + fields: + - name: pqc_support + type: boolean + - name: pqc_vulnerable + type: boolean + - name: risk_level + type: keyword + - name: score + type: long + - name: security_score + type: long + - name: vulnerable + type: boolean + - name: weak_crypto + type: boolean +- name: vpn_client + type: group + fields: + - name: active + type: boolean + - name: config_path + type: keyword + - name: detection_confidence + type: keyword + - name: detection_method + type: keyword + - name: executable_path + type: keyword + - name: first_detected + type: date + - name: install_path + type: keyword + - name: last_seen + type: date + - name: name + type: keyword + - name: service_name + type: keyword + - name: status + type: keyword + - name: vendor + type: keyword + - name: version + type: keyword +- name: vpn_config + type: group + fields: + - name: auto_reconnect + type: boolean + - name: config_encrypted + type: boolean + - name: dns_leak_protection + type: boolean + - name: ipv6_leak_protection + type: boolean + - name: kill_switch + type: boolean + - name: logging_enabled + type: boolean + - name: split_tunneling + type: boolean diff --git a/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/manifest.yml b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/manifest.yml new file mode 100644 index 00000000000..24e9e926793 --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/manifest.yml @@ -0,0 +1,11 @@ +start: true +destination_index_template: + mappings: + dynamic: true + dynamic_templates: + - strings_as_keyword: + match_mapping_type: string + mapping: + ignore_above: 1024 + type: keyword + date_detection: true diff --git a/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/transform.yml b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/transform.yml new file mode 100644 index 00000000000..58f20ec99fe --- /dev/null +++ b/packages/tychon_quantum_command/elasticsearch/transform/vpn_clients/transform.yml @@ -0,0 +1,21 @@ +source: + index: logs-tychon_quantum_command.tychon_pqc-* + query: + term: + "tychon.index": "vpn-clients" +dest: + index: tychon-pqc-vpn-clients +latest: + unique_key: + - observer.id + - id + sort: "@timestamp" +sync: + time: + field: "@timestamp" + delay: "60s" +frequency: "1m" +_meta: + fleet_transform_version: 1.0.4 + run_as_kibana_system: false + managed: true diff --git a/packages/tychon_quantum_command/img/TQC_Application_Connections_Topology.png b/packages/tychon_quantum_command/img/TQC_Application_Connections_Topology.png new file mode 100644 index 0000000000000000000000000000000000000000..0c88a5805345e96f01366510467468abe54f5838 GIT binary patch literal 765085 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

I$gDKpmGymnsGLn?AOD^fi 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

    PMBYOD@sEU(~BkTn< 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�=!Z2jF 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

    |5BGVIr_qAs! zN2$h0t!BJCg4X-oFlBX8zfjhhj+XzfnaOU4xSomtIK$wg*>fYmv02@bpDWop`6Y*z zwWs;=u7F6kWN15eeYKjU7mHMGuQt~1iN2PseOW~u>n}yO)FE;_2UyJsa0F%^uT=9$ z-lIYVjxw(9?RIT>bD$nIsavTvNT)hk)|j|*As$3WNhcRy+(_2yB-Kw#0Wk*THei4q zS(^TZxB1+CdfD!Q!aoe#KOyhoOor-sJr`5-hX2H!moL@jHxT&b{aSsU0h zA*CegW99gHT9yAND9p7r7AC37^~vjFOpnlEPhip6vIPr^DyqF)0y|x1@!Z@+e7KLT zIQ68H*5@JQLU!e+R2|n{??jm51wyedRO9;U#fiQnk6E~)#HhAnYOyVNjILgmd9nM& zg1_o>1F11LeV`jYjwHyYDgqL*ao)z=?dm-F7Ozcp8(-(=rt<9X0l4%>&a}2%UvbpP zOK%M`Mx1Kyn!KOxpID~aClyLfar&rE)^{NS9Z?K}MkI5`?-*_%I0`(4Tmz+Qu2%I2 z4B~HMMduuzk|>bBehC|+jGMFLGJ&DiKVFP%-}|q@QdH^-XVj_H1f{Ov4q=*y5e>GD zL3?i`&oSB99s0Ss);?R`?oBlOy}kNJX$>b1*Jr!q%2V~i`dpT3E%1CLKp@Ll<6y01 zcu(hGs*O2#E{pqT4e0Ac0KW%vT^lfmNwtO&%!-9Hm#!$KqX7arO%>{`8+hu^_Aiux z!4e{#@x-pILf!Fhz29+q@Z{q;Yc(d=Y!Grb1PGv(O4wr1Z(o|KIW8v?Vgt8YoAo1w zn+*4u#6_Sbb>30%Vy1@Olm2*h9hDOLn$oKx zWo}I(Uj)dW60NS_ta5mHyVA{XfLY=f7f#SHb$jg3M$Fc)-)r_kDl>z_^{;vfuprL4 z#T79LV?{Pd!2#~h7iPx-vx6rOJ>>z{-R!MxE2tz{q>B7&cK1I=6O>(Q zT4J4^#O%5-zc}Q9Do@zgqAHS>-fW9B;~b?b^ZC`raU7%2U5nZFKCH}Tqg9tU)8TbI zi?SADY|-Dx%BsN2h#o#7kB|98^*Oe(8^^?)qO2uR=E*@zm$1v6 zL@*TE?l|cwvnv}rWqpCWr|{H=6}HvyXpM)LPIy&aQ920`7{fo!I+`KOJgslnhk?x5-WJ5)vfP=+P_8?8x+GsK>K2LA z@M_I%dEC=aihWwhon}hD;Ab#kGMJ!QpmF_eF&A;d;l81DZiz|9n)XAQ#9%N%E%G60 zxj@>Y=Z=X@N#KmFF#KJiQG3t}CoyMJIIA_KCR26!W?RkUtA5tU&I?=9)knru6T<^G zm2?O3bW(S09-%ynSni;Ckajc#~RHEI&@Z!b>OKHGEDce^2))po=q_&{8K z%G$DYrXe$bI`J|=IOTLbvTm;e?o-C=T{ZCwmssL&{CPzjO34*- z5(V!eM-;8b8X_o@VE1x2)T}Qa?lkB^uGMVOX#47@vKUU$&Nt5I@B`lAF9Lh>MMJnZ z%pbP;GG{bpux;+d)eZT@^G%w`%L@YJs>AqhO~Pq{qu#sPqJ+iDn1QE1bf&a}vY1Ls zqhKbY_{o1Dh&;6Xl#=U_szWHwpYr|oWp+8+yxFq{PuJ2opZd2*18Uy`ZD5?tOm6%k@NVW9Hc2NB) z$^$#gqi_XKe#o2cx(WVz84JUFLx}1%%V0KdRg{0{!7lo%sk0UYW`@KVXFg$i#}E;z zfdlu5WWl%P619QWxLVC2AYPPH!qW%F&GG`e$tCn(kDVR=jXW5dcsFvT5_tqmXK&Q3 z8im;=N?s7Bwi(*6Bl=$jQ$TXMXihGtAblWpTx#eAGaE_@(llX>HJ!Bo5v+#o{GuX62g=zD|XVd1rNZsIdOy)04}uCcgFG z3f-gJlsR5f9V3?+5WC;i#ILrcZF+}S85!wxaw=~mw-~1#zFzJ~BR6{jzL}0b#tlt6 zspca?2Wif1txrd^#Cp>LLg4BgLeWJad%aB+W4dOPmB|QtbbnRboEeZOY|Wmco?Nf+ zMJXLR2+en^2xb0g^EVl$CxFE_-<#|1fEcYyV4f=&m!5u^QWdCr;GutC8nI6Cioce^ zs-cD7(D7>!^KywXWUh}rA%AL|V&K{2o)|{r=G~{D?_gykuWzB+06l{td3kiqv2*5T ztjeEqfhR-{o9~0iB^mtMy;~R4lyYhBy!s$eWw%<8@p`CYe)%YrX*jMRgfhuV^?32b z6>JEg)V!~a35a-Qtnas4Y~l1h;gl+%AyYv0OKuL1$7D*jg{CsQx}xna8HUm*-ya># zLr^^=#a6xH3d&T3ha1NTBGH?fJ~56;O@4EZw|MM5P;mjGU=FT9B0?SJ-4ne|g%ia?ry- z)!BKC3hc*HiS`%;hW!1lvCv7P22GE?iMIERRan5vwlZutac#4Et)Gou@*~mu?uZ%u z7U&ZQK24>u;dqY^x*>ptG5e@wJg>Xh-$yC4xdbdc;BSdlG%DHD#&w#|ZeOy4UR^QN zhWL^2xvIze)vwG@i{TRrhpdkvrxQD}c^lGa@Df>u*jH_U0EFl)7 zJx%6q2Jm51M`gX`Ax&`t=nv8J zs?zi9kgorTFRByAS7dME9F}Agf8BE*j&di&k`7htIgm?|s60SPZo1|q40CRW@g+S; zFrV5LPj=MLnI7kSITY=2Qtt8Tt|>#EQ17rpRqVEdq~&>-{k1W^I3?zaYP- zyH!YIkM8i|*_VXB4Z{nobKlawTrT9}SD*UPhOc>U^e88Ju4`RcBgGj#Jg^;%7#LKn z<})OTDULnvTnf2cQUQHFgW1n}EO>Sk^^y8)fyIBk08aAHTMp3o`m!{Zmabn46c7<$ zJcV;H06TU{d~p;ofLjE#m|2PEj5w&mYf7WYKda;C^ZmF{AQb4n;XM{qDT_V595|g} z7N}g4;|IW3fw@+SiP<2yfj=#ry61idN^K@Z%JDe$=rA$B8~*+Nf! z*tBjv&1|*-4bDCB!kad3pbg7);H`SM6Ts$g5;@SC#xByaO-*E8p9=1Hf-(5OH&`6y ziHUJ1ZroX*pm*)zQ1Q<5UkKY93#iWTp2rV%Z$1KS5~wcdhU0WN8NbH?2k)yKQ>yq^ z_dmXborol}q&4gO+!Rk8{G@#$!2FF&tCdSAnr5Ma@XXU3*ihR?hOa~lI*i&PVu>pn z>N4(!(gUO&)sRV1Ku?;Xj^8Nkw8Wtj$x)jV%*&XpDY=Onf>^(JRdpabuPRn9DrJtI0*UBxV z?y59yyYhXeCTskHw5)D*Vc=IouLW>TQcigMy$W6hP)*N_C3Kh}^3%)HR)7~Yz2d3) z#D{k9McnJ;27cV|-1=GJE1@!&!PmDh)IL6Gp~eW3c=_w|o80dUA99q;2XZX}rH`g^ z11j~}D$_w{oDjvu6uM5EJ?N8xA4K7)bZ_($(|&wX zYfd5xsieRnRTJZLyHb3u9{E|7?w%=yzOvA-4?g5kmwLCfWVF z9rsom-NSV?bT~_>gDQq}*qZCbMwLD#$J-D8XPkyR+FD~S<(=Hs7YDU9{uGK;_Bh-u zNY`Vg{}8+P9ybaZf5XvVSf{C(t3_`t^i#oa$XXex02%-eK|%EEFH zAgfuZ>9cO!qFE`d>DhCk&bUbi~=QTvP5#$HlkNTJbw_iTyqoLdN9YpxR(3 zr5%n;Ui8tV)UX!38u7rEd+3A4%qmH!tQ`FG^=*xl`JA)0Y)?zZ&rkg=9`X~2W+qA* z^Jklu%5=tjm+YSjdCU+UkyWGJ5xv8c6freY#LMA|wkM@hrmUjM&Bc&~{7K?Un*ha8XXM$L(iehBFV` zqrofcR^i>Z$EeO8{#X9XmojxA>S_SKzH{u!ix!shazLdiG5?^b`DpKAU+=$bt_6~; zFVcUBm46;uqb0E%qv6OonfeT+_Jq)w<)lPpo^SB8s9U>-(hS*V)@;a)*ViM++&!K# z4+O;rXE*$*P|@EI2ctLEBJLHhl8DMzIGU4`8PCK$LQL8sOwgr1RpeJL)k6FI`@Th0 zR}B>ENLLv#EvFb2AP-_~(I2csH%p3kbeTjYh;-#l58~Q&#F8CTT<9(4K18g(&_WzC%p#0eD0*sG3L7abalN!>FVyz$<2M^vD$`XIvOOQP(IVFJ}+OS zThJI+@oJknB({dWd#8R82kx#%B%2ipOr_r(@U+qSf-A;qa&vR7`4aO_hl>?krLkJpw?s;(?ig=@DcGT#avG*!Z;3hQFhP-~_g zXNQKH&ZzgKB1BfT#n0!y>_2js0lN!|^$d%PKS+5@-(!3zXdnvhCD>4-lPpBL>6{uU zwQ&{pU`Adm$g8aYCDkhBi+sc1<@h_+C#qKTbiZcH$x*b_`N+~^FwZ;z~D_N zONz%-NAkraREB6PE8(-*Q0}+oR5F!l$93A^pK2bTsIx5bZ@9&0~(cqFr2p z?X^O271O|}U#1u(lOzxu4{=VI&k9LROS|RG4R@xg5!yIOlj~k{Xymn9v2HdoW<$nu zU(^#xl8s{2#1CXm^{?S1gf|TYW)v?46xI}Z@{fv$E@%90m;aw9)ygLO&tX*yW`@#L z)(bYir`Dp|Dvbz-_)5Fcn8mNNMU(Q~;fSOTt)ZrlPeYBDyTiE5Ji$~S&Y3)&S2g3b z0*Tn45?;^y z9XZXOc62=KRS&%8$VUHM(Y!+x63hDubQY7=HLJI8U49_XW4zOLn+#vKfW~B`i-a#I zdvgNAA(N@g`Nvhgd^QwhzJa5mh$G(inD5fRCWz39zsW7nRLP>Q7kMkD3B>Ov3#uEb!5?6>IX zMSDI{0cTdPcn?~u#;Z5B6TiREL{9nfPxc!doVX@|$%{XXW-g}P&TiWiF<=rg{#>_z zVYkw=6jS4Mg`c+~7%;T{HmT#v1`Lx2gPJ&bx%$h|?L-Dd5Yb<0Jc(m%G2A#p|JHo| z!=r{V{dU@1DG`dQ!s|*OsuIghXy&Nc2J~$soR~FsuQGQQH z(jlYw#kG7Dd(SoyKMXwxlM2Xx^X=K&O2~;B%SQSyGCVY&@n>W3*D*tj`p~S7GJh;q zrwlG~xNAx(E!klzyBZGGdl99@K#2n6bJbr!PFLS% z1zYzw#QKfT5erjw2Qkjd9CvBX?a5OsGg$-xxVi$T{K%J>tk%DGDI8_G>x@PNPd;X$9RK->+r-9LTYA)cqY zZzLhGyzYmg?}xJFz@YvgJ!}?}9HwSwXQMJF5LIFoQsI^NH=*#ARdgP&;lN3K+(M1Pd_2-x^%4Le1)63H$=-0JA=0H7i-%dR0?kT05AgPRnaFU2PLmvt&xt zc=;Tp&>L+G=YUyUkN5JY%-_ayF@g0_&A%-85c53n&Sj@#W6R#om;W1L6Xx*m^^v<% z@EmwP-zzIWYuahFY(jNWvp>CcyXDKbWw{>hLv7wh+7%YPfl^L^lMT1G^{0{~hkQHn zN1Na7Mx!UWe$GS0bhB7i$B+)O&~o!fN_(+}@*4{t)`VNN_KOGzp2#J5j1=Xtdj)&d zAB!aG7d2c`@5G;LHE$PS(bXmN%x8Fn73Amt$jrQ(HS`*sm!*a)!E3O}S%ND+K7!D} zn>l^pPI%0YR~g_h3JraRqK7IxY5A-6W)r915%(P=9ObK4lU5)YR?U}m3ro#Y!u%QY zeU|2dK_3hC_+$)4Fc|{xbc1;ycUijJ)I~@;FN%#JJVZC$TB+y_^AK6@QW$-@VGD-d zyw2sZcoL5 z^@?Z9tzW+U(DsBS->|DsQlY$4ewH``jLG$5?)lPbd*&UjViG_~aZ1z293XBAW1MlE?TyI)Ryh7+Z&b`6HzM9g(tFDP)( zi8ZZ%eRPRCK6DO0B~Mhvpp>+q@i^j_BIkJP8T${R^3Tb!K=MrYAAv`E-?Ou`r7F|y zjjPo5$}bvs>x0rn%ve*Q4wCh~gpuugrwMMPCj|%hO$N`d2!*98Yqx~kKTE6Ft&HI6 z!1|WHXCdYf75()4sm_Gn++BH5=8kcV7??V>Z^4kIvb%|~eM5S%mL7gg_H|>tB=($J z`<1b*{#=bp1ecC=*Ew(|%L<(t-0U&%LclJJM$b>a#Fl-_ixzm!$2w{2mXGVANm3hU z)0_x792KL{U|bV5-hhk-rO*M$$NONMk1jt0_WMma9c6hkQkN<8*KINYr6Nk<@8m<8 z*zgGWH1ncXZ6F^VoRKlTM$Z`-Z1@tfAOa*=L-&6!v;~t2 zx^f@{k6zl6=3;bxY>ESmKK~TTelp`kC7Xp0LP~8>A(nVv7`qJGIgKQ~=6-J}oCH-E0yWR7A~`-;`GlhvN~Ns#&Nv5zGp znh!t?u$V-5i~y22w~w!n`ET6MBeA~p@IM4MU?EwihI15SUl?LoH5?IE&cjB z@)?NFDKsF-1)t2f__I6j>Xfsw>^@l4vL+R-zcR{SN1s%%tUi-%6kONClAtl0)fTbn zHS$Zgei+`z%v4Un;2TyJ=2fJX{jJ#kaM$H*uGcHgekX0K zi(ejVy_H(T2Y^$K|o!B^6LJ?7v71}l>O7Zreo zDS0IfKZn?h^+DZS=75G`g62P1y>TQ2qqSS3qi*agocq0MHqs?@_SUD@O)-qgZJ1Q7 ze%pR$a&Xnr#MkdD+m->DN<-3Q>#z){&0af&q}YsXiXjs_hS}4g95GvG97SsIBA2(v zx2845QU}%tNZyJe!E6v0XH%{eX=&O83&hyvx~K%+_SV|T*)y_==0Ll#4SD^6!p#)J z{bdygt#4u^B~_1@e}cJSYK`u^;ebCq?*y1)4zyblq7)#J8pvD2_#`^^I3 zylZoL;kaNm-HWZ*r`wrqwb;ylXwSjeHbUCIVW$vdv3y%nC{EC7f0cALi*>9WU4;^6 z#vrtCZk9PX?mDM#8k)JZw=;&UK3eCJxHM2MTD2W~O-_TNNFAE?Vl5ds|WF<+_$V@ zR#e7q8dj{ApCYU0SNKtX7aNu=wHenehpBB%E4R2=UHd!1-O&mL#01F1L)*q@Z8%>ZZGhitc5&?#!5l$iUYaVostZt=GfRekK?# z^AmsQGe#hNB@x$8i;Bj7!@OL$ef>hV9QsO2Ux2e}qS}UrkT8%{1x)d?tcoYMs{b-& z)s(om*rBMUC9-%ST|$IQdmYm0yjewi3%wz`pdbU3H6wW{Xsn=sGOrZl@BVZjAB-4% zuHO+R6Slcif6zzs;NC70;dSkGJb_)lB|Y7JNiD!hm60DT*_>@d82U>JP%MvW$h}qj z!$%E-SeeO02A~RHeIIkh#<%5s7GL|do4ss({EQv|AvcgKP^p=AC9608=$RX; zf*0+8ch%Sd*dzcurnc*so2%~C6pBoGKPIuL;ix}(W2*+vc)-nw`n53Ld1{c%k<_kK zgpYadMj6RlParMAhMo6;7J>t@gZXEqe0r(q(X=9U`{KQxi113i$R|yi!2T$Bz^K9F z>79)eo6Kk|nk~zX69KYBRL;V*cD)>sR8PbSk;Zz*k?p~e?U2>3M;F)XxTktMRCd-P zBMzFvFU3eOx6zqpb8%utP1E~!#6NlWU{;{lPtGxgJqs^f?5l1mGK^fgIW`MxIq0Cn z_L?dB;G%2n)MGhMER78uGys%(d{~sqLgy@eM!s_#58mHjIuAhT9UX;{cK19&A;pBd zCMz-6t-E&Vg_k~M)GPGuDK1J!H*KUNMqjP`KUeEtFoGhT!}k9F(rB&GotARtxSX7v zY&Hw6qG2;&9borDI9f>~l0yd!Zq1dm!yXH^jBavm3OPqpcSJ0mWEQ6MM0&;a)>$=( ztjE|)+g-N+)I<<^x1jTrgw@LdXylY8n+e63$2C8Xu-a??y4WFE{?G$3G_rVgW&QBr z=d=omTbsw$_)M$JiEzuYMaAV(tqCZcgTnb^`LF8}=!I+i2@yrcUEk>a6WM8KXqGPo z-Hzq8v_fZ-$(;9g3JqcVpHp&Au}C$YJ2SpTMIBcsq5PWr_^1b*-5^*9{3y`p7;saM zZIkY+)j2Zx-o@TvTfKhh<%{o8i(N3_GYZ`)5t@bvv9Z%mhWs&PU3Z?osbFKL3fdl)aSYDJBqE84$15VepM%m_V zi{v~dX)_Le7D3FhOr=i4_AU2Pi3EvFzg(dz_GPR`#)nnVb8EHa0uePDxt4E=G0+*l zyC5Dbs`=};$`Y1l0~V=DCepHl`<0x!J#RR2NG(9A!Gsi&wX?))ToFVjNe*m^gwiIN z6ofegmWwm#-lOM1w@fdK?Q-@=g1Gi@l+zWy0kZ35XdYc0nwQp>$nSk=Zp?FmQ_ORT zC&DYG>rJb2US6Tt$y;mZJ#C8Z2w={{hc(vw>}&TfUkNw-9LAJ0h6Qz;^~KWStwW{# z7%v{0!$n;?@6&^_Q&Y;sgdWG=SCLkBp|B%KXzNU(ew&Vri7%M5hOvLH^_{$}*cc!; z9v(U9b&)=5djG!#!e1ZRV14~(`qJqjNF}*CD)M5pHAqteRRX}~opZl@LCHj~kNm~@ zQ75LXJ#4N;Nl8=XO4{;#xhQh8%KZ|r>3YcB^I%s~S&0e#5y2Mev9sP4b>^%icZNPp zM;i$l205%x-ZGNB4DC>`KQBZH`)Z!ar{8n$3W+eRKOB@60NrmqiG7f5ZU53aD%e2( zc&qkxBg!9u^3=t}#lX-Ib#BkuTTEa1NowG|@l15CvDb%&;W$f$X$$3;i-=H+$<{_e2*H*>i+Mk-{yD`mTx6VER zAZ@gI19*OSUAzM{PCiAw!_>K8xP&pv`(fzqQ01|acT%N~^ETrlx~(6ywf0nBu#zL< zit2zSAYpY|XS!2V?O=iNaE~>5=9Cr2=vfziwh#zYgAsO~T*T*bv27EFA52bds$Nx* zzKx%I=@kRQixA9%cd<9^JpSS<@wA#=4ncslL65*K=o}m=baejfD*mqhx1akztBU9D z`gvJNQH?}l$_?6SR5o#;{Vo0n`0#Xr9>=Fmjyx0|Vevv9uKSxok~=Gs#L2(pjDIt3r=fKqYLu8zL*$+Vn35tYIK;Cf_SXhL^WMA zmKpVKI852Wc)lFK1Ol4{zJHXU)rjs(?OjZ7JWm$zJi%3~-DR16f2GLhfqu&X)Yk|$ zIZ)0Qb-QYK?jG@~{upZc9_S7=4z7pc_q+mLDg#O$6!SA+X+W7jae|P z=%Nt^a@`~rDt^DBB1M84OXrWAbU_-6}E2NlE57xuW|4(VvyLNoVdSHpB=^TE&pRD_R2-M48YN<2Kz6!vCgxI)|cK?jT9Ky-|WVe8%-@<#hOIZ?05Jsk$WSEM;AYAv&)JBQaq6wjg|_ zqSGi{p(VH)S=*_psr;t4t+mdqs(*5{FDrR_sbM71AXDRaXP=I$0*;CnYtrX%c&nGP zW!ioQA)|{~i;Ck6fWhGRi*WwWA6Kv<8Z72Um8%Z{sTx*Rm>G;N<(otKSMF^aA zAH{U~A}nd9=bzm$a~XKl17tte>;v0V3x5)sn#O77k-)$s#arwMcxLlx{lS1;@r2_OMRIPi|k8~ zxB?H~;}R8|U=3lN&`L6cqemL48Na zd>9vik0mKZ+86y9hG_#E>jHGpQ}J*WrEg-@Z}LP#cW}*2BAGPkFepSc)J@Bj31q^H zm1Cx-&6BQ0d0Ci{-W^xR&x0f)%{w=EwJA8>6m`2{IyYSPx!y{>hYLTW;VK|&>Gr74 z0tNv<1uNLQ4nu#8?P`7z|Bn}d?bj$!u3pvq-#5FXas0(;vZhmh^~%X{#U?|NVD#N0 z+btP4K$j3`BXL}K|JI=w$kR(7AHjsN@A_&I{3-rzh7Udq&pQ7zTP&bRtGCZX;QAb0 z)6RwTM4)tzVPcgtI-VCoTM?s6gM-&Wx;s<~g`vBGy;BwtmM9x-7W9^9}v)Rh~h$IVxP?B!%((XNTweY5Jlu#ZH zFHuUctDX*zhR{2q{EG7EbSRNW5zpE*t=Uhhde*F7;!RaBaVz4UGqjv8PApH^s#mnO z9E+NgdAK^rLhOD7RLvCpWV6n_PMuND6`zNbRZ3_&^mJ(si**eUxAuMoF^@#C%S2Gb zbbEH))*Q(TkbH%r8XN{H6{!}tqC>t9>D*trJs)mYi~vbE2MH4~s84nME)`}g=N zLP*TTb8z<0f9Liu%d9${CGvx=VX|tp97VZ zXsEctNJ~|_`Q(PdkTNX`%XNfVlNU3B`IOK}@SGa=+F@PA5efePfM&RPzefXxq!@&7 zU{MZY?v(r19!Z-d7!URw9%7$@*OB$9A|+3YVMw-hQzY4Pv-ViXezbLL4|+SXEe<;P zn#&ACiI@Jsx3r>x1nZSAqfkIcySiE$mS6sSJ+J{t%?IE;00Jmj{jNReDFf@Tohal4 z9%gzB<@H#@+T)JrbGupv_SRr*vq|0AdtVl zs0;^B{u3L2ct8ZHj7zA5c#-}kc3nwSLccMH51xE^{CY8b?fg#Mu}&Y$8_&jv z2V=VQjKAuPFYqjq75PvL2Hr9fL=cz%&5kzWOYqgM1|N zMDR?ypg~r!T6&j=HNs4plvSz8;20kYqM6ysY8&+|8Ds)1Qi>{EaYaeBwb|re9fWfiz z%&e6}GrqP#n{1<)h|)<+mk9-&?V!L+*YBX+xBc6m(8}HHf}3?!)7#6opC8lw>U|19K*so|=-I1@V z)Og|*hq|C|UsF(dq0Sc`0dTwnCyD$bD9_)GexA|*&AAWuDyg8r9oru_^e|kO!zXPB zEzpQb{IvySP{X3t2c66om?83g!)T`AeqeyKyoO@e6)>LMCUZ(3AZ4Av+~wZcarqha zs=Xh7U<13{YRX=0HJdZ8BswWH@BAgE%1%t+=|Wm8eT2VFSMty?5f(7)ud-&*lhTn34OOvyRN!<&12n ze!lrbhx4WoO+m_O#0gNIBJSBiBp4~SFbpPf>$S-?S(k|*d+CceOH&Fy`xnjfkCi0- zUtG$J<&Rs_>;GNsJOt*EK#}{2zekJeAw{_QF z^__pHQe0$P_`+JE!#co`&Yr>%Trj&b-QnS-`TKih$H68!%b9v%23hc6<(Viz zdx4;~J2RGThjxGQ-(m%|*|6$2>n!vGk<`%Qj?V*8qQhe!`}AZ&aL)%~8NqRa$H6B` zot!b?llBsj3!;9B*+n#G9>0ft40Z0$I}(Gn>0{ALe^ItXJa08E^Ovt_>&ThiKa85_ zKEAmb--0re+xl(5?tyiLs>83#kxSO0s4=s7nlP~X0Q20&N^MF%kv=QJhn;pY_d{Tj z=LPqMT7Q;tYWo8H3Gib~VBU9_(EuFFugYgHMWUl*1t?yHK83UUgVc5?6soh__5DUl z@djiiP>rmbkX-uySU;=AI-MF1C@mX~l>gF_vVcHaHxt$}KX-M3Fy3G4^ypi4tUH@` z;4U^@H0rw;Rm(29N1N=#mX+W|`thZ=q8!N^H8s-iD5k~E&n)cq_KZNn4Lsn8bv~Xj zuGuQ>Mv38fV$MqTv1U8q$Yi1f{mncb$%~pUsrgOKTtoPs2E_wmT2>1-1mZ3G-^pus6W)dR zB_Z~J>aLznnm94J>T$1}>&et14lS?*bc-OqyzCab(PYYzS1{8JTpDU_-k<##>cf>xv#dv!AuJ?ni|Gbq{(PFj?uiWx3SYLA?L7V0QJgO!j=T(4=}sd}!l(t|0H}Nx5Ao#NjSk z;s;2j=q~qgYRb)Rs|LY#9*FA!_!-RR0emS0Cynii&*#A6CVOLfJI7Po1W?|W}9CMDwo0OFFBEO{_ldx3NAF#y?l5gC@)~YiiEyVCcohFo@8^ zJ5gC9zAK%W?j|<~gSKaqOm{S^?b7dW+e1Tx@0tT{EIeRzTnEH01kjnlBw`9uhiGve z9^Ct!U0B#|TCs414ysEaqd!Zw!$4S#+gdAQdaowu%%MlZmV#a{I&X$PMfa3-p7xG& zKe<}8lCy35VH0R`?RiIh9hsP)Ytv6>erkZeohZZ{=WGgN+anQ?!;C@=6Dpee!exef zO73)WqxfzV6MUoCI{+t+>|{#n|Id5(_}_|e9EkpUp*d&I=SDfyzo5IoiMtQ?Q%~}` zjGlJg{`^Cu7e#>03orUgN8NS{$P23F<}zKS$h*X=>=(p}E=xO92Ny0yHZy{9v}4HJ z%XifCBys`==c_{KoDhWR6h=z>A{`%CzxTzn5Cd!b@JTtBo$n{rC+*Tr$7YDBI$t0H zKY`q5Tf5AYq7rxq`7H!gYbcX4@WT>>av5rkFE;Cx0UJk(T-DR0KvgVpfDk3*0jN_Y zC?}KWK<6|w#M?2K^Q77@*Xg1Mv7_d^fU)|z`NwCp*&jR9pOJxY&w0qx*DCn_e)$fK z{p|w4VQIebOMGi~^!yPROv54=KZ?!pF3hee|4UXnry3NwHUrrN`me6=G9#JrDfh2Y zKdU7>fQf$1%8wyj9_kjfa=rjC)o>Zl)T}+?yX5bo{m(1CV1gq9113s%7NvMzM*0pr z-1EZXgY*0yaHRof5D1;t;fe<&=8XW@6VF`)VdTk6G|L9 z3v}AVb1AVq*pgPnbAcG7oAe~nuQ?im-$$-V3J16(*#6KW@x~hGAuE!i}%gKVgKqF$(K>L|k2GQ%NB!k3y5Jzjf zV7JKfd@(FySt+H`jJ#BPDUftJeROsUo#68c_b}`F7F@LaqlfHZu-^%g4 zv*0Ks$(BX9c3!!w8(kiRbI%wpC#@5+8SgZmdkC2_1_8#7j*OrHCv@NwSukx>hdzqH zMUj*9^154$>pUr=X6?CI6M9ly`0fr|V)XYAs0o2~>w1gHZFzp{8K{|*tsa5Dd7JKe z`LfqA55qx~9eK}8&EmGkF&_3gSW^L#&04+cHXLM3bZ^pnvw{IJ+q$`4A}s1kgl8q$ z^}cI|llWmmi@;%^3 z;*_uJI%*Gp(flT{eHaSFr-jW^2_ZB-J2Lh3KBo=Oo#xM& zZapd>TMOi5owj*2wY<<_ZC%X2)_E$|aEh^t)x9*0e-Pu?XL7lZY>J3a#2FZAZMN}r z7`aClCn#{yF{M_U7RO12keYxs<(UQELF-&ZJ~7Ayrm->4llME-J9XY&mq8tY{=S{t zH<~7bQ9B4Dd*B`l(C!&(uG-BS{YRlIWip$J>Qw~dzG-wGO=XMV#uHTxjz|6M(h#;c zYSrS|^+^;Sj@(v<&m{UcI9;{R#9#*P?Z{qky-UY?wL|o_2JK$u7XQ|9NlLPH9VT#p z-s(Nt_xZb!|IhtLNBi%y?nUg|o;Xeh!wH`|m@%xnw|?nFfE>hw-4Js%v!POO&2Qbuv@o*5#caBQw8tAES{9{cJsvg&8dsiwv7dJYZibWuh?ZP3pbe zV}Y>(7X!+TMPQ>UdUvAl?$yDLr1qpsjwuBvnI9dUI%SZozXTiT2&m@26e!CMiZ2p6 z$-ZZX3S{*1d@po6Pdqi+Bw2NTa@eSY7@ClaRNW~Vz~n~yyma}5$K`r`lv4d8-fRqb z#{qXPfxQ(__|*A?!D-O)z<#N!_UBr)p)a*$_T5A!xB$DA|Fi=DFWTtMp)&b&JiyD{ zNdD>#r5$@}!T#w3oA)`!s1)*)kF(kDRqn`ei7$u5N&%yLV*|fyNH2-&!<9>FGL<9q zq;7#70!FmEL)9A&dZ|CTkFUJc{v4jo+kvbJ09i!TRhYRz3T5&Dd+=lWg2lc5^V8N5 zx_KIBA{@y9(f~-~ zv6{YrgWb0*q06aR(fh;ARrrVwaN4`2q{@a$46GdztV}>HHpP^bINn$xlnBKKQjQ%X z_MD4S8I?kZHVryaZ3sgBMk{68lWg6KMCQ7roE1{kQ87ws=?Xq=YQP(whx#2!%2(xcGLR4Tp>mGpbJje6@-_urUI5!0m`5D~+`iz8 zbX*ms=jn0Rle{@4bbHnTsw&bUqdIy@M_hemf(fWDmFXMj=yAuzR&Cv%rZh<99eHD0 zq?c2-7Obq()G>0Wf1ucOtN3 z9dCu!mEe%Q%?3f5(>Jat8*bp9gqAl{@*Cn%ewHvx(Vyz@7mO}P^<^_!9jJ7X(VJQX zt-vFT@Y==>RX`I0?tbWSzVw?it9L%0KHDnxWjp9tV*HGA8H&UOiqW0hTA^CntN5m7 zugo|^1^gte-rjzqR55$eN#ah;rVVIeU^3G=KU{|%x^~efOC2rFuBNg39n@tJvF~lD zU7m--4kr1@oxMb{EBH?ahbMonO!C3C%3_JNwc9MpuDfc46WW4{3YHqypa?Co?alb+>rXk}(Eji~bKYVbfr{5qVSw3-S6}XS0qvm5igx7|dTJ%w_M0dl zJ+MArlk=31t>l5;2T(jMn&pF1nRm$r8fvtaVGJPJ_k<~RTLC8WT-U@guKI5)xY0l~ zdN*nq&WGmVN)(D{`bZY+nT}|Xu=*Jh3l-dCNpFadS5fVbNxWwUn4x<$@oYxGJ6YvU z-;to~?p|7v*Yq4w{i)8AH7aN|+76j0SFC3-c2O#6ox56@*oYDgKlPUOI)213W~n=$ z&dqj^%MNr%Q$`<&td8Ylz3$>?&89Oeu1h(0I-Ro92GXDo&_fB(mIWH7Li@ZW^3avU z(}zy>HW|-Yef~Qx~X*fo`M+oMaNluhDNDxj{ieLS96m zjAV1bG;j0q)I(*F(AdG7B?c!4Fhq5-{P)n8R}{IU3>Jd zpe=UXX*>u{1+ghbZr-dUUkR%pF5B_f_$M>(obJ)=Y6j4kE=W>FPr>{g4<4~q^76wWHdFQyox!5?v=^};>kT`cc`sZ)Boan0tGVv_^oidj6_O#Y!5lDRe zJ=^ad7yR%0yuJ`e7xMLIi>GOAwvEA;SEh_nty_AX_NVg@CC~}7orI$Y+0Vn31UgQ- z5gqOeN&@F==_nv&^u`L{;J~SvCEKRb6imp{b7SNMzYNTj!CAh)I(BhD)duVvmyK>^ z$_@?=U6rC`OpIQJY~V=)7vURe={@dYKs>*$vCPQG0F+op$c<^os($Y-P_ygnb%el= z-gZd%zc4=K-=gCiAPXA+ng<#Qw^IQA?qh9AUw?1W12s%EJ8v)PsW+Jd(n?B%r7Ogky;@g1vEy}bN8-GvXp+!&b2~W zegf0LYMJRn5kl<8atwZN-KfhAD?q(m91|omkS0NsVk*y3EB5FOFf_abw?Y;T1n0>K zXl9idfZng*O06;iJhMJCT|3~ofmhp^M{0QNi|u=GA^|7}L<7o7B?kQ)*ni{rLaEX3 zf=<3ewRyqWVTT)yk0Ty)C4UDr0BD$fACy#<=G{u5 zGCvJThOvP-s|RW7l*x9AKVP_fY;mB%j$YnsnY$NO}Gj90i}hg3ZD5rZ3|)TqHU`DJ*GM0j6B!$pWkJ0I?ihK{vXYaP zgz>Z5W)b+CdXfa=d#2riV;X$YiDKh4Q$;C6Ew<Jgqq5|;%TJ0kvu)18OA&Na%! zbA|r$Mb8SULmp3&vgzHvj=8vAUplZl&{@ta zcSG~&6MQr#kyp29##=<>gl_0E(TPA~a=Tx?C7#Z$!vvA-TMGo}0qE!UJB4?Ykm?9u zpfy&Aw*cE8 z=ri)HG9?90845=Xx7pX_I1|#e4@}KA@Niy?+x{kZg7lir%HFr3Cu4G1gwbx9v^5yc zTo3dA22vg1p3a5C8@%OJ@}lVfknjs}#s>KN<_CnXDXI4t%MO*n{=cx zEr)g2ubz+z?_Mb=5j+YDvb{Z@58r~1HE#*C=)uA0w#Jk&;shhmGgLR}q!t@1%V z;&h90UtS60ut4Bs)J>Cjivp$6e4-i5^o_(4Snn~h_e-lkJLbnCeet9wV`{s7-F{)u zxq356TepjT%K;ZSKtY{LTcwna2S={qd)oGf2RKjRQUvCvRZRvs<9>P)&7{$O6A$0B zZd()ZX~cj=UwiR?i=+SfNSozfx_Ns0@+@h01NVnFdno*{_g8*iMdL5svYI-oGou`j zJ7hk1m@%Q?%aV6;MtjAR7x6{U!rZ?5CwVrEd5o9kmph#{?y@~srzA@RtfFXWoBU!4 z4SdvqgVkLMcCGIPRLmQ#%F(<%CQ;7y)AHcM|9AoRtV?ADC}$hBoc|wJZvjyn!~Wb`~wZU9+l zV5qa!87{C`t6({jGT&#j8i?5MBBQc~o;V(pDp;Gpi~9KZ`1)i}xP-oVPw}1#-Z%83 z%f$_QXi2W=tXF;IE4hpF?(0xrWF^cWkuQATd=T=7mxRyxuEREOym{5@9{~T}EqLk1 z^)YsTA3)%#iAPeG<+E2_d}P(rc>6l1PW_w{REV+~Y!Tf7{A$Y78~)>k_ja(x6rb-I z7e{y*e{B3R9qmC&7I0gBr&O#flVRZOP`~LAJLL@jI7T#Kbz`Z#cVb+VZ8m)PVJx1T z^aFmKJ!w8hF-Q|D&5g+*+H52-M%1RwxSG~=>{RRD1wJiDdH#~-Jv{t-Xr=t3 z8@CyEZHm#}Afk85n3&2U@~oKB`5C6DsJv%n-t`ygDhu54r7G5j{pejRD07u#wR)4b_O?#;6 z4%bTQ%^Ssc@jg@UdpF`zPenLk z{r(e6&J5Vjw|{e(FLHV8?Ci1*@?=u+5A4CDp{-?C-MaaVu716j*|3Kn#grZVrt7=^ zGRT9M!@t46ja8b+LV;n}Gw&;v+c}aBD0WRY2NHo#yJ$GBpoRuM5Nr*A-9<$u4GiLs^N=oZO{j=PzXPRRUV+YwwKgiI*&|$uwFtSk-&(f(xh2X z4a$c)BV00FY)qmG=`u*To-&@qV}4i7fs|cs3kAejwVrAY{nwmBRluGF#nZiEQzB!C6}7Sc$GYgT-D4f6_#W4~pg5Kn2- z+xRIhMdo0N{v@ZGOieqIn(~(jY2}kYIVp^!@^L)&L(TG05@ z+Bo*s&2BhN6bcA}ggu93bt!p2OPLf#KT;+xK4N@H_HszC-QIT@t;Sinwgu8XJk~mP z=A|c^hFO#Jgsw_iDIs}Q2WuM613S~7aYNzWd<2X83$x4#S5p?Ibo6m(g7Ooa<$gwq z3r?LIP&|A)B`}xHg9|2^vh<<-kgP3xpmc;vnPCl*96IRCyLyVEi@e}T;`ZlthZIm~ zN%ihyGHKMVN9XHSAK|ZZsd(MLx>|H+E^T2e?Pj~YZ1naqKRyoo%yaokf|uGmE{apCkB<&uWgj*yv1-i}d_S z1p=(ZpzJxmdsv=7v^hYQYQD~T5D@{P`5aTTl_oF@Zs(>TL_bMOOS8OHQLH>d zOur257L6hv1fVQRLj<^$&CN!9rQ5}>X&JSSq!5NR)Qi^2aeXu|2`; z;G>xbZ$oq{9|%j3Jc}F=#dZM-s&w_FX;LV8Jr<<%bwlK?1G-hQm^@ZW`D+RkB4$ES zXLp7VXqeqEB%#MYIdaH3ESBUbsYYbE3plPweQpo;4`G?YFgNc&iw`DmrhOcHZ&1O_ zqWVQaKv{6o2AoCXx48JBHN+JV6)6>Wtv@>;c>FdmW84(Hsan*0@eoAk3mW{+TZ9X! z2lC6W=eO-lgb)%R0_7Vo`k!_(rohgl)+U4>#9{s@1gw?m9hXRiEA=i7! z!WtVKu^L3>WhzqhG6|V)quZiN@vno*O-89WBSSDqA_G$~+bW8W{#F!Y;|wf?swa&H zY+h!tz+uvU@I^z=dzsA8`Htqpi#WVrV;6nglDM|Us<)}%VSqtzX@=%jO^TyA`{mD5 z^Adw?8>X+9>x6RY6dP9`E6jp3+Nhv2W*OPx8JId4b7-rVW zJ6GSnf&U&8)3G_23_a82%3NMv4yVn}$QXUGH@$v!H(PE9cXD#l)zh&U{n zu1SX;2m!-qVT-MjW1?e6pXWO#DNpM>h&m zPX5P=#->{_>vu|;;*+XCJHhWK;K~@1>OOW`EdLSs0}O85hzx0h6gyjeO`Br-=L<6K zH}d8K?;RwikQQl3fsa8teGrU@qC6oL2O*2{Pkj*@E!z_ch;JS@I2W>atyuC2l${M; z;*av`(DYX|Dw?8L)XTHNp~xbw1}1F^q{Em9F+uV$ikJL$ZP2X>NJ|!NulvJJj5kNr zG+shb%#jN4U-vpx7MWvhjx+gZ&D>>}n$n?C^2+8jS;Ip8lG&9VWZ!$ObciD*k2!XW zl9^fe-Az}p3e{QS6<$7aE|WJFGI#Bx?2@&ez5U6Jhr_`fR{C&n45=iPTD3VA)Zqk; zG2gLR@#h2}+LV`*^BLYU1h_5KM^e)0_;@ivLFoGWdMLovfk_{J{?2*Hm0V9%?AGAI zgeL8h0z6q4J6;d|=P@xc%MMdj6K;<^&$)I!^0^#{fYsojf&s)0!0gp}uB0H!MHCbi zddDm6=lip^!;dgnn!qu7@{V)sfL z11(ok29loeWLr7Nxx~1L+<6r92fqyYvNrKqQ-9?4A`l3R( z-^d2!pqSBnn2<{zIuDw-tT{`EG>59$m!R8p)7_#4h3Rv&;}x&T#sZ@AosGwG#A&qa z0}ZS}6{|0Fu2aaBLXi}ShQQ!FBqfUauqa6VMP0?-XMjobWyU36egRxybqOKk_Xy1} zS9edmP;rtf!r{8+_&E8v)PwpYLIK^2WvdUp^X2{Q$H+I8@jVHeIX*oUO zEjU`xd3#+V(>0xlQ&B+ z|F^WX5w9`GR_yB4n%x{7)UB-OK=Fo&gYz_fFupW`DWI)Qq!-ix^<1Ng;AnRN%_V9h zf9bR&Soie2{4FjnCN>ts^AJc|^2DNu`Dc26P%0)c8A((r{D)w2t^dDo_og-BBpc3V z`e=B4HDAZ1$odNH=&8MRuw&2ebPl6_)JSsb>wC_3aTrlY$CdlBMz{&9n=2|GeX}4= z3B5aO&g9M;vBOW5Z=^bhge3S=Wp9$ARf%=^ zDyxy|fgPD}{Zt}epq9ZB#E1#YLWGGZVn2iROKyY^<$j~FjKP+?Mre|-pdnUH7f{(t2sSbUpu-FyZo03wPph)69K}DtW1Q%cAY6=uMm5)eq z0oe7rg?EGHN6`qjZu+=UC`mqdNsp(>s}vyqkB*J)ygZl( zxlF&!2O8?{))uqVzS?2K9vz={z2fn6heRk-<`h_E{e7;+|@lc?A6&_ziCmc zjRaT2rq$>Iek9P(DrVQ)oqX4mZX7&LyN~NV5!s%1mrzyK%W1ajJ zJSGp!Zf?(TyrpzWF%(gG|sRM0-TLy`n(7moJ-_L9tv^ccsUZHT3 z&|LT0%i3&aWTtSMQjj#?ycd@F+7EP7wvCIX4KTFjywg!c;kypA)3OwAex*2;A*f#> zPrsm%`>|;=F!fBlNYmp2CQ`5K9)I}mjMSj)XT3)T`GO1i5B&y2F(FqBkot)TaXJ zktrxE!?p#Hc)1AtECLPJ$pG^(Vb$&A)y`ZsHJCJl00*5b91}Bh_AuxQMW`(f7OiTn z7QYz$;|xOx-9Y%_zwIUbiKJ=#PxJ?$dmMt+2lX0#e6rXyuT*cDmgwcE-C_PM8qzmN zXRD|5H;dxhYEKt6>5e3{<89_Bhbc477?iIWJp{R#?nuYf);e|9K8&e7#onT@PslZ! z(M~2$tqq#XYRTZlxTlB;k79$W>&?kDNwqy*!Ho2uQ`fEyhj(WKhz0XCAxXaUkBG*Z zFR(8gbK<55r|f*pGRiTh%spuh%ZQg#qpJ`ZSLguM;K| zanzO%s)mxPYNgGp5SIgo!%QU@3rq$yes)f(l9udAO^NK^$;qP>8qtkpF2oY0a2auw zl#obZwNN=fiIwI11GoqpFMFV@>Q-O9LM0vmjtQ>$Qk|yezzU3B=0-xKN7 z)Ki6N1pR&CjPmcP&oC|8SOpCjm{@}cg7U09U^#F^1a3Q-TpLmll*_?}SrhXfDHO|9 zJN4b<^yF!2D}VdkaNMkFQdSmJrXG|JJ^Njq(Lmu3mI-^X?DP4}i|X(tu^$oilvGG8 z-MI|5+)-eMX6bnzc}{(jXC1JC7a7mG(&{&_*GUdnB5t@qe`KRFfl8zixe0iy=u~-q3QErQ(iEOk?_O zs=MiHGjdd+Nuq@4WBtL^o;4wZIfpLY24Nk!f8)(VOke*U$W9yQDPWvFTLScDv?U0YL`Fx4 z7!MZ3 zc>8~0j;;rGt+u}E=N?gR zwb?i6pJF<$Ox7eMz^Na3-m;~KhjtHKaH*A4A7XDWkCr06ubdoYY053RV{PYL{RzxX zDdvRMODx4KN%lOG&1UL<=9Dx)H)*@ld!{sx)sO2c?=*h(Djck!Q<>sZkWr9@ZgwdM z03c4gw}47GLb7W$L~vB;JsQR$hHzQt6pDq&`+r*aGCy6>m*Zt4L{=RQfx9+uP*^hS zwM^4+JCH9p)?*mUZCniH7OcYMUOL-xxz|{Vp7msM?bq61%n^%e%R{#dyzD;cKnQ5x zsp<{!W$qCd3M$#xxOjc|R|&oGT<>ZOwG9I%5LPsJ0z;+~3ASLV37Ul*0lWOyeC$X$ zcP{lZ`GTB9)O^L`))7DO$GZ05dp2Y8frfcTtyFb9k*#V2(aJhm!M^adi)r2711Ay| z8d#^?5=pxHm!OW6mPYn|*wanUk4Hy-1I>YaLs?e_A(y^Za;HU%*W%44Vjcl%c-<;1t?_KZ-DlkVI4x3h7rX@bpeBJQiht#F`6-$caerl^;GL)1 z_2ayj+Xb?g+s}v9AB;HXa4XT2^m3|-gX^(}FZ2!|8w+k%AHW$Y;e=&-R-Ijcm^bgb z{u2iZ*So*@>rzYT0jqwR*R9!t6?-Fk2tgsOFv8;{n?A(KBrmC@7O|GceMI&!DMRnR0eJ}$M! z)|%bP&u$V7FAVW7Y4tocAM-&i(|Pz_@!zB*+Q&ca&mT_kg{kH*_4t6rv^!h0x`tfq zu>kz;OiuL6GP{;^TA@FA=*5cU*|7|^oX3+j$G#Yxtm(Lz6gwc~#!&dY>&BEJSLsUI zo)oG(OQR&9+^!%nDKLI;9XAe(VA_Duz0*-eLr8}cm$mBP9xQGlodF5AdFxY1@iE5) zqqtNA01hu7I1Dj@uL(lL`#;%tqZOCt6z0X`_1Vp(vi(T4z|JzoPrH6O@cr8dvcRO6 z_bE%bYcb3K0~wWT`nemEYAVC7@=?mej>?v(LB8TvxFayYKpl7WEo9u!2v@BgO1*hF z!&nUZTatN&Te|p0UiC|YhXkl-_&=#pV)ncHH+IOTD41_cq~Q!I?I`X%7)1;IpmeL{ zd44VPQoPDZ<8?nhw;yKS2#9yNTBg76eQ>R`J2w6+SMEhQbp1s^h9flw>+JIpxBpy+ z$C_Qkh?-V#Yt=T~orHM!#$2?Cofp6;m+sUgt|sJkl*NpciK;Ima>&TPN2iL!h>=qc zb;9+Zx>)bLdSrB`3_UC>awE-OmyzjBOc1JT2?S_uJA_Hc+vcNtA9cdzoG;~2UIoWpFw^DRl@U@8rqm|~jS9L| zuwq}|t6rU-&JY>8Y%ZTAo(#p9s*T;JNqm8H*6SM467`4c;k^pY%Hm2nKb(sUvTF91 zRq-60;pdGqQV-{7WVhz^WOnA~4C|(zBC*?s90J%XgoTyx@)7zYY1eT_Hv7p^%mrWy z((;eQ0zf$QFvIw)1;KwQyyh8|1}6~VC66TMDvMC{&xyOg&Ht613K8Ootuy2L5nJ3W z89rj{*sc7>qPtY*!yo?L>I$W)|3yX-TO{4O)Spd~7NaeIJ?^=qu3z&V&({CNFPq#C z1{x`~I3+#HnD^?no}fw|xG^1s7Nqr&)5gkdpfYcn^&!TPl`=;8vv`~3YLG;2b?{bB z{xrLGR;ea7kBR#jW4?yjj66L64Pj)2aN)K-z?_;=^8$_WS5)TYACpyj+AQO<23>Jj zT%+YEQ@x`4hPW*7;ly?_`Us0CH$o&+Y=b+lU<)XrK|>B1+sXib-goHUosD6Yte?&X-7+*<$Y|9853{ZoG9&A;_qaJJ=jn@+KYw*$Xc zi@~CCb2aP_g+Z1i?2cVwm|Zgz^pjCh9Nx$>qx%B zgLpNN3!VEaYmhTO)~;j6Wvs&c{4zq$2V@l|TCZ5pTG-?pk2!5~D7d8rQkPE-do2(+ zdrF@4TI&V+eL*D_2KZ5{FJ1u@z8XYZS#om!d(1ABh~TK>h*DWuk)}HKwhWCn`IwsD zZb&bR4JSkAD+naROhyX$wJFId(~Nfn`!hrnM%b z{){he-nyr+Z?NMKy_rx@`bil}Zg(@YnnB@F?}#%zbRQh{bc}n(r!nN$$;Gslrx2wgo43{GR=jASEg8*8d+Hhqs+dvQPvK33uVcX@m4=GsR=zaRFUH^fz@Qx8!5mnG| zKjapu<+U?fGJg)njMb=r!#vS;!_GShBilL%CMduE{KjpF{&coaCz_I07>o^%h?&WIW`sMD(KB)tjP{mGa6J;{moGiNk%>YHxP_7$zfqBPw&$t=O`}imWh;7>tifH(fu8%28n0>W>GrN2I^wHy&UiGi$ynkX=%EtjCSu|)7xDVkE4?0s( zNvcnXO?U@MrTHHinpubjF@))?4P_^yPJ63w?&={<*uIY*!0@SRvw0S6mM{5kcl!twZUfhGTzT67rfFi<5qtV z<&tfQ?)|xL{SHhb4(4l__1d7&-E>~HrNCN1;j-qS%05`ICH|T(bGkstlk$R>bherL zeun3MQw=VzSm90%E|1yI0L`D&FWjYz+6FM;_O^Fh>kjqT_v5)=DQ9qh*<9Q<<^I^G zT8mrO?Ra>)LRzwFK7qRrC*qD%uQb*V^rP*NS^i4Dddi)Da=#bma-4R;b2j2)zDIBZ zs~P*llPBqLWnOyk=G-qH*KPJ!jxiBTo}h1i@~<1}>&_h2y2G?Ik9(2+v!s+ao&DoD z81MmL8y5k)bY0ZIlqJQiau;(HZ`YJ>sq4y9T3&C6Cse{ssR`%a0^*;6iq497U3U!T zrwf`0+iIaLe85hj{j^yZ&Lczf)52YwLhH{!tl#)b!z;bPE&cOCzuOxaL`+zZJm;dEW zF%7JMy(<)huXJ6^7`)2QbqRBkvfCB?Uki*dt~aB5*L!D2$5*Og8E`Qn9ZNji;EwTe zS#(#=tnv@H^Zh}9$NFY{D&jw2b-qLrMc(ObuGR9}`K&kEN1y00pZhWy|K@J_>AA_4 zV~NPMPkTEfH%Quf%V>O^XljL8`=C!)spAUWUm+Y|TozIplrr2{sk<6;CbLyTPy)4b zA12DYmnt&gwuM1QXpaSzkBU1W?7Y+lZX!HQOfK3hUr`hc`rfU$y&fAdr#auAC4h>b z?+0|otSiomxTlH)F!L#Gd0^~K;|ZOKEm^+}p~skqz%-uX$TfSt>g_!+*vFcV{+`e= zms@%|x}bW~AhqFJSmbJSC_yv+DQZ#Gardv)f$cUv3EjgBpLSvTx0Tfo?C&ZaH3N|d z{$yn0pr?QD0&k}iwBrff?yqV$bb96{sh=Y%yFXCZ1Fy8@nlL-?{2eYlgU4SZicq22 zH1e~NRQ589Ehjo$-pB*)ezj_SL~uBSMj8SN!^f`f7bB&*{5_FG{ppYAIu|Dap9s^!L?yDbR>fL8@~U)aC({{J66ULrXaasLu8IUp5d=!FHvcOo^- z`H(b>#{62fny;47CfcltswBgt%(Njv>0W-HyRM^Z?7M@Z7aY3f4n6K2iM>yLtL#@u z`Soben=Vu%mr=iPWuA{-SXTli?0@=Keg79hle%SYsO`JFN?tdV&lu9o#z&U?Fc4}J zIF{uwB4TQavocA2PUrwl1*4ganqzA7+P|~kDE77x5N0PUJ_P_sJ zE2B1~Op46%4G4g6wpZ;7q~saAd|@hs8fTVOKozHNpiUMF(Z|=9W2NbT`5`>(1=%(V zTp*gLva&mSc^MK0EbL^aq3C|EDSlj*f%>boA4naOMig}HkbdY@s3i7R9|(Ie2%-Wc zVq3q}ReilT5}}}@Pb$gwzvmd6lT)n1n#Axkz~xXJD;Ii)FBvwfWi{{_x4)t&Kz;Qs zg?kb60k2AHYFpgqC1`V6*##~P>lK;cS%RtoQQ#${FUeard#U!d^(N(n=bdu@Y~c

    _RY!Tt6ZqwR4(~W*7vMt3n2p5^DrXv8pX~J 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%0AI@E=eK&AE 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 literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/img/TQC_Application_Detail.png b/packages/tychon_quantum_command/img/TQC_Application_Detail.png new file mode 100644 index 0000000000000000000000000000000000000000..e59ba1ba5e360d14720369b0ba85feaeaaa6247d GIT binary patch literal 387057 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�Nyt^T%jBRnKd`R-gVB7Q|qIl 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

    sZNCb{=&^2Lai`CA#B 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 z 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

      iz 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 RDt-j~Nr}memWdep{9ihd4aNWf literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/img/TQC_Certificate_Report.png b/packages/tychon_quantum_command/img/TQC_Certificate_Report.png new file mode 100644 index 0000000000000000000000000000000000000000..d17abba89013b1565f65a5015a4de991fbca9307 GIT binary patch literal 168169 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 KxSX1@c=LbS{CV2| literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/img/TQC_Cost_Analysis.png b/packages/tychon_quantum_command/img/TQC_Cost_Analysis.png new file mode 100644 index 0000000000000000000000000000000000000000..a9226c4ae2c48830c67ee2c046178c5b1ab1be21 GIT binary patch literal 132934 zcmeFZcTiK?`!8%c>ahSv1yQ6Nm0m>%NLP{GOF+7S^iC+!ZGfVHR4GEF1_%iVgwRnD zkQ!PNsgV{+fJhA_K;8|0>zVU==l*eL?%bKXW|FMEv-aN4ddlZ1YbCGrb=4Tou$?(_ z`4hi< zfe-ww=UbmKtd5+0$sklyZI89BMqxoq-#P0ptVtOsQLwbgJVMgx<$JuEAYQ!)a!Prb7E z>j>c3`xTp{JFi9z-K}2mD!@eOdKZG`G30;Sy*cNMF67W#7~}{+XOq`DLS@B4=wTbFt0g*GHfx= z?$p-kmw`<3NLa%>MYsm+t=ybxamQzWTC;fXelT&pY|`+e zeTRID43gSB0lAg}8AIG*oCPeyL?6yXJMbffOG}jCu=l@&g z+nGgRIm^W4$G7jM$REoS%@9f+*9rC*dF^_I<~1%8oKySrmUDh@;HGh`)ifwDvvx@k zyRWmi7S0#sv2Trz-?oPJ%)Tqx%cRck@s6yG{MiVVvZPaXbOySmH~Zd^x_4TMkv-!TIc_wjZ_Hts?>Xwtuxt0(x>qRJy&8VC#pK=UEEMjCRm5d7;A3TvCO_PX- zTdXqkn$4IrTFrIvOjuj!vZWxTS%$W)!jC6goVY~~u`$?lde=xUisfi7qE%k(Hh__C z`evxAk%zwB^>Rbi{&WTVf5=c=uV9O=TeufcEouyTr1&U5IpN}bohq5);$t;EG|Y@x^|y{e)9vN~r-Lv6XFr~Wi+8@$+2 zkl2DxaS=U0(*I}?Xa9{%J&_S&wu`}P5#tv;;%pj&w>+;kCri%WN8|4VLW+}?_tlxk z{VLZJOLFT;`*I@!VqWF!aW*eFl0u3@FuTo1rzOeSS_*q#^3I5xmU_QirJm!=?~ScY zNi;NC_Nwo&T=c87UWTpcYF2&3ABgFEqN!{Ctn6YCbR{SxQq=EqN!h+XbgbL|wej|t zmf??Y+^KiYx|NvYJwTJ zuzpP%4g-B`u>i@JI1{Guo3qfI!ZY0YdFgxMY9cKAda6{3)DL^!( zmhe6-RIYQ6X7aR~K4E&F&f@YcyLzIYj!;T0m{FmNZa10S8Nd;Yu3{tn^4aQJT{oLO zhu%n!xDw&gu3J?Pz~ozo9C9FOvc4)}=x3@N%O&Ty(f(~m?5d{0R=P8mblF|B@t!aq z$&~3LtMM1)x0EQUdA!~1z?f=veB9fK?*t!WKrCVHiZ@cGBX#X#Bb^Qs`9@ejk9y5?F}3G3O`hCN?|0;BgLgix5tGkgOW#bbCfu7a!ge-ggZd;`%0n25;el4` zxz3!8U+CvMxj>vJ`YP2LjmA5$?ldy;&#u014rDfgb!9DH3BC8aP;Agv!?5}m69Sj3 ze79%%BpXwge6F{kRO;%mQ3TNYrfJs*=s15ySLGzdhNd);}t!F0Rxj zZ*2Z9+aF*Jqf11@F=M}a5&Y};I8dz~xpDiAEI7STNmM=;tr}p`@{kK#ISrACn)1{HJ2*C(Bqf`_tLuL;Jvjse97w>obGRP3r4T9 z(5}ilVj0~^$1J7I$LrqXvhgQZ!6KE zI}LpZk^^f_6em{=J+rSJFAP3DVKRDD3_j_fH5))IkK>XPJi%Z}q6G_-7eeKa)eG={ zsAF6a37)NeGEoM%rpB8mF&FSMG%%wBYI`ltJdc8JhM^b6n!G`eAC`_x_%U17!|oZ*(7?ct^+ z{w(DWPf#+83Q-WhM|2w%w1(jwLa{5hZy@zyt#p`5KP7HpvvCEio+Ya}jJoIazS8o_ ze|Q0)TchoY?X@^|ZPojpOj*sWk%dlP8NSb;5q!flizuofOjuFg=&+!4=)6ubL_7^9 z47EF=GQ!zze@Gb{sGfhpjfwzYY_2iwfdtIQ6HHu9H%)@6uPK|(;|(LI>sR5M9(u0# zyR;Eh`y44p>48RaGt9P!XW_+EHOEkggdwh9VWf`sa)4Xl@k_;h&ljGXG9Mh)Q(cCe z*y=X-#5RY=W8HgepL25cYlzmHx)RqK2VU*Tnyv?LHWlY>YO~0zqbUf)*o)Q^AJ+mx zOi_?gI2IBC?vCoZsIC&oncvSeG%z{aB^kJ<5xL2gQ>Hrcp3wf(_42qe zx{+E{XVpzMLgRv0^3Z+};ZU{{CANO{pwg7);eD{q?$ljW87E9B+@iRLHFG$WlLNE_ zr)*fl7DvzzQ^PI2jqiqK4}5>OW@4rxS7T}s@2KUZD-b@)*_u@j35{0F%ti9G*Mbq( zv*a?BWa<)DcIF|Cfm#g9UF6EX@EaQhX|KQr47;q?AP79PX?AU7aYb}ewmPVGf7hom zAP9tGP;l?k@`QBYGZGGFBaIN@D*k|>Me+yj-RiLlH$EyAwh};#rut}eMP`lUED(CI zM9tWZ`T9IRz4DkP>H2nbXki!Ax4G2w)YYVGII`9%g|R)$T3ijzc&fx9zB=fs9ocLP z)408rF=~=gBY@goZ-=8rP5Yn(fFJnJTvNVOC z8NbMGUxP_oIZx7kQADrjT3ntu8k8bJsivGNS()_DkP|cMunm(0JTtbnq9V6AUV2V) zV0v0f`AXrVg-b-VOSh9)$G%75510PAkNF~7Xl!5O`E+wdm)xd!1hN;?RDzeCi-2ju zUnu&|m`iRAGtNrZo7(7vT5-4&+Dr0De0Qu=!#{}cDX-JBJ|B%Z;nXK5h*JT zHyp`tezSz+V6wXSzo6)+eln%5^Z$((rk%12UF#@x7u=I*AQma=}8vz>0&LUDF{6F>ghjpP4?P*32NJG`D6iI&MfNkYMp-N!m?^t$Y{YEx_` z+K@}5xy{``*Dr*jN?V)UZ_;laU1ht)sd2Op@{lj6G_#a%V*f!BZ#+J_1v>D;12sg+ z3CHDyWKZPdv$--&_jjeu-(SczQ5exQFQ`qzljg4o_~RezP-RqKCCZ*#K%_2oZK&=m zCMgD+VDyxbg@NN`&lcXLphz&=V8AzLNP4B@`)AZGesD$AcgP-oo2WvxsQgC{=v_olrF_ANwx$@LF&aK}yk(ub(v?77gtx+2hL8pM%2Y!Bt6;C~O6pG-m*g}o za1*z5{a@Qm&pg_wh&ZTu`HN(y6^Kb0{0F}Wm1W6kuA(c0`L^k~$M|oS- z4cABg-PRxVT(<6Wif?GrmdWx8sKKzyd98yS=+x3bdP0hHmhXF{)oXTU7dw2!Vv(4z zLd{mRneU9b(7l6;{R)ZA`|1;Ow|A@*#2t}S4PUS(i6%Wmb9wCxuh2@kH&>MAyG+CT zOV$$>`*h+qEok+iKV^;937tyl4*SiepO-m2Moi;Jx#O6_$o#SXnukbbIj(DH+}3PHaC*DmgM1ICLDf zNrJ)qJX-d`$Aj|XtMwjhwkWcdX(TD(;5Q1LHL9CO@bB{dsgqr+Y&#nys&5-phIsgk zeXpJ%kOx5{vC3oOG2(WHP(ho^z>F7aDlL!l!tQ%5MzR?lZO+{~zq3nP?m~0*f7_{D z45j^glgh3KYF8d5wY5)G;DWvRBT}og!La()*EGS z@q-E!$9E+uQ_`nK-j}_hq!TGy`du3iY%&}EVKPAtys=^T@?czVou2QKANvsG)Tli< zv^UYdCUl|ZFo0jpc>aO_qjBf`Knp=ErRSqtPJV>YYZ++@&3`V|)120-wL_Wz$hP$} ze#9DGAGM+Xs`->4kw7bS)t9q^^ED#rZQcD1Vo>bWyzoBCXlLU4`G?R;fg*KEB{b@` zGYy@pSZRsL+UV2IBn{^RIQ01K$-pusSPJ^NQVe05YV-M8xK)*o)9YOZtNn&OS3%OY zC`;|lp<4U8KRYPIqi1?z`V;95Mcb`;EcDSoMRuo)o_PhE2e||wj3xMWPK8Hk`+OYq zbD#KAWQQuWEbFJ;xea9$ohWe6>M!=lV`+9s*s&@VM3YJ%dKi5fu{Ye+=8(TqOda>U zi7i1UX>s;P1?90Qk;O&K%ay^`<%kh&G!{DTw#c6Q+v>7y&1h437)#g1nc*UMgN|B4 zs+*U4gKO2i7-9FNRy}F<9S8h)y>V!!b^|FAKJuA>T11!m`BH9sY&+(sVzL1&`AcB5 zZBg{(E5gztTR2TUM0Tad(9&{NK;t!DKq{|kgyCCe-EgIreQn!*u>epis5HNCY}h&c z$N2isB(}A~SJs(81tD@@@QI5qmACvp1#d*krajWgEr%uKwuJe+kD4nV`}EWyVxcII z168hDD3x8w&9h&v60rj^h~G*aQb$)8=h+JpOXdagb%_%;R(TlLy}uhcXhT}n`~fQ*#^T9py~y5tlEr~l4dMIJVX|*@}kOP zmLf%4=`Z7whf%^Ot}nc06tzHFiH3oGO!94hv4AdaUOiSI2sZBVexIAXTq$m;r{YZg zc}&Et>W-FUXucSsMmeF~$z{euX}&7|ZQS{il#F6m1!4U6B({Mz(-QU%<<4E_V@Q=1 zS(MqK$!e0ZPg4O zY8<&xX&|6O?rUUX8g#Q)#D3sKmRQ!tEE}9-ujgYn*$694kX1P$2&#+;HmA*LSlO)S z3Z9BCiQN3XIA+ut((gzwVUhDSM%!N1$im*#rn)^}-lM!AdTI6z*KIyBb6!}i$1vlG zp$>JJna!O^hSv;~S?opYp|jI->blz#GQrReSqCHA9s`~Z@Jg#NbnY7kA&h_42w1Z` zT2zO*STd{3-|2JULwydg(sV)JH&w=6PJWHy{c*`^+vq7Kygr(>8UKAUex69mTq~>YtnwLMaISXV%m@sxHVJ9F++!u`w%;{P)lX@vFF?_NxHl{Mf*RLhW5EySlB1b zWoR$~*pC+PJLO+2R7ksVk+Rn{%=7o^<2&m+JPHZXPRW@DeRo;oxEK9E(%^U8%SOE` zm$OP_)lngDj4Nq{CH8Q0!<3Q$y1hW)ra4at%J}hd4Oe8H4oL{IjtLSv`7T!nw#7H^ zzTH^2(}7{Z2D}|Zsqir^^UGd4SONHtX6e7wqf&aOlDYDlRjeG7;Y;d5)coQ|EiZ4x zRB2g*f@r5gO@g_k*!I~Tg`)2*>4J_E5OLRzb|X!Nrt!;)X*q8$@EVc6OCr95mGP7n zz7vFeDF$8F!FzIW@8qPnA!Vl1ot%rihT*=Sa?yTnB3Dd~CUHAB&ghw=P9{UzR6IFT zm)Wy4LB{%axGNo4#0$mE6tr6E!0XP_-pyuZ+B>>Rp;8afl3v{84F&V6&7xWpanZ?2 zfzNRrjYEx2V*bs`79QVHZ&BJ^wZe~S6rt;lv1$zN$d8wLto*NUeb9Z6V$Z2j6lz`< z<=Pv9#g+|yC=0ht4ixDL%PlUczhCUOKSP#pMakH_!e@l#Osp6>MqTJWv9rjyuidOi zM_Y3ZsfsMBpTc|fPe?)#xsk#3TE%>*mOsYJhPt(Mx+~^*BTs0+bUB6B6-a>bgkN&C znF_+X^bK47so{IpwSYGv!B@z>KI;o!c_lqvQ>tBLQLzLQPE)<8Hc_bC}4>X)BRr_W#Vmo?6a{&eck7E_+BbxZrMzy++ z1mQ2fV!K-UY1%#>y{3gUZEL90`-&c4@wy>$);d|DV5cc%9rc5BEwEPL`%jMF2ZqDy z{cexf&k&CD__j4?!Z%hgmbrC%`IInYmGv6ez4pjxj9-KmL_zKLcUY^{>n2WLJ*||T zKROo7+DHc+iZ6>E!_0K1kuq}GTNH|F2z|5UnN{xEXvw74wRaN7%)2CtP$h!e$Q8qY zPF4Gz4kOtc(zTB@2d*z~Z;OlARBNSt@iL;dH-YJag~d${0zzt!6-s^vgN++!;dO3f zqT?XXcb*G|T4$WgzMUj?suaoU_lt=QDMcw2N1Yd$$*2YU_?+rNoq43K|0Uc8>k?5m zgSGL$m*n^8`K%9P9D3mkm9|NHH|_t!xado8b7>~QvPd!TT*Das>0j!$@8>HpXD#<= zjvQ`%_s|plcM)Umrnwbmmhn(aDR47Z3!X&o%k4!w!bL1 z3xUo4`}~VSF@gwwzM9&uWL`44ze(*6D0tzUg8pLKmOVq+DeoSruv69D)L3Fp;ZnvW(wsTzRIkfWoLCtcH zw`1U)lLe7+l--{`QgA7pagnV`*)I4MW4jr-nZaVT^fI47zDv<=;)O1BeAk!Bf7!!C z*zo(`W-kqC>U>$eJsV=mNx9PA%FeOgl5MXG<%~yA}{f3#12Vz`zg!`tx|`5AE-4h z7MVdZ?I?<_1_Z~^-K%wLfRC_Rg}=`lsn9V)g_M{nw=g^~EPuALZHOL&WD2^)CB|nZ z*ffsDg4v|sQX=y-U!i}SN@_xt{*TjnqAhrOc97W47(at;rn|vM02|J zP;cIT&?|6U%?g+6k4mtcnm=~RYXuiYP$fMM_Gz|{7qB%dEl~{sJ4XksDN$itmv7P7 zJ&ejl*{PbN5tl!lAXg7~DR~%fGSZEw|AZ*~hdThe-l)2zR~94H53a`H`j?qN_#IH! z1|0S9Rk(S8{-$S`36ly@@3*ZcoxJe(uwt=HURvs>7Bp&X&8A&=r0_k7>S|1p4LV95 zm0bLsT2c{&a2#2A)V{EAwW^okno`Lf$&DOX^m*3IfOftqfP z!dvxQQCWsIU5lfwn?<}*u2OKp&X4r4at$gFDQ07rhl4Q1aRN?x8SXq-K{zY;9i=N_ zaz%*={f!SqRq~pDC7O6)FvS3?bvI`R3LdZDc!bxVzQ$c#2Rjz?;LVJo;#D<{?eI90 zthgZ#z47cooo@47FsnON`>5-7-@6Psvcx#arrgFSETDMKBP1*pJxZ%eHr>6n*Dyhp z9YN_1URu&ueSWD9>$val~G< zeD85xc92!|*^`Qh#6dlC>)qq&)U3q^4zSejTc)DNDe5XxD><1^sy0;qfm(FLzLL)E zLc{UOGri-hTh@%PjGAyvA{5}FxY@*eaZKyip z1JOD4%NNzpxj2M=@C+UxT0bHOSMx7Whxamxp70zCYYy0FtI-mT>84<6-Y7G;{Jst6 zD4{RY)UBzw#jj# zamuP4&oe=zOlQZn{M8fLLUWq(V1grwM@&Stk(>kR+M_nZ*x5zsTy9sy|!9emo z4qfv?Z4$wK59MEGdA+_f!S7x{{(?4(R}gg;8cn_t<9X2&>ELa=RSDaX(`2xwjbOOG_f@w=(zA; zoo|!$WjH3C{=A8828N(#ec(zu8z6+lbcRnvmSNU#1wky!=HdwNfypWVn4aHF(IIl? z%B?6f-zD=(A)0AyIG-w?g;KE%YwzH*NIF&s&*L@{O~*=Q^=&}k%|EJ)-X!gsWysOx z8b`NZ+Ic9xzCi2wnNH+t_Ad#)0y1fK%oKX}EP^lA8p!Ix>4t<*DN8;7(h?SEGh&Xn zw8BJSC)+_WP;Dec#$%9D_GXZB>X_f$sEzAN?uiWA^m?7d_RA)&&D18Px2Eu!09J>> z!XAua*W5mwhtQPYMx46fF^DJY;eyFc)I~~=`Azz%Fi@YeTXR~zO+~?=gri%4rZPjO zxE{m_Gq{AlI{yP_+;ZN8{xiCIhtdaB-w_c6&!+I0CO+maKdAWF4Pp=O8G$f3{fmPd{IE}u7@pdaJA zvS@n+H5g`sWAPFteQ;fAz+%t{+eT~(9bc89Qt{~F?Lhi8qB=3~~D-%nDu5@BxOgc#GtfPD}?n=ab zrCw+CNV;;E`4Y-`sq(~nM4##NhN}IGgPZOKQ=64)O0l697x&jp>9%FAOKBn4hdr#+ zpyr)BBuRhl`Py11m%ZIvj^|Q`#j|#UUYK|)z-0qNi;qqREFc4$jq3}YQhrYV?y*lw z<6ihujYs)e=icLdpZAo@eehGDT1mi&p9pnD$m(tWHl>P)5yo-=HQR zLXd>8Kq$ejeNh`*=M=XR>{BZ5p?5d&o|jS9hesUd>v^^JYu)fdt&Lf1)e>cA9MyKw zBXxsnI@VO>;}eA3r)6WXvF%2pIj@aCc)JW3GK_dpAjReP%A?{tJWOd%?G=biznMv@ zn4YHO=T>%vV~_A)S%Pojzqc$sft&Eee=2%S{K3)=?7Z<0^C!;Ba>zS~3d3d3xUpYP zSxZwO>_V+KGKxplLdoA}rp^r6&Pc|_O%x|QpTMPlFex$JdlA4X|Hx?CAnfD3u8Xgj zfA_e%bF4_GDvr5Pr=%0H@G?02o*uL z&cswph6M!mj_zn4F0I&yeiYa#VIKj z3BK@zcP|~`%pN6+gJ2{!F(u4SZF2g*ar_Bfm$Ws`t#K7E+^Bg0jXZKK!D_|=-Wb(9 zV6C6Gn3Z!kbwH`#DlJ#abtMW;+~X-OFK(1WOtUJT(J}o z+&5p!og~B#ZJrA63z;r-ZXZ@hHSB3Lg1EImlIQ3r5u=Ff}YD#d1`0cR&ks4Qw@tm zKPfq*E9o+_ZldL#U=!8Uir%zo{*nJ6v3HjL#toz4IAQWy;N+dmTFehkgH`+#l)5+$ z_5ZMMMSa|MOk`(IB9`L^9C1J)&)ZfhE zNWtI-TL}%rU7JxbKy}RDZab{G|4%xN0XhGh{(tqJXes~g{>j@{{ltlQz1K0YCv za{~^tzBA>unzhd3O_|&-(-{RUNj0;a-|v53&Nhy%xQhxiaeMrY_SYCbeqjlFlFF3Uq6@zE%Hr<_B_;><8b$ss1bjl}C#pRh zQi1dhhwkl4I!%Pu))^a&ACZQL|C^+L^^9LW?~suVBbHLP7V?IMm?5h?F8`WZl9l($!XA&Jt7;0?5S(nC9WN|NZ8Txc0XY{(pAoH1fO| z43g|G+y0MP-8o_Z{@46|jNJKuDE8kXJUsgUMX?XvZJ{BS3CAh?zCSocMw1=>x|{aM z6Sqr$s~$fd{n|+VyjRj^jb3aNU43Sw^pPmA1>ZEsA+tgL>*)?TIcJf)sEXJJbbCcZdPx+Tz83j`pA*wveLmI`b0=gZN}?g z4A6gi8TJc}YHqP(8j4cjc$fJWru5gHrT#R}#Qa#d)Wn0xf<5VN8hjGU&6XGvGc{>$ zcH`tJXKyYph`}}cCIzHMGc2PeQqt>3iAJ95yR+A;I>8G)W4>ylFw zGRE`oHIr)m5gQke9O1Xo{vF^zwLGC_lwC08%5xiovM7-rTlk3xkN&{SROg-?1=-XD zUX3$bYX&sg*o`e6O3~e(hwGvasfk&|5n^=k`j)%lSjT<02C#D&gXgdg-5uYh-(1=q zh7+u6N>!2?`2zqU@86~+j~w}-ndJN9jftN6Kn_E?rp9giSX!j1=|g2{6{gbSlhQ*s zmyFm(onWrGm%k~y_enE|E~EkM>D8Y&j3$Aua!eqWK1>Q+WQzqHuH{6-)?CZ-ukOU*0R~nG*_e-@V z2a*8Vu0sAJr^P7xo1rHH_8`cdx!XW0H%FKHV0V@q%ih9zFo+n^67GQdQ6}QL);~xM z#j+~{BRpg)^jhY$4ZHNB1@>pemH)A1oj>R@2b$Y_POYQpw(2UmsE;J(C%=#wY5Y@X zaQ{jf7gyZiLRIcuKJ%>KNKk8oPu~G7)bPGN5U%D1re7^N1@f6)w14zsQu5n0H%6^Q zM})d*cg8tL%>y$TR>_(17GgQJxk)K!Po=@ehj%Z#1W?{?TiAnY0WB{*?OV|t0f&+W zX0{!o-qC9ue>$&f;hQ3$BG9soJf_s%o6%YhEt9ty(r%fg*S0Eo^RGP0T}fMeYFHuh zPydOpDpsCmmfOphaX0<4crGl2l5NQ6)e|!P!M9RNi2{VNKgdrG0z>^$0dbee#87!l zA<|C$9%x3&#%&4c%ubqb!&;-2xHFX#^Ti5TIDZziPUSAxFS?R9RL!@86gFMR4#-@O zRhbOb^>KC+b7Ih5#eA}i`)%UHLhJ^y@6YWaswF|{_7Vr z5nKwqZv?9r!9I%C;-o~AFLgAS4^cm1N|$$W*z97r?V)6!xZ!e{;`n_+s%0!o0U?-g za<#WZrryEaD9@g;324aB0oaN=LN7ce4` zrp__rnMV9qgg>E6!Z|M%&a0bh7(RaaT9L~@YxADvxlL}Dp6V~hRX;|sgqKw8q$Nt$ z#K$XgSa<2`C036NHy^6u(?G_Bq~fh49Q$Sd=WiX z)1J$_F}DcmCEw>14es~+p&aDs8OMvXaegVYn29>;C){#-fiKtbr5%)ZKb@?Nee=2O z+hD=N2IWM@70VEfS9XVYJ`%x~31i6~y@2gfi^q87Ce)V=POoS3m%NLwjgivR3UJ0E z{-LPEn?M`^iu@(aZsF-$v%r*wP$|*Z9M5wslmuTBb)EPG4&2(nMPs6!iOr-8c(JEC zh@rN}6gX+JeiC`+C!)j?AwM&1)@lhJA7u_N13<9*T78UcVdFZcvvy|hb18f$P1tK*7r7;r8sxOSM;&(Cc#S|(G3Gw^V~ zck-a$GWG2PHonS0)N_tvyK}UNljfoI?Bcsg_jRZWD1Bcev-rKh<$ub4+j03=&sZ(4 zZh2wKReDEof9B&oxQ9QSpzYzRcG-@>^`sCWXMiI`0I+U)4d_ZsyE+t27ZuQ|uU31# zd6^2Whh4+LZM9B>T!EfZaKfBysg^i^vgZX7Lu-S!YoXJgK}|kr^Ke=1vbNB&rlkYsSx$b(9Fq#>+B;jsT!Vo<@wAFP!IB*pcHG`^2dUXKDpq+UakK61{ z-%lMr@Q3eN@{fWdYsE7zL{BS&E|~6wrbTbL_l9jtwbp5-*8t#d*H4-L0eHXEMsOx) zDDCZdKBp4^L{{i?TKrYPU_hza#@e@&AI+BOg64U>l$Y)=$}j{`%0d0YBI^x>U-K7g z>+ zrNLYmL7x;lSy+T8fLp&I-+_(tqlSQguuev73}Vsetf_R~+E6X5P^a1}0g1I;g2 zNCD~+f!I>AYtexZM*MjYA2Yi>WU^0;=XRL2?Ca}~26;>h07+5Ek1XXF_8K*@(8QvP z#dGHz02GjPNnSnOQEeS|Q$K7Zq`z8|!{6DC;vu=9I+Kj$^b4(vliy!9q4q|P76TAs0 zfM?+qaUOOUT2j1QH@ZCq@Uulm=ILf_kFLFz3kfF8iQBHN3R7Ja5;t~Unp1!7{DFl$ zOo0;_EJ0z~R`o(gDXoECL;Z6%TvOb>q_$$m^nU4GCuPRV=4v%f+689KV8Ld`lMZ0f zN$o3c>PNZ&ISz!4f*y80V92I^%-P2-rN@P_(8l;WL!C-e_tzCvhR%tb_P9AuzRF6gj<>%aa6-FsD= zu@O?@8SL16vLW?P6>qOH6XG`^sC`|ez#w*=pwOd{Z4V&8SO>Bd6;RldATPC^H z{8=m$E}$@1^-sK28QpF5VCtMN^S>YcAH@GkBbz^}rXo!@)r`aX%C7QaHl&})K z`2mP|TtzE{fbb9KnJ;f0jMExX51N@4*{Tl+RXNP@qqhM< z-!Lt@PJJ6;oem zsd{Go#0wm@9r|)J&5Myi5c?nWGM(KYG35U|U(6WBFj~+L#LNG1>)<5_w8&!5ktj&T zuU#Sbfo}k=V0TQR$5xFsZp?D+cmNjweUYm}LK?yjcu3GSN`2xN+swu28F2^#_#H$Af zY&VGd4!oH+f=2&H$}h7%18(j;aa{E|ZTog;x6qY;IPT6CAV0WVtzcydDpKK7?l$;r zt(Xx+S0^nR0lv#^OSz0y(-}aqLIAVReT1tpm`Xzq>z_w{l$cl!n2>14x@|QEV#?wK zd_q2lGGjiuF7Egi*9 zg{>Cbp?Qk+Lc~%N!ui+?-H(R6*Xgd4>_77%` z%sIqY2eE!9wa_>jW5Mdvc9+z2--F!AGTv?FA{xsXwVBE$aqR1^)9RV?znr~(^1`S| zx^f*t!vgXRdDDw_F>t9Cnd;LjqM_L(F#bFu)bgy!4Y9Lbf)9Vu^R03<`l7kqPR%tU ztF@JKc&s5}KDXV@WN$9bw^Hn~-9akRZ;;6lQ7z;<3}qAv$YnXQ+nzYah2(`~c*Y zkC1kMa8B7VvfKhfJvJcOVtBmsR&^Mm0I}g;+y4tOKV08C&+7Kw zlg0eDObLIWBw(1_Y)*VKaQF*)W*1zHA4BNolY=DD=2F%{W{8-`KvZ?F z6H5vz!slEL>=^KARU(RNKx$Qm>-C+#RL}TcJery9p(RfV5XiJtb1&=iH$WpB?Sq3Y z&6HyQDNutcJx(J>!`wMbU$dkT&^QFfF|);lgh1>zvMHd`p% z%8ptdV3!E+vObn!R?oXa>~jETNLh9L!zx6_qi(Dc-6{u7#T5Kp#1hZXv*&W)zm$}Ec8CId`JT1%?t z+}^neMBZ%Q8}k0?33OtDNN*2S6~KN;Sy#xb2*ARwYaCd(>Pi#xYx7&j$hpjO)WWBz zhR+ObI|qf^2-ZWla2;?91_vlrZijm`pYEfUV#`*Oej%yQ$4K|G-O(m63x|v4>;iOe z@7(AmrlzoOZ?{1_ygHaLzaf3K#Kp*(A{(dahdM5CJ3mIF&-rtAw4f?hNcN$ERot;V zTQ%2Dt%&a)sAjEsEx%5tXrR(zDDeb7nwr=4NKj+VA4S)P<~BTTS&lRrKM25X3@W{w zyBa9uzNCK;uU`cJnlj$1r{NNZY3Z*8kPi>U#^%JB@L!a!98B_^3aoTgS&a*KkoKq8YZKYl?@zwE z3BVtlZ)TZHY3cj3!69~upu3$Ds|Tqz0TXrEuI{V7=0M)w-a+EU-c%}Dpo2I3$6U0~ z%MT_`VK-dA53ma!BnpKS68Ex2+oHFb=boC3gNh=33PjaXw)UPihHjWOs~trBKzrgg zuy|VI&_j0KoizInoRa#YY$<8y{X}Nzt#tIsVmBe0o@4mt=R5WAAeMH3v8v}7`KzA2 zQ!$GZ&;WwOh2p26o=Ks5X225o)-SJIBe~#I(UWt_#Ypa6C0B4`pXP(DH;X>++9(m- z?4m4Pw3Orq76Xa<>(LE7N`ZR+C@Fse2>?;ufjT|$Jw!GB{vV2p8H$C-W1;Yj*GmUU zClizjIN7S#w-b6_L?Hsb$I{phh<|=mnsj?JjT4!2P>u*w%uTJGk1_lY{YRbyGA#a; z*0N0l!ZlYGbHZEW0|J<;7Lh>K-QP8S^757tTncrg3bM`0hMg8g0TBhi8;iLO*Ct1< z2qvubB zNVi)kAB;nP+R76<>Df2|V0BrDV)4??|bxQ3^2$54IzA3_>4pA?91dE-j0W?~*~F=Gpb z4$`kr*lQ%eIKToB+bjZyt_ERlXkdd*|~&0b^M>9m6b(M+H3ly1DEru>r_>+TQ&DWZ}!9iGfaO`@bAly z96$WGm6+A7uiQYXHh~+cG!^vg{gw&;k1>bcJJ$|_JLc)yyZZ;~1nBp|`gv4$>t6>x zWIZe>x6T7m6r5MG4^Twn^}i0{zwkd)oev-K*U|suLh=8J6+AN*Rwg>S`>xX>zPb6! z;)~9fg2Y-NRI@yu%_*Y`VMPdTpu++iWKpqFrti4-NL}QV$5Z(klBG_fw;l)2+>VSq zDbz>6|A9u+2U0R6S4dobT9~+~Iu={nN?7n*9zAuT5r#1jdS6zgqU# zs%!#9(;BJw3W2(bGlqzg!)HE6Ci`S2YC|g@811v>Wm_SoSyR#**K6KSs{v`;NXu;o zpkR-V2-|5S3Y*Ukt)8)PNOxN+6KlrnNw8jGBe`&J@aP3fLpHTc#$ zgI{n)JbYqHD}b#?n?`oL5RgE*kT~6-2j3I|vs$jFq{9L82U;@Q^e=aQq~Klh``oGx zZ2_gA19K`dH=2ANBCD>_Py*k?!&x zfS|uaYTG@8-3bt6Pv^88WyREPK*M9K&O)ijvWSIb$DmhPEv;yGCG+E(*)-^`J6Ybn zJw91U(Oz!L{#B;wk*<*KxV_c9SvP5mc4+q;pan>eH-iB7Y{r;Xm|p`-`1BfnBJ30b zqGJ3tGV zD{n%_T!sRYHf1^#c!ZWlhd_p+)5ilPYr3p(&t)O~@Q`E7#y02fBCa^4&fm45KuFq! zo^zj+^yJIE=aNE>wL9Jpi5VG4G1Yi|v@T*};f0G~_!sa}@9hJ%RAu1G{hs9$6&Bjq zxY0U)-WAX{sBT)})3A^SP;HKS30>f!iTP#CnYJR8s4$A64qzvFQB2}hqwe_Z->^T| z^xrl^uT21YOSpcUJG zUnEIJC3%_m=WT4ly^wbA9CrCX5!AFyJu9~K8fC8qv_CyGuuoWrL7c+k0J5O2%FQLs z)Nm*?Hg_sr{b|fSh8di33cG zOn#RMd=2EGtg4f!u4HJu-zX0oC&~C|#RB9PN9?UmVWy?MM z2FJ#p{S5ZXkx6Z@}2fy~Ux z;&HV~B%Z#TY3A^@Hx1C*2AB4ZBEzfp+aYv2egd@9*drN)y@}f-td+{XoYmA%uCU!I zSIN5_z7!cSJvX%EBMeguXUYZ$cU$jJ(DmYQj8)t+H@YMPA)&(C4PU=3WSXAizS1Gw zQffP!Jj89|>t)+6#deutiIcResfDFIKP@PyJ*%WM=>L*;N-_?&({0mFu2BVPGl-#(ZNi!ct-yK2*ou`ycgy%5yT{IpqY#!+#)7@% zOeYwWWTMQ7ViJXqij+0ZD-}HeTvMW?GIwoiSVKz2B2c~-K3&cr;{EEqT36X)U^6zi z52hoGt{9J04njikBI86CArEMwvxxjLUCn2~@@n>B1@u`E+GS*edkoQBF&T0M`_jE) zi!!w!QNCZ7GzPchF6CLa@?sk80T6<>7F=@Dbr`bY3$gjlUL12;%aR1a4j<+ekZPBR zQz%KZ`0KKO;N*cHpH=<<)=h~^?mdsp4dqbA00cF$wN=*ma8^52d|JX@i*EH(0`%%C ztWa6OY`J~cIr0{ri0rf6?kTDA$I*=FR@;^?%*If_txW7SZip;EBBVYf8A1_&%ghQx;Xbm##28 zNfL_$4obFSm@{W7m@+Yv`gsJFq*l}3?q%JZ+ARE0-5@5PWOybmp~Lvt4ImFQJ1lw8 z{+SyR=Z2jHIp{iP&iufZ%hSNn7u6C6f#(;Q6p?O19GTlV!2@{&cEfuy_I0@-qV}VO zz>gywIxMBfc2TrTmszf)%_lOUHk`*xXZhioIj?GKeJ6VYoogJw`1!=wsGknHNcm#e z2SbDENVer_4z;Ahnh;%s6gpz9LgWm1goBpMCC&RM=#nJxZJhV?bHV*w<L_ z85!smmZ6OL6LR7o)L=I?A)oZj+D24eetzSgeIV2XR>Eqn?T6y8vksp@qwCD#k7Z&& zBi4^5Sn$~^74{c0B|>x|2dBb$$wy}I!x7y1eCWM%zRuC#fBHSh>c*N{WcR4m_M$r< zy!5Ww`{n>D@J@Dilm5l8ZQ*`4W(nMaVB!TUW^!!Z(!(IPX)e<7aiAm6GSkpOI@#;r*cdwVd~uEMOIjc290OYAt zA|hYaE*%G&r>qL5(1TDz^2xMP&^gx61rtgsyrz-x%2gKO*ngg|D31Nqv7fEVJi^@{ z0j-BSS`0OMr9i@R;4FA}7~W|2&NLCLFhA`K&9=TpN-CnieVMU=l88XLbK)_S+GW%M zg$2M5cnZvVY)EIQg-)p=P0U`iSXlBBP?L&BTO$|AVBrSQwcH&7uklO@l-+q-lhX~y zEOEd_sx5O5&lfGSz|QjG0R$NAlW?c6|7!xEV;YD%uFZU(my6WT$|yt+HMXxwgiyxP zJ$N7=Oq=e&y9Ax8zW;;G>Y#hid5%L#I8f0$`S1QP76}*4-;HJA+TZYz!&T!7S@U`ywc0Jynud!YCyXA zjR=QF))^uLexX|TM9T!4+mBx;9wKg6y7Y+Jja(>JisI&C>sRYE&FxxYDU4U(ln^l% z>=Lt?ZcCC(e%9&P*lD_e_!8VRQgLG(9-SCp#A?MSl4#}H8+T984MU0-^o`QBAInvd z`Z{gg(lXNavIT~h1S1O*_gYM3>&S%bKvRy-Tkaj(Eih-z&AuJ=4mon`%GcS2%(e^2 zf>D|<7CjYKfh`X&19QU-w(n0hgOS}Wx9!a}2CEN2${-Uo9_9G0nn7{!GoUfN z!2<(cX??XxKwCd znn6>KFnyFk;m8+s#;2Ck2Z08U7P0>h?o3`Tveeh$QuI!JgSMEkdS}X*xx=%E^NYJ@ zPOo7X8YFWxGnImgm8PLLNSwUF{qc0TCOw*(Ivv7`^mgRl&IxixN=rMMwq4rw4;?Tt zg1p;Uj&9E%!d4xgl{Q!2Ut877-9>8DmTD;jtJ7aQ)TGUmlO?+JiqL-l+mfhw~QWgi4PAi7x zgO>A{=N(W2fZXU?*TD>vIQGp}eg)6sTew*GEjEi`s`KtS$ZXmf3JZV2EW*@VeyCFx zd>X>C6E*M8Sj&IZc{g=iFkje3-GS`yqB(Gz4Q4%OP`kuRq;2Q4G2(C~_)r?(S4v{6 z^Wb+yrWbXM^Tn3<>B_}U4$cPR0Sipd6P?m2C_wg3KPLw8ALt5?yvI#@9Z`A!;znFM zC`69yt0pSwJubm5A!LE%ERR6eH0H9+)n?H~COO|;RZ5{{zf7_F1KRwonXi_ z6LYmB_)#?5c`-fbcTcR0IDl$LHl4wPRx7P0%-EA2MzGcKpy@^U zFA=MgE&25eUt?zwGk!RQwqS-vv!5%W>VL0vh&G8xy4}N;v#z_Y~b)WUIcO z=imnO(3M4Y&tll|4f1CfRK#t>X1>hi-KQW7r@%l&AHqQgIBCy|5&pP&AI#~BlK`%+ z%~F~13yFzi_ogmu`5301BPbZKmVl!+o#IZKT}St9b^x&qd3Z)kaOyVg$9n~(pgF{9 zn0sC6z?-80SR=3eZSV+z2M2@q+_j1q-`XF{l{Y-$se79q)S=^&5Ft`s%weR7e1EfJ z{Q%tcZ+6)N4C)3R%b%%$Muucs=0U?wwE@Y*SY8;wWrw6e^IS5Cr1^BE2k85VuQ-g$ z`WiX|z_p7p_GI905w#t~7i?v>DhuzV-GttfgftF#vJ|zDu0+b`aj}{=z^^R z2EzuOGG609E%LwgF^IDS$h6&)3Q-9&<==@ z5G`;zlgs*!!vAFlMER^ho@NwxaL6d)aMJ|UdG0n$v)91+FmU|W7idc>7hzMBW8y;+ zv&JrA!k8oq6nuHL;bAU|el>LeTKC{D?%tZSn((lS@8JPpL(Hq1A?r>VCuQ`w*Q}j| zmBrjsr7&nN{oe|A_q&MfsHCXOjd7n*qi@=m(bZA$=(LS-lwwq#uAXPF!hhVP5?QyF z7?NkyqqEeo8m6hG)!llqH3lv0w!TE&#Z0(xD@wYO>U)iE5&rF!;KHnw+g-_I4~^_+ z8N=n4){BV~Jvxa+KhK2sFer0>caB9o$CX)fuDjJHk2m)jd#=*7(oEieXv-1So7|K$ zZ^R{`-1*mE0|^dq27DVC9ExUyD{X?5(HGC(%sJeA6Riqd<#<63^r@t)P7yT18|JiCLIw~piQhPWLKfkIkzj4+L#d8Vyks&-B|8aN9 z9>47+%nF|RpIQ>9{U1?+|CKeR!_CEy6kflw$$NEQW!g~a1LQVBMM_gGS$!;-Ie4_8 z1xO(u`Q`W8k?UvjzF7YZq@FXw=Hf=Y#Wf7iu>+mRvuGjJ@(<|T70HkNxnJUu;y}mh zNWGY%;hv;9KR5l~yAdlMU&Q2TZ)hjk7kBU!MC57rCCsmm%M^9?$g;c9=VldSJU}1_ zl_96wl*lq?c6v95)*{o)aK)ygZ&U5vI40e6CHBz5g>3ueqCAaEG+PJxOHfpn5;{EG z`?&k$;o(=$Z)mC|z8x6&mL39Ua=W9pe@jboV4w#)+_K=;Moi9Qc_)$g#q};)dzZ?h z)U_Nj_Hml5H(C$UFQGF3Kt+N#N%d_wBKV4fbaD1R>H(BOq~{!eMs4iOlFWVCcMY_q z!#Bo$9X))2GpRxGwhPG!iQ2}A?@CgOQY!5Lw)n!1`UYC*{ zwAMD?O0`+$2K5?iHZrJ~zeGQcEvfyNdh04$6s+&}(9_mbQcRf~Z;kljp55tYK)0W1 z9M6^Mu8}f1Dvj2D$ff9}_#E$PJvTQqXLIflrzbCNRWzy=iMikq$L;a{%<#An=7Afx z+o8p9P(HA)1T@Gk;GIq22($ZAyi8_XymBTIy=3#sW!g#Gn|?HCCaE}nt3ayO@_VzEH;CU zYGyx24a)d}y_wV#_) zC9yK{$picwirr>CEMF{vxIae>ZTuYcUJ5H#WRVic=&pYq#{={(AArh$w2?Bw_T|rk)MG=XqtrnWAp>XCo2^ zn@H>zH0Af1)UoOW+tz4al+;ZH1ja%cJ!Z_4uT>GmQs1M-_lHpr4rtu37qJ4QbhXAo zwTMPx`eBOF662c7S6OF$+5H4FsEO z&F&HU&iacRv%9KboNqJApgq-t(_8({5O}(`f#Y@)1xJoX^S2TEX|bex(BUmFWh#ojy#TS%LWP-`Oe{9DqI|!0?R4tMSyTz=7ZqAyt;CO=ySHmikEolt_Z|}k1FtN42 zt6*qHivtis1u(|Kn zO4t@Qk`paj1)0acq-OVJ(h+k#7d z=Vy+mMwqdN44Ji5ET@E%zL9kBFWF(8st?pZe(Qjbmj|iZP1p}9ZY|Z+Tb*Zrm~5+p z*4*<-Hfm5}+~3N197HQLKlN&jIbfnoqqHT^nozgI&^!C^Sy|Y_6q6@XPe^j3vf?$K zQB`4AHL_d}wLbEjt!2D!7^xWL%yIQ%G#i)4_8GgquLgEIn}YIVUqARcRIY6mNmjWg zi-7T#UEHwV&d`7huIS366br9<=|oxaN(ZQk%*>YBIa>~AdtiB{4-Oxw zo@ephcYObnuN*Ky*v+E$dX)&jV){+?YmY6@5-h(bT)Wxx<>CUb`Bz<-9qd6ju3awi zR#4?*W!=|yTi@C*Nve039$Gpj@_eq=$d7*iz?V0?_87!ehiT5oKi-FE9vC~kh0U&< z&b^6TALK%Gf8KZqzh%1Jv=t6EovkrTbzcvP9E@JgRzr+-3B0{$JDDgKrh_lt4IG;3OBQ5H9*&5rR;%;5dSIxuuR@X52a8G({`Qhu z+;f(3&(z{#HtTP1e-8+%*6(Uewtx76>K!k5)Mj4j`iNxZyS64x!^NT#a?Tt*N?gyP z^3!a`bZ!mLWVxC^cZp5Cd@=IO>mHx@Uw~ zSq8OZm@PVhb=xwW0%E*2Jm}|nC@(Rj9~HTQ8R=K1+B)hCz)=%q2acTJgoMbH>WclQ zONA5&g5(W~*3yFWFnLp347Yo#=z8zo z`>6JAyVu@}5|oirY`+`2!fIZhj5z4#bLFTjnBli4k#KG<>-%3{b~^qVmy$y1#uYmh~1e1YG5&wgTxJxsj%yJAb#baexVy^dpDLg8}3 zCsd#gX1zx=Y=3ah2jdA2A!yV(pZD4LM!~YPgn^O~r4BhdMg#B&w;r`rU{|`}{|R?u z8_1uw@J}8-LN;^5K~AVAIi(rDF!BPoHsF8a_&u;EHt?5%%F(jIVh5YqOkj{ezJdMR zdodQ;vS?t9`s<^v;q4TMI39`Q84}fXBTZxIq$MC8$uj9GkF)4#i+xf^X`-{qk@7`0 zZ!taS7O9_j>*IreS>k&xCpTfl!=OvI?Fui=&xFU^Fah`z6tkpbs-Ht+YppRLEv{zU zp6p5rq{S0%>J0OpPLj}O;D-gS;RW7fH+nzP|D3(HMwp=)IDFhh4m^|h~No$1}$&6A*0Mp>o>jLB| zuSdorsFFvv96U}by_Q**BWVVsA+%p)%$al*%eOD40p_HcLN~I^iudd^rR~y~eRgK1 zVu%G3pB)aDroK>7nX}F6AiBnYL6SL+C73@+= zZYV7`GI>7nY(VcJhdx}(^SCT6-In&{6@6j8HZoa=z#!*EimXo%iSTl-X6tBBjqNch z<9KY4*u@$9T&oAGHQp1S3pCKk|18T_b3U=8_8P4=n7D%A&HK2g@t9}&umQJ)+qQ0SyVWsT7p@yus+DPX&^4iD|mxTRMe*Mnu!ywhb* zlA@$i`p~B`cb??*rdyHQibZoMCHq&`r4sDCZrFN{bIhg%LSB9{B9rl<#9u8yx{co3>ZmwmGj(LgCmL79YeSr-{)$bWtY30*-PBWAy%Z|JbH~FY^WWHZZ*&<)6psRJ1xGDwOind_0jF4 zWyIN!^aXl?V~twG@8;xjoi5;<8^v6!ID3%K*nGly%c*&$HT4#f{qUa4f3|ULGK%qD& z)!-v(md4k4?c1z6mBy_2&evI&P%70vAp>#M>wO6Y71i}Yi%*zGi<|Z~URUx~6MOK` zEY9W7gB4H%;#h|=WDa2W)szO-6asGc$Hqk@T#V?uR@IZQ8K+mt-MjdUIT09Gu=*eK zG%C?m6`0nX4Xy28m&^p-<%?I%MtIcz{<`Y|qN>ze>VVXaVI#+B;HD{ZC^&+KnAyGQ zE}v93B=?1}1sFau5O@hM(%^o%+pL)mervzo^bBXhyj0mKd(N--iVPNYB^QJ;DadZy zxOksTl@J3_712zgC>2vgR%>@WETMyhFb`3-`5K>dG??dD@bmfK>$;ZCi(_URk18l= zdC3-$jleN<28-KcG(}y#t>pTsa+h4E`N^*XPh;~0@x2B$U5!G1y11>aPUH0?pR0oP zcf||WziVKZQaCyBNs$EcO&UoDDuJ_%>ntW*`_ z2b{hrZ9NJM)4}bk1RFX=Qq}gektFNZF&X1z4JUMlxz6;6=!OO#GkuZ8Mk|*UR!kH1 zl$zkJ$HS=Mm%XA zpgYU46^k_ql`clrx@y-R|I#R({*}&c-xdp&xt@o-o&@u+n+716{%NQ2URFFG8|6oV ze62O<1xKBu!pRg8zS3JOZhW`?4m$Fkar*3dXH|lSYgJY>@^wsul~q+a=(54tPk zGc+v)uGxBq%7@rWAFzbe<8fR=f+puH3cSSF$K6scXxkL|A<2=lzKsw~)7IURsZ$Bq zVd{t7tRh{rsd$VkI=ITVG@3!|N}$#-bbBmWN>BA}U)8#pNJuxb7?H{Aq~4T$($ z%d^II$rQuFWXXzQ<7)1(C$VA7NyI_&hI4P;Xf&xfcYn>7;R_#+;nS{sa|iO*z8LJPNoBtPrQFKZIi)uU z?~dQmn&nGan`da)xmy&tZ}02R4{zG8ES_^;Y+Ai6W{}SERt1P{$*xh^Gf)UTN{9?Ouu2<@z zS$0-rM#j@^^YC~Zjq}pK-&9l6DioAcNwOgY;_!WH%!|GsglAn6$B5Gm*SKJ3m{3V4 zeOC+bFAe23Pk8f8yzqbH0mPG5((fl!*#B`~O?$pUNF@nl3uGY@$YG)Tckateqn6B~ zxqtNtGqdJ%6KZGebqA!>;z(ASUKRRe%ds?c1snM-INA35E71lQz4RAlpCrzcCi4{V zW!kn4;-T8hUziiIS#f#cBY3fkgxmt%~X7*I8i( z$)%;FA0Pa)JajAB*{Rkf?P>mPaMlHCE6Vajqb=2!>OgBkt%PWn>^$?Ah_n&<8v{#G zHNixvq3A}w?r`Cu?p8}Hyh+Y!E^pKw9NK1Fkkm1D`P0y(ZUQcPnw28QP{*m2KB1yoKr`5P4poKFZ*Xl!6V|waBPkFWUKPPW3d-C7zjkG3rfOuUOAg)!+51CZz}{ zZE>@U?8k#rf6(f;@lu%J(N?NonpiT1f}n=HP;Jjdc_9v0HYU@Y&yrGOPYcmWez$~a4wX1%{icWf{0@7v z1i;ng%!~!H=bd=`U1JEHR##-NNF3%v|2`rR?}Bl zgl2|<3i*FA)GL}Hu}s@apI=7|na#VLTzfk7mF0kdshLQhuP|fEmt$Im!tAXs1=N0B zQg>VyeDXV)Zhvn(dm+~1tle->4j`BdF6bi$2TM_|Ft!PAeTs+n@?Y3 zMDQ^Jb!B*2_1Lmoy-&jVVPzZJ?w9jf{n3ag8AZlhyViY#NOUBfUG3^Q=pP?>T;&8A zZ;%~3(7jsh6F%+npblDb@YHD!BV0wlpFrXzuC(GbWAL zAMQs%mJzbFp0ix!5+GY|&Ka$DI-lco>h)KO-Q$69Fw@6&&uG>N7cDlPx%<#2Jb6?S zmRHDG2^kxH*e_6g+?S{P#Bgd0L+;Yn^cfT8S3cF*vY`ERF2KzhA`UPIO@aHpJBlI` z1w2B`;ooQNCGC~wK2MFj)6Hb2BsDbZTkJj0$=Inr$5bR3=H()ZlgM|A(eka1sK<1! z!Ecu#9^Nf$6fA06eIcVN6O&=V*v-njTb=&VeUUTsd}Ir#?(H|oBKZAw|*aksGW@7G(#|2b8&D@pj_SV>tG3JWhV zvX+j?@T1J2yiekgq{G>JaZ{EH#5c3UjE$NAxvY&w^ds9!Ar24eNKq@~twF&owyM$IzaVy@dHpx%Y)wVPzs7G8>x*(R4R z{bA{Qo{h_4+Xm~@`tDb3DPnRMsRmLTo^l;>gH-j!q-`}g?~>=&&=yI!$H$z8ZI2hC z>?vpXjm7%MPzXhM)JjM=SJP&!$?oPWHZC)-n(I(6#w4F?L$Glqjk?gmeSM3&c!vd zN-_M&^a-=_;W|s9SNhX6$lXF9kVZNh$7W2JZ_Y2g!oI;92M!?G(2OgznQW zyhhi0$ufXftykP`!)}s47Ns;%A8fJ4Qz`@ofYZy;-vb5PoMB3+t-kx10%l)t6W{@~ z>3?6q4EIFt1fCN~j>*WlI?D@#X^c$l+rO!~e?M94=Ao88Z+jUoPPx`yn)l2OHD!j= zO{8w4Q7KKiJCVOkiM#iQwymb_iCyjM0|GoSpDy4yd#{H&P66rbdjs|Yb^mG~ z`!(Z6plo^{*G#V=_f4{8Z@kOsj!NM)A3l~VTS1wc*Gd7OGIN}$ML0g&xE;`|dukjNu>0F6}k=1&pBKK4w zHoMF+A1p65Ipi&DPOWC$GB7u~aYMv?j*tacu*?!2bIs?X!(ZL@0;=E>r#e4g z7_+}2(?eaPA*-in?cx=~-L^a6(d3sdkgeUh2e}hk;`v-=Ep1$j%}rO^rzL12Z`r*8 zAqOhgQESXE-G$OEF#XMk)b%;23CS)o-ZW7}Jzu1J=v%pk9NW=e3W# zzP9094lGWSUiQmaNmUU`?R{6;kE$1%?G7C49vf=I3)*{zR<~zt!i5$`0k?`(PnSkh zmX*I`qxjx|Y7~24M2*30;W3tX&D^35Hmgbj4Ch|5+~R~CoQ>_Qu`Zz zIFFA@BEKI$e5%&$4KOq%(JH|DT;3Q#;LB?F=M+waHTJ?q#jC4x+UEm($EJYimoIDN zII>MIPL;f8c+h-mDbiZ|9c7eEW%w>){b#luYFc+LmTMqMIp1m+yp&y z+wGCnB@yk?jb33~0TYNm_G{E0zUPCHO21qQL&E!N+M%O?o9twFiC zT15#2AQpV{*-L36(?d`TF6+Z()Wl4-^MnYs_7}4c{C2i{I(hJugyGl9gRvY*470K= z0M@nPp6@OK0(H_ketsx$fE?j~P(}y1vkQSA>*O3Yg6yjO4VaK(a=(bOnR7XbWnt6Ja2<1}20 zI6a(mFB8`Lpcl`hC%-LbzIWEm?_yRHJ|(c#dQNvqaa?<6(Cs0T5qNhZ?s&o(lCM7q zTCXC3r9jq9ou*AHrxx5Z6kXPu&}gz|?GSJ+;ks%$ipjmD|LOZ{25MXUNdguxbqC1! zflT5`G1j5;i+4e|1A;j#hSd<}f*~&}QI7*YMC;lgHCBU%@LBIPH0kA$pCAnOQE77y zEWq1uvMu)U{*#rDZ(tNVf^aO(Y9h{hv)c*~TFTE^17@h4Y=KyLb2#%Rh05q){e{NC zAc#R^p%y`T;2K}aTilugg}#&YPk?ggu(2zoyUkaeGrk>-T*|8Q@nI;Np&^5_Wj?Ua zeOe@XZuw4N3zp(HmSU`%D4(Z@K4sChnk5CYPrci#C*XItgsr{l@QPva`&08pq=w&wXLI*00 z?rLNB52e7Umix941v{9FW-FFm#+&`TdZ%@}%DUZ;o(<+hq%nXFPU=5(Ag}1vPcM%E zANW~wtzA?kE8(~Rv$m&eC?tYo-vjxE4qa5ATp&bC%2lJfD-mj(z&bs1bke}kllC6` zT%FeJet8YVK&yVp(L5P=fr#~b;KgEA!4rAUx z3AY+G{CS9zkK_@2Msy|D)@_t1g9dP2uS~W=c(C&uVTT@!(&JYZ%{EX7{(VlHOQs!7XYFq;xRFJ*Qr4Z*n@SPJ`Perx>_71*kNq$YKKaJy zgS)iQDr?qq+fcE`{#0>%<;=YjlkJJ|t#G7Lxri$?#i<$uG2w%O`^N5h$`-xy+QL9z zXuES?lZ)z?!otz2zvp$TKXAw_E5Zia1n8em#hewM-I7amc1K{>pZp!+73@&6%&1Er zo8Vn?jE0x+f(DU+C{=N_P$<2Zolf8Tmj2q!)2knfU zpr{eg=IOqf69M%p7q;PFq*EYMi?5#m&n*pe$f2 z$=Y}*z=v^Fcc42c;j5$SNZKdS~C5GtP~#SJ@$qHN6>t2nN`$g{HS zv#XGgwi7U1a9E{haJKat87&ckGlp}&dO>9uYMhLx9f zGmqM+sd}kmh@KI1MurzLHhtr}RM)xL_>DzF>P`qdI%7i4rODg7o-(%9CMSNVxz&;N z)W!C!AKE@+F@MyWK5wM2c^iS&H5+fo!8JIB&( z{F7-Wjfd?I%){(_y$I*CdG?Lh?&+~BcW~eiS^Q0X@m6&u@be!lk2aAKI%Is z@B54T)ZFn1Xr+$s1l*rQ04ZNf!R)66>~9pZ&Aq1K_^Yp7xmbGl6%yb*D9_8+cX*bp zcNWqsfOM~HPzE5y65WYSo6Z+wB&I!kcJ@ub4v^zyly{mazn9+D33e)AsokcaLax_s z=pky~PE3X4@-t?j%uNletS3%T8Mf;s-QIsT?iwGkAS1C9f0fFT{v)AHs7N27ISH+| zoip!m?%5b^lpv^20Y~x04h&h#m~hR9v!_sN8`l_IRaj~3vci4b`uI8pI6nh;7>TTw z7fibGrX-q;cAha`<+aosviH|_%kW0e@;Prv2VbDfMJU5!l$0$2>!~s~5u2xSHwG;Q zic^Q^1~hjiZ0{CXS?+-pZj-i}EZOZWHtR26r|-uU)%!h0RXvH?+p{4~Y!2-KlGS(%Q$enzR7 z(M?my^C@j2H97s#qY z_Czjmh8z=wELVA@yP z=OnscA-@&SdcTAhXacIGjFDjVjd2TvhFKFVpj6@ zPM6Ig<5weUZ^~nKZC5 zUQ8%rEvP@XIxDvR@!s)ov*cX)pm5IRY$Ah{=UY(+6t1;rYvIq^7g`Hg5nV zCh{Fv|6nJ8t?;e7in{pPlk0cF6vQX4hZbr!V~7*Ox*bHcs#zdH;>*1@@bqXO>RP2L#ntf9~M_ zAyxjQE5vour)5VJ&(9*4XjA;9Ftj|h$SS(d+QqTTH6L>j)A93 z2p-~42VXy=FMtP;n^^nSjrl)tZq3x5jM+E*`q}3Do_lpait%P!+n&~|cx|noD`%vV zwwzONZPZ??s<&WY$cLIk6ucS`pg>)CS$iH)z>I0!wa;9h=uJvvhY=sw+H3_cWm11c z&3`mdsae1$tc|S-#MwCP?#k@Cesl-&+|}N0sNA%rnkN^NQXCGE*Uxx@f7b{dnI!+y z(=d`)IU7RxV2n}L^bZ40uuLt3IiN%QF>RSzmw})ZROTj&u?T>!s-+xqdK-ADXxZ*`r!QHEfM=9d1E^h`iZtguD6tz_u$fK1bmBOY% z7s1Jt958frF)=6gh$&E)Ck4Zs)5l=9i-0>pX>gDSc4p z+Wk!ua5x4b#Iu;@V)S|VIYV)e7Z()IHrM~<1_{U@*qO;Yd?LoyINvtfJK>Q_O4-IR zS|{sBEZZ~_m%4gt@#ni;u0-WVmA6d}Skw9&uw|LLr(2|+GiTOBY$R$ zccvUz*YjG#8v&6cWU*R{g_blvdT1hVT4Y&W?CSmIZc9LCfE&@E$ z0eEO(G0O-xR37O)3At*H2Jt%|mXNzcqb}gz8}-4-d>T^Ctmy#7+yM*OEGaGW-iP)X z;5KlX5l=R3-6vwm(qg-?X?i*mgVG2H-jZFz-OPMUweM9iBU-^|LWzU1B~E3|6_09;rvM% z)RHK$+YeHZC7&|=mXqr`kIS~4Sx4)a#Y~GQq<12rTYIu5p0=7T4o{NzNhxeF;7R5{ zh&D)XiuE1e3(;n!^ZNSYbQ@ysb7llfg0KkyKd!$fCiI0sr)cLdW%s8ZnWn!&2A&X~ z)uGe$bj*Q6CL8iQfdeCailJe%dlwE+2KbtH^6~aK9wDD>$eIAvYm@Xf6_8nKw-)+ttJ5M6&otrKsmu-*}0^^Fz0A@x;7(Q~@ zqi*M`F%Xi#&6z$FzBa(`n0F;WPsr?0+uihlarHY!@-uAkbkQ}rTl(=HS(Xt3$I^+R z&;F67>W|Na4tH;@rh6h6?@jrLxQ;`8o9zp?A(cBY5LoEGBgR_vEO%5rPP8)Iq8@Dk zmUmC6Y4I$Wk$X}vC|8`SA1<@WI7Mag^lPF33iJ><`BKR+L@9e{)5eApGRc;Y+@w~m zf9Mb#5kLRWDADR%hVsCFnK&XKPXqr6lsjGGrCu15y@?HBavf`dd}#c-A*;;z!cBxh z(Ir(R-(jr}TT<^fGEIC?jg~0wr_7R8%f|zi(0@mI2Mzt#9~Ht7c>i1J{|E&||5omt zz40HvN5uCAiUt0yRNVUCYW#UuZ_ywTUcaf#XR?zSy|=-b-YDXfpkWHGzy_NAgC4e5 zd7M7Y_-1NGpE}`C;l3Qh&Cf4rQ>W=ho@|!S@>mZJQLX?_RN8Wa>&9{iWBV{|@2guh z!)IVEy>2xPsOqC6Vl%qI^z;^i<4d+S3gcAgG{%(TjnQ3=F3`RUi_;iwoPF-J*hUu_ z$ptDPhSk+Iv(y?55qv*gll4Z!a`|ncl{ZrhQs->O(|+kOj7)vmHLSecMDV&v>W0c}u(*cJT`JNmsLB}L9OKBmu z7ck$~M;!oqyuA>{&C9LXH?uI>|JL|HAcnZ|o_RM(dYp^2c?+c!<}6LPvU!2Wf-f zQ8eWu!m_%{#_5qiwDQg&oZOsrX)l zCR%`jj3Pw{h|Q_HzRQh{O?=-mbrP{s-P|c{l;fB7Y(ZHr?fvmO&PK(T7e$wJ010lN zrzh23C#oRS+OOc_rR__+8;EbHFZ@-4z=s@=OJ-1)C(8~3a3fdS_q?!YNTf)zo}Lb3 zb%qa!MHh#ZO=iZtwu?(-rESSlf92!W4Ri+bG+9T-*p3ud$%DiwDJfNYtX={3$S#TR zch}!#i4xY`%PZi_zy4b4bBU4&bkS&w1az;}He?}~d1$Gt-(zTEYZj7@OB zQA?rhClCI4|Xb zT3*lvxm5^FZ37(y7ze8T?&T|bPbq=K`&NA0_NG8&Mv|iQiPkkEK!(_^P2qc?!%t(* z9=LF2$RCr}7ba4&WS1LsjEvIqNH*!Cx-h5Gb1c#s;Nv@XKyuSQYG`-~Ge>In|29@t*tSPHX>LM@&^aB0Rw`oJeMI;}w z??iG7xanzKgQk5imc{Q5q!4*iQ(~}@T*68@>RIJT)N)+Kr*`J<;4lK z&R8rp#%QGKvoXQgyqk=x@%NSuw9h-#_ zQ4NXnOdg&d*V<*r$GPQf_5xD?2H3RsYD0+WI&Zrfr1+Buesx84_dmaXp^3VcUtb1q zOkSX4`DW!(fzEKXFA6?KD|}2x&UVz=WfY>A#Z0W!vtd6|P>T)L>?6xvTp-$G-Q7Iq zZ63-7IFeIP|513h_GkmdItV7e771ey7rs736(rS_SF*u^!+wZCZI0N1Hi2^A=3}n0 zH7>DzUov?|AW9D(J0mQmR-sH1V>!&y?hkl$y&agWtY$em#s3oK2NMisC#r0Z7S-SIc!spzInM2M zxA`tN7r$uO*^uCGGxmFdX_t8##UwqDOIOSp4q>}mbI8vCU9t42>KIBI$etz1Q^&yA z{AC@RHLwqCT)h2#IR?WY^{S5Ox%#{xGa7+giqKv8PDmZqlM>UzCJN{}+?Mocbt~K+ zU_GGmb5pd6eX(3Lm4F3Zg+ zX~Q&oIa=ft8dCT42tDucQxFM1OdrgPRu|CG$8d^?=|Ok}3>#zx?Nr9HN=nvOme)mX znw#(5|4kV!>M)*`Ulc56QzfD6B;)mTx>E+qvq{Ert>c^4*_*RptD()G&(%2 zU}m;3O(NwTpSv~^Rci>OrmZoktV~-+$C`M!i*2$@Ojs8Gy+B7pr_dxxO89%V1-ZbY zTvAYhu)b*dvK$!B+#jid*NgT_lPJ^iJ@J?)nYW!+M5?W@reRa0FU7WC6cL%L`@ z+7zNu-cw4NkWw=B!KkcWVdq?Re1CF-{3PkIBhoq_$LOkz{wVML#<{MxLdWH0(-<+a zQi@M+)Qu?;=&AX{ahg@_&u`AnL%10KpB4Z^218bvW#(a|5Xmj|^HS~q*ayBECj{@I`8-V;CH{gage zZW#|pqAFS;Hwu&wee>TM8{jd+JN-XBTmGW_6LM?Zf zxuC@wsQBE!sjQ?O6`!{~yFUu84}kJK<#R`#i_Wz7|DodB+~>5O%AuVVMf0@|9S2` z=REh^zn>9$*lDd=Rd3a*de_>i8wTB0^kzU6DsqS`sQlK!%Lh|Zf|tkDrnUqPl(%1; zBz>k)kGy31t*@_lN1kU>hD{XYH*CXlpUGjXjMbFe>i)j=l2&l$GrzU)WykW|1v6|F zkdS^a3}EO-3eL!9P;{n&y{)l|-(>|Wv_AJqia2zyOIP3G@55BAmZ}6w^ipNAfoVTw z1h%Rnm!}N-eLNP`B9~LsmUpzcH{FxR+{3KsEp4#9zvA^jXQ?~dQmTy{@_eCli!y$> z^}cax!PRI>i;-Sp3*T2@+vT60CZ2>@pslS{FToU;5E)~HlNEFX-YQVIuvTii>-L<$ zIR>3gtxWarUfrm#ZD{!CLQZZ?dHrZzG&-M)S7)VZXGO@NJ9q!QXy(csSF`$1a{2va zi-DoEOAILj(NQDq#F~FD#d4|1*XkDwkC^E_^P2TE-Pt{pPxZ~BrhJd~n#tB=_7QUA zoSZk-b$q@^X;<@;xQC)MJ!O&`jx*U5xD@@{Z>RdiZ~nzF`@QnRccySDrGUPUxaqHB2|6RSllooz}bfueBcVAA1Y6b@u+t3~Sf; zm$J&&CjId9|J+pShemw;`rl>}_%AI-j~;I(C*Vxlk_0-w8PF~+A%2CwzN6CDYph$| zQ=VW)$@Uh72mI^wxb?sH^!Q&S^ItfWjIT_ZIQfWfUG!vz_oGK9buZbb`brAZ($mTB zsSQl}OP#|-opUoQwp}0$g&ep)t&yJD&2qQm{`lpv3mg7?1VTB>9MY;V|16FoQ=Y;hBeBXpbH_5;xhFoGus2rLx8Ew$viiP)>LO0F?J3If3UuAVLCW#clfK;L&HjS@DbJt(DYo2c2*t(rcTbP7 z2@q`&m-ZL7*fj~_ zf63g&AKBnu1U>T`=g`a)9bQvod`8P}_HwplP8=ni?mh>Wk+L_2o)n^R>kHh zH?4?chC`RoBq%~@Y3b5@4I>F!(+-m6x9H|;JE;kCZFO}N#ET$}6j?SWt%#AJzsP3E?*I=tc)TdD1L6;1*xyLrI4_=+2mQBP?#TK9sbzG7y?@ zylW+|Nn8~wd=&J;3D65r!pQk(E&i40e*sWU48#*=b*hSDiHO3aQPTH0k4F*N8gkv% zZ1p_1$lCcPFO)gXoojYq=}Y$W`y>9|!9PK9Cr3jKLZ-a*dkQStS`+0)KYfaW`4HVA zo!x1?46fZh+p$-8z`du?Dl1+lke!+N+W!6f+1c2X=laXIpSpex8h#R^?iAO3>-6kw zC3+D@wd>cP%$6=HsB3DX;Q^QgMTspntJ3+$u=5Mmi4!JzW}jwfxlp!_jv7)@-pY(H zd>)Gt1Bh*DBoAuJ*yhuI$Y+?IjnOK;s+flB#*e%?s! zvn-phro$xcJ_wVRifx=Ytdye{ce`01%H07YjJx&r*U_=DDHxSJF8=e{`PYx0z0nK@ zV8k7|i}UU^s1#cEAx+x7dp8?5chd zJEAxQ1T^5X)}bmNc`^(KG*|U+Mq0`_10PsKHZeA#{Z|I>OtmEk=H}&LN6&8Qc6?cD^5(s5 z@7phwx_=Cb3;%ri1twuya*|rS$jFfKPgF`~tg@wCM~Csm6~tGsPQZYg4wSniT~JpKh6rGEcsO3nbvdP=fQY|w`}Xa+rlyXT zco}sqtyJ)dCUEWn3W|{A+;Q;H(xE!_JJF^p!&MTMS_Wm ziHeFUF(u_3m|v=4O#p0rr3B6iEQV7?Mh05Wf8R4LElmyX3{lZJ=nce8U>E8)Zun^z zT4KTdLbtp1TD*@QJC;!HzCk-w3g+VN?ad}G-mgaL$cjNu^VnLi?dsBkb|45Z3cDv$ zQ5k(C!FNQ>z#7w2QmzvS1Zhrq0t*X^{C24nhzp`XWo2b}KBl6gq8o=!Zf#XzI@Zzd zo)g8y&Mpfl3Oi1}%EV8xzkl~G#eHKL`m1VTfdykq2DuH3(Fxfm=<4d;m@_mK6%}o- z@bq+;YDZc06sUvJrjAWdn{O%{I(bPcO4tDt6B7e=bYsz+|I2W58GWDCe;s{mwromE zTmgmt`GQ-RprD`tdXandAyZYV(ATt-l;WD13Z2~%HGb6wh||+L$rJ!Ajt;L+}w17#!NyCUER$)PbL#S zykL?K1lemP^VfnIfF5<1I_E7e6OwT%ryX9M%`n_$cu z88>4=6&xm-uYewD=iKpzvOx-rwH)RoJw48K#S*KPC!MwvhMscI?*RO<7%1<1WtEOI zZIi|vJ96X=#_d4)A3JMBfE&}*-hyjCz{`J>iNo(V2 zMMbOm^v?hdsSY1LO>hd#^@da~E2|8^i}b4xX@GyoiPjpoZoP((iqCfBIuz+638ZuE z>?$TEDWC^_+NyI+Aklo!9S=}vI=h1h4!jHsGCV0L177K{aIRS6*^~BzZ+<}{;&bOF z{BDc%Y-D?Exx|l6Oqd8tf=clHs-{zD$=`R-z`&qQ7j%MMT}|x+fuIhO;QiGKz!X$I zPeHJ=vE}B2rYVR8)jO4`%mVC{%mo;@qgsu;~De5tF+4&WL( zOU%?u&(G&W+6Gt_92`8=jY|h#a}2-*gE^wEq0t?cs&M;u?3puXzWC5&)-II~10D%@T9IE5TlRzGzP_!MUJK`rr9B)8mt_%)nWMU!( zoLPNOkB*qjk`nY7i~(%qGy<6*SgbY<^iw@3i(6P&8-bcsr{v&(1587l6Jk|mt}7bw zK!{Z`zzFBTs)GD}vv$CgkquQR{xb7xhMcuCKeYjtz(rnxsOi^Ve|`D#<=t;A zYU=C$s*57ee==ce+06&Bup6;|I-y&5-(W8iBf>xu!J%YG{`jD;-&c2^F4~>{x*X5I-~Xrh+5dTyUH|3HiC+mHElKhgnc$H! zjJ{qvh*1XDN}GHc4X>m4=TkKCY40DvLABI%9~;!@{(L$~I~0dXGW>SYICz+AKeNe0 zf8Q9?K$A}WbC18j4Q~GLBc%U*)9+vYA9c7D-u*+sXUJcqM@GG<=<)jfbHu*)+S0t! z=d#+<9;!g^t;5o>oGSjRuMxKPKObHD@6)ccU#KR!3LX=T@nxgx-Fo^)^jCT9ZR|8y z1&#Ge*a(nZFY^0&Y~Lh)DS_>>rlB1p#qR81CbYRyX!%$lzvpC`6-Y^K;&3{u5Vioh z@*l!H@V77@$f-IBQVUz)9`uc>KXY)(3HgsCgZ8n1%jxR2h;I(MW3`Jv-d~zHjE-u3 z<8N3q(KV^4Q-3+{=Qe)r>l-SPZxgKbq7}H4|JeTomWo4jszFd+!s33qOyEti?bTyw znoAu2rqI?>c$?`H&dx5T^PighyJHNZvA3C|A=H$@EUl;K`77uaJn!)JbkWD~*}mIX zwmoHD+ls3%KiWYZv(uB}x%zgant{mEBaZR2gZADyIM&pb7F=&X+{uGU*qDnj7p@-l z{W7tAAdMw4#$VB&@f(I8`I(-6^Cw0K3ef=+E{S%o@yj=_y=FGGb(L@@BnQpzTi_u| z(9y?HX*%$XHTcfl`dGpAL1yue$O*fj1!%G#s*Tq%t-QQgNfr0(bV;?nhv;~;VZV^a zrJ`l_JMKZ`O-9ITVQ&_z1WL^3>w7vBh?a@^IWx)lHGdN-@KfXh6`XaEe}@kbRrfP` zd@ffTm?X8Z1*SXA^(VavwJ`sbP|ME6M$En~$&BLB6G<;hxM{$-)y+p88Y9P56#Oz@ zUoPZ)Zb*bhEk;WA`YQ2D<)`^-X8+5ybiqV3cbl-;{bbd>p#`)-MKYRJvV?()wu$S{ zJ3?iiwf9u1r%~QJv}l>kR>JG=yht%hlJ?|w78W+S`Xp+1FIdi~%aDLv7E zv?fuWqRtUIIbV}})8`OO2gPSZ{FVCZ%{UJfvU*DhC7DJ4% zD$VRL@RUTx-Jz42iAl9e+E0LCu1umycr+3@n_H1Po~Z+q6{4Lyc+tM)p^iKo%+Kj- z-XCfmeA^LW78*ot5Sh8ObmRT|Ll+q!1>}WvabaXXWcYGEecEF>TE|bzbLYw7%5dIs zD)KCSGMj1=8<*wt);3=9C*L-flEHA8&>PhV@83UAS5s48Bq-R&*C>ooJwh*S0DsoA z{sW=H?f?twx3XS`*SXp>!Tf2WHdk|Ibf+~U8bn@ZWm-1c_k1lNe($O7pP*#g?^)jC zx0ZYSx{%!_D2z&-u#Rx7Cp&Bk+>QsS-n}Ywg|@vlUjkIUaN6WzU}M(+p(D znQCDozKUOe9g3|AvB*eO&@LdI6uR@M@Qc+Rq z<8}oy8MEoTC#Sm$IBWMMtgYThqOqW}eONYC24Y<>8glrwC4EyjVz&1>-@gwD%s?#S z&x>x*r=}84cq)R4oWPwHpE))+l;p5wI5IqvvK?(%mzk;l$c|2`D4z#g=v^^U@Re@! zU8Y4!mSr;(s8$eUzS-zS|C2md5w!th;q$zrSACmMXM}fYzKl}2d|9ub1yl)v3LnPO zteTkn$WUnGY{O=0J(I1P!dp=kfZRZHo{QsiAE2g5q6g%bGej0EIgs zh)2%qFi@8)Q0l;w=`tjXZs_F?hBSbsK;)}tW0QkPsI0t$YJK;#LRGi-^&a{nb7{X5 zaYA=h)*+l1j75@X`uRg=%DRi@Wef)@ zE6=2gUtS&#>`7SPaBhBY)uSeHl1ij(>`hg!CRZIqeGXqJ0zqL49CG( zAr4@VGp;Qo-@I7p(gbO>5#KT(S5lvTj5Hg!*C~lKC7-%}ibK(>w0m+u$Xi=oElKfH z91gBx@ZHB3^_95%eMlc1oQ!szYs)?y?_Z-SR}nHLg6;w)N`ZCoOy}`8cyfV=Uol{T z;un`TIy#vME{;U(nSGud>H~Qbzs2q>=gp_d{&;d{w1t)KHkY<_{qd!zzP^M&2}@P` zrBsPc^8mnxhL|00CVL~8H%F#!1eL)MSoDP4J-M?wEP&|e>Sr`$2H3%nRFgRXG)G5A z<;dftK9S5Td((My_B3NKL^R+fA0R0rZ*M$IiT#v<8&U^5d7t^xB|wqsih(=XpV{=y zgYs(6Hh`9`6$uj%_+=M0HEs0FVdW!-K(Ards%w)6Th(_>)X z@E@AB=|j8LPkbQg!U_TD4;fB#MSG%}zKlbWi)z~Zt4Q0+B;WcQH~?36AxGUHRf-9a zH*K*|VR-|0i@(kadt!zPhHp-({A_aj7TrqI1|=POC*%cM_$$HkyWn?)GU=?=5gWjT zrq^C3PQuCz@U*SMkLo+64qA3ylW}TpPi;DP@uDsUre_^Cq&pnv&xZsC79M^`d*O8! zbRX!VOep+hl8y8(bZ=3QzqO{_ApnV%p*rz|0xLg&)rb*Ii=-aZKPQIFpt;Oshr*t-6F?BSRK%7X~`}{&;`h zj8TNujN8}xN@G)lU|`GRL-pj5pg`?!b^EU!YX-8UGsF?y!oBAUa0QkIMHhAR2Q~Ed z%MTM(++UdhWF-lWpAi#NZE1mg9x76#N)6G7!^%U$4q9 z;DO>&0gop*L+KB)WW79QHa62T&}BLDmGgwXwFruUowRMP?OgoTpddh{fFDuSJMaF) z>K2dry-gUZ%HqdH2$NS3oS(R0BvQB)IkqQrtZ66ou;a!$X;gX(>Sb*J__NtAvAh|>2woWVd>H3=uQ2xxWQlR4R$Ys% zgN8w@jks?$E;(B>$7kjaXbiV(mR%hFlS{z)*h z&@24Hx}qMS1XRl^l`W}D&yX~E4BmWdVk`qKmew&*I zsk(&!(Ts0ir2$ZuZsHkR)FD+$;->*aT@pEs6C54QhN9)Ymv6dVeBzR|nwJk}{!iX? zQ>FRaivtEP7T&J11-kG6w*4UY$5v3di0ONX&VgE^XSxr$Or?(duN!PH#AO!WyA?!g zd{;h9eDha)M%7t=hu++|-$R0e(q$N&RkUESa-x46vX=ax4;R&!O&s74MGqm5jlw+s zqgb1}^a8v9!F5HyK0~-*oxkIc_8>)ZScaFmzC6Q;S|9QuC#_LSnwVrqyG-TS9kBRu z?!c#+kESc@V!6pNEMg+>wzrJ#Xqxy;B)09r@$Ut`XeFa_4~e&0fm93XYCfhL{EL{)@aGJ;IGb#5}%_< zt*PA1Xrp^29BK)h}FNhbp zj(lG)5n4>G|0=ObVyAARlm+$T#Sqj!(~fgRCO0?VijNKs#)8yaUy(*f*$7TEvI_mT zKce>oz4uw*T;h0)XIkxNVsEjhIxLogZ0gb{U(c2_bu?D>pRs|pP4)iU4B<5N=QMpD z^U&64w9a+Al3*Vl((~J6)5Y4W^RD6ZOH9Z=?ZSJBhntaB;&`1)Os8jE8S*XvGD!JG zjTEpjvkMk*dy+~tvcP=VOX~0gICvMtqVMGdAiPMD6-r)>2wU*3l3SL4Jt^ z5|k(v7nh{!z?kze1)ioA+u2k_%HJ?T%d_&T1LbA@#fI-Yg;A&8h4mgfnY z1|DW<1MW>;-33PRZf=`YhpDih?yCW&y=KsPq|?VYnm96NoKp0U&cIH zl4!s_X4HgjE1aQQf@HM9M$QNoO7B_+oVJ8F;3Xvd_@ySkLx3g0tgli%_lSFef^ zGWFN*n{L{zJE;E#JUOYu``qRh4{C< zr~1Xq+1bx$hp21oo@ZqAWZBHVN@KdgZ?~*FY{PZ2bs1gV7HDF;;MjM+J}OB;ACAe} zX?pJXBVzH&qEE%No@uzhez#60uoo_$>CcRayQxmrQ z&iiW`rszgd(WTUab-yvHtgXF*!x4xV8&xbUa8M)Kj8KLZeF*T1Ej8aIPZ1;= z8ymrLiQre1ceY{S1gz5WD~29n5~9Tn3F(@YC@7kWwI|B4wiT86Foc``UjAv=b#g4C z=4LWqGaN4iF9hWuS&ZXcKRW6Rs=HiFi_z_~Vyd{BW5L@Ce@g@MpuAl=`i7kR&Fzto z7&TG`-k{q#3zC)TKwoi`zU_@KW0pS0xAB4HB=P&Raj@|;klYEof{#B~uH4r{cStJaxSYhC7)zI6k$5HNBM%z%gWe5se(z-jZv$2jRX=Ac36 z=B@|uP*O|(n`0) z7<5Zcnji3u1%U+l4n4t2;fBvGGQLYI6-~SZ1{afDkBuIi>iO?Z+_Z6WS^h?ECIX?C z3L4}Uo7z|BgIG|WYxTZBs`*RhXos~h4kwjnlXmdQkN)Ro-$;i-mi>W{WW(XDK=y!` zc2(CrvXOqO!-vmHewrhI2WfNB{H|lX{sE{~zhp+9=$;4!{zXMd&-*>>LewhCGZL=7 zjh&Hq?O7Ic$-iO5!s4>gpydMYVSO;Ff(>MXf4|(mx_?E^k-iKJs#>k7Q8*!CM(5?{ zssm!16MU*E>8Yf5Yfl+3s9|0f+3hBFzI>Q9V>d(sDoIQo+u9jW7 zWmop4=L~9qFCJ^$N^glpL(Jiy-4*t8a@ly{=Bt=!zoono7E}x)TT6Til+=Bz#r=%z zhB=*NG3DzEst&$0sj*d77ar;twfW?4VtQn?gcy8@P^x!xnB zcHgv|!I1Ox_hW0};VL`0N=!QX$l z)k)b)M-P9^1bO7i6UmM(l`S@K7&q%K4&S|VxkO}87 z-&M)q_^fY5Zf=zkvJ5hm=ZKtXZ#Q61+b)KdmYKx1(i(rQytB$a6rzQ8mX2;u@(;?*Tg1v85_5GV_Lqfq7tTF@_|R>1V&Zjft}Tf#Xz-S2TQu~Mb*UZ&v6sK9!u)8PGkBVbw-P((qwZm1i_p*K65*Z*PQ*cRhr6Y3subr$C0vVhLp zD9nY0hL(tm^#w;oWkp8*s`?yTTtO`^&H$+@D7{X?uMp5+W;v;=~ZV!Zv+ z_E^bcW3otldy|!6g{1tJe&?*!t=Cy*W@hSodhyTy^lWRAiV^3jYiyKAc5fPY{|%f@ zdjU3H8z&qa9!?7wdo@D9!hYc{T3wSd4{VW3l~qA)vdF9CKT9;HXGpm>yL?)?^=q)e zYcO4z{R0IYiTJd%sqN18ni@%ji&f8&n_;3o-Z*5|(J0^8XptdloPSR~j+lXJj~1gb z8xU_!0gfoTA^aN9uh=g%%f!b1V(Vy`&W}D4jL98n-(TBRj1{oFLHz4Ctpoc$3rzW^ zV#V%FlZJ-aQII6_2j#-S{Y1q`+bQQxz0uLql0oi|;K;PC&B!=)D!Svk(53tkuq$N= z$7$H8zNaMWPWKYq)!A8$Dhe$765m`lNPW6N0{n0Z6md9EC_;J<1!kZ-8Smb+UROKWE+)}4 z;L9K;Yzn3gYI_<5-B({*dk?y+YH$ClJKyGFgVpSulA%O}{1%0lC->B{Rk{PoL&bJM zAEjbsgzN3oBVuNGFUVH8Ar#pF! zjOcl;UX#xm=tzo-la&cLCW{d;Pa&BHzj(pqCqb+x>DWi%f`zq19k(|`9}b7 zNzg0%RqJw5u^vQ5#YOozF6HY_DwgM(E)u2(hC>F2hSDl4F?;mhfhnuUi0kp+y$&Sf zZWunUB6VfuM1T)f*3|0RtinQ{($Xn?9XJO>oe&RCTo7_zZ84oX-qWUrgawnUS0|45s5%WSzQ*|-oQT^~2sZpY&yH@U zH|#87udS|LlmnR{Mu?Y5UO%Pa$K&~Vus`WfV2ojx=Olnrut;@s+KEUXB`T^rI@qj@ zCNi51lzS0xBP^G`K6N7_sx+)v((6+asZb*5DHsco;+*NsG3+kpmG3E-0l)shVKuI< zfl~>gvpbU%sSSjEnC9>e#zuA9KoUIAe2jwZ+Aw4?Q%bqEhe1 zJA}5RPTHTwSI=5$X?Z{Mt@k6N&qtMWC54A;&vXTy_Vk>)w*_KdeMOW5Z14iwgPM-3 zuDUuuko*KI4GLlg4sMCu&C1BQIy>tS%ic4GVWyYx&{a?ffEq^-3~gN&;_09wea*?{xAuq19TOb(nP4R81S_aB zr09H(j=E$>CZq}o@^;ww>H?TP3!s4Qe@o6VNgku2iPI}-1;xes`I&>B*Aoa*I)zEJ z=*lWDbroAR78V&66#O7Supn%|Pua#M45+N;PJ8kom}oDyd(>UvpmO)_6JYT{J~=i! z`?8cwp(gO%z%im>NhJ_o<-y>98>#}AUgWh?)7MV~H{mdQ^0a}0A}mEm{FkU;y@Pe=cTZ2(l7{>)Zs;kQ(%Fo=qgN}hAp|tc2)v=easw3*RBaP8uL2DbXus4h< z4p)=!GzZ+P;&g+Gn=ormNlMaiT_Jj#f#?avc14b}qOXC}cU``;2COk8uYDdOuL_Tx zh0oTS;3vQ(LTYzlVnahiBNn0}V5i9b{x2+>#K??3S9d-w>Y`8 zUV^W>V<^IY@#4Fp$9bclT8Z|Jd56DxLr9frY;X4qTMuRjoMaQ7ne&c`DO89S1uC3M z?W}Rlz<^Fzm{464w}zHhacOBUBH+?8F~69Byfu2W>G8tUf!JyfZipucF~U$jq#f%k5AeFnA|M zYKdu?;^f`G!{MH%N7aRA2Q9zt!thnOu48^3X07Es2RnV{+nO`63K~!)aph2;Fq^+U zY!@pCEnokndWca-TEbHHIddQ64xW)5f@e=ipsHm2m1SEI-YqG*Hqc~sA_unW!va4h zX=G;XF^l^KrN;VS?sX!z?D4#A?I*C>^A7Q@8ZQ|MeJi3VBGrm26@PW47-yBsN@Od# zf7&~tDL4=tVM&+V9ZpN0?$bPaRxDvCzWT&CnQ~t%Z&Oq2XJx|?2(I9@Sgvu%Y$4wB zRVk#%1XRaQ`Z!cQx<$eINoGv z3Dge^!R&x$)FJB70?^gg**+R#tTYnKKoA4u>Kq6P9&kkZ_~dC9iYLWG{;G4=cr~z% zSrsk;&8!Y#WZWPSkEd3%HGf-3`Bk{^2BESIULjWqEzhb;nRb)240P&M+%I!5SyUYH zxEbri7?reheqG5~#@2pCj8Yb}O&$^fq*Rsk8F-Bx2;3eLLNW?hl5lliUlTclw@ZFENnP4Yo8IhnuG?J5oyY}|= zpfKIeF0{YoSm+4IlIh>6F&;;HzkaAx`ml0Kb+n1l?}eEc0Jx&<3OOSqDl1#AYw$*U zyt{AjKY81)=T}9@Tc*Jr76X&r#(gs0-cCxlZ%6YOU|{-B*hu@OdVUZsLyIPSi1zk& zK5%gEmfv2V0>S7Wd*2y0$e;|@ z4O~$e`#G;b6#17-z0_L&$8ktni0uLY@T5$_dKuPrjJ~!7jMwD%YRD9|LAKB2GmZ&z zh!)clkR>y$n9h*Y-r5rE4qFIPM&|D@$Xlc;CnT>@tynbhs=~QS+nqd`T+P#{_dV;k z|4R)Zl#ZI36&4QMtT%Za9zG0HA{_9KLWREPg};o|;Ejiwc*QHfF%-a@TdJf&qk3UH zW0V)^NbrjS10X0&R$dgI@*6tf&72D|LqUPpZ3|p zQUrs;b}Vjs9@?dg+GjZw z`jr~_T@OOVzony1)K)aY-7L^z>sd#Mrz5=u=Pa?#5|OVLkMGjG@^9Du$d$~>*0Aq3 z`=x{;Mh(6aVfXzXKbL*a{BPVZtU~FRnS{VuGVXdVY>>+p1D# z1xE}wrFgbKQ^dpiI){Zvxn-1vhav8Lg#@kwE07Yu)G+LTgG;N0%AI?!pp&A63-rFe zCgblWzZp##GPt|_5n+7*E0AcL#|hPJpoc;I3O?tz?a}Bp*ZkHe6(=` z#t*+J+xm(D`!d>7g^K@T~y)WIk4}SS3dJD4JO{qV)Pwxr%VC;|U&u894o-MBK04ga&j5@dTsbWV*%J^Ulwf z*nF|!1ZcCFd6VyQ1>1kLllo)RHuVcwOO!NRRCI+_bk#+5#&!Y7bx?**g}+n}Z_IgS zE0m1LM~hzZJL>eD@n)Qb z4hA9dHAWUfP-^+8JV|lK3)TSpZN#mgLbib6vY3B?&EI*lR23aGMXN&Hi{HW?UB6qk zpB!kGxU<kDlYO+hU zLmrn9tAXddVw;e*nL*dgR*mt_EqV+y*^iWjoT0Yk!ie{bb2z|tnwql+RzRG$n!_t- zBm4=|*1m<672fI@kxMMhZsNeFb6!yt4% z)pOipVvD)6nc#@5i$zqWC`CTJN71(DWNtTx2d$g*?O!X3 z3h%kukd|GVSrsCGBfGs{$Hh3#i-D%Ad!NsbWfHidK%B_6so0um;_KUjX3g1juoWli}V^^>nnuq z-zHVINO~2MGNfa=SCNd?Js`Tl3>y~f+(aSVIA+sN?*@R>spLhWD}ZQKq>vRT(@s-= zR85U~#|EQklX&fov$f1&)27|_R+CqMsXw#3Zq}&yllrm4MMb-8uPh~>T8Vq2|BJHH zwf6KUMZ5Y*2lSVJHR8}er#C6v!>pIfw{aKKHNGNqF*&R)fi5vDA!~e?C(yAxW=_b? zw((;vv(VgH?->;S(=$bs*X{J~?r^_ZMN>u5`64qk+K)m}OiTMp^jDOO2a1 zU&Go(SQw9=^pze@5wcTg^`_Pj=W$}@(8$oRu<$>Op`Cil%AhGDqbXgJYQM@pBWHkb zoUrBh+&&p)Q=JNQ-&EwrZ`6ffkv}j6PNk)DwIzn?$8F4RJRSQego0)7ta>h!EHpzI z_P4mUUQN0?y>6`ma{0hTVoys8+o3%l`d!f8d>^-O>>U=c?2Y7!*3i+3=hWGwfbcgi zEtIc?CNP`Uc9?4~T0}HT+&guFANMhie}Lh{#&qiO(MySjmU0uXdX8wfJa6sF!%A-@ z*=4v4djCcKLvT5nTic=bS6?ozTP-o=mp%{IbnLupoELf8D|1DDMg%IIw^-Bjf#?C$lKKhMwqcy`otE z7{&{mIN+{2I2>(IT}~}8SEiKMbY-#+7VzATgkhE>5Q!%5pAo9J3j4KB$22ALHeOPP z0f$w_jT82xE7T?{vjV1{=f|32@-+9RZ}IGH*2waZT`Q>5Pig?x-m;Q-&jVXQVe z6HyiQfowfYJE70;_YQH_(d4BbnH`h!J}nOK9_pBa0w4m^1OsJG&9i$wOngCXX<@0T zXx?{)Q}=!;jA3|qI17qe|9H^>0_S$F&;Jo?hkpF&eo(hR7){KA%pI%?5Hf40LO zAh4;N270J+*nd~2!8Rt$<0QTjfr2W^o&J;pE|E`y$#}ZqKb0uATOpCFESR!CG9mh%oHcBIUh46YtrcMj+YG?;cNmeQKby zx?Y0JLq$y`i+Q%`5ii%-Y{5X=nii#mt=QfQ^Shw!D&upO*go;eQ&>~Vqrzj|S7uM) zzWA9Zy9*uXEO{%nY5zFNsb6}|urW3z%L>^qhItZTu7|_}hGf_)vAw!BH96S=a=c?- zu&{A(DYQb=)IQJbgxi_qDBHSX1S9WG-ElYtONB3*X8RHmiAP6AOKyi7c&w>|*-bn= z*r=+g7znJ*A{%&NLHWikALsnGt^>gck$V2!+SW4Rdx<5l5(|em7n|xjlNh%@a}hcO zDSG5d0MDUK<85rof8=j`%}x6Zw5I}vAVQ$bn9In!$ErfAK13|5hQalN?vEh17dF0B zgSGb6Tj5je4bl9P3dyRN5qn{N_wHlzF#_*T^u*v%xV@q)w}he;;CNLLK}|C(`6LGa z6erD!U7FF^5qj=(?!$_yj$u5Qj6usZP218Msp4KQEgclw3;4}D(ycaQ?lpx&w!YPG zR?ovTwysXr|3XJ|)=*XQ`S!rMtpG&V$!&~%7NW~}+@%=>%L;}){i`)Pt+$?#TqRaf z)sEXep*xbaN9r!_NYJ;^(w^hsV&}VRY%voRF5(m-zMXTBJmBee^#g;<`J&*E+3a8n z1qb^-ME4uG&d^}>w;qErz<&tP1&S`@`5E~vRxyg3e5_cXs`q~$yr<+Is&$HBWkQ}3 zOn7@LWRKU~#qp*V9V=`zqTl=65=CSaL$%7*4}l6?2g7NYxWgX_z{+n}9AUX02kVS2 z?9*i>mYaq4(iQVbP%9V>jULM7!Z^!bxup%)<>TX$W&EhCOKKV2&xdoRQ1)OZ6$TR=x_ z*0xcO^&po>q{P~koK=i`O_#X=FEQAR{xaB|o;&L30lh5TT&AY6abZZ-O{PP8hS=-s znNd0g1QOy+gU%{6cRO{U7vAj;zZ5Gyu-QlnHHtK2gZo|gd+i!U<(q z*b@7sf%Lp*rD?W8OHum1N!mfe4be(`EK)~MiOj|3$G6zVnt5CPqP(<|qO<;rH#5sA zx&4?T+mto?$)_oaiRy1}0V}mME#q7V+}+`mPk?H+;LCaPjTiwbXwL36aXsg?8nTta zHl^OC;yA!HjfuS~c)0odR|nQ-DeZ}$RB_nbKGE*8QmEF@?U{ov^P`%$+rzHXyBa6$ z(~66wB#Ku`T-Mh@+q?R(v$L;1%@+xn_nt?&3@5S%7r4D==X9RuN43^SIL0E*ReC11 zVpC!F?lnvT+NxA5T_dXv7gKVT*Z2kx-YT&JHhaJV`yc0 zz^jk%EG8$uweC>#gusN$FLU=n#UN%*&qbrJ8H$^B#Phym>TS*>r3^68#kqi0rayQ2 zX~8B+GE~P#(xIsX>%>0%VxtxNNea^ThG(W6SFsYXXEBF+X%&o&ial0Jb}&6N#D!4~ zhb^)JzhYNbsJ@GeWnoX}W8n8sq#KmIo!BOiOGu=;&K4U$(&FUBAM=ya7z$%&(cezT zkBuE?`pCaDU~kPq>zi6!{C=N~gQEkRl1c`r4rvsC+(9-(ri^cT!)5Guhy(Kbbv!M^50^?717ty!&Od z%+a!LOB{*QSBFu4sqXA#mSa|?1ItpyexEvv;|+n{OIt*73#TIg%i31wn3LN~-5O|* z+=&pkc;+~3rgEWEq$qS*z?JBCyP^?xE|7{>cCfdX#cXb0Wh&yg-?Q|zD1VlvB?>$Qt*{hjN?_3T^L@S`CS%qU9n zRk^L@LeC3kz?_>?)6fXd5v$r=s35UbwO%b)e(zDmW5A3!|Gf@K!C#NsI&S_rCYzhZXJpTZ`fUKs9D_`J3N`GA4~-s z(9SA@nMpZ^5z9;TgM1H+aB&D0%rMAQ6g-NrcF)7vrq$dD<_>O07yQ+zZ<@@!j%yoh zHrJ62bw1CY-LsUVkXjL||1|um_QtGBylSUXgn(5`!qcPq4mw_OEoF>7bKHCdnwT6$ z3cezBJ@r@^Rv*3P>#m^lpuraQ1CDMtZoiY#S zFRiPy<?d&6&@BZ{aGya7GN_n9Rp#%{^|G?l z&bD^QmJ#-^4v@(lpjVBVmWxYe@9yw8+pauHvbEi_JwSJ$R;2SihZuvuG@*-ty^P9P zUtg#4m!>+$rs3&Xp}@H`p{V+dY=2ut!q%Ign~E^7hYNjS^J7TX?CnqI*N6$f%1(q| zE3}Eg{?)8*%$FG|BB@RH%p|8R&O3;;?&xGFvy>qZ0KLgf3CX|5`ZkuYqCyD(O&WM? z58w9teb&5Et_V#X-d1WcQKRswnpg^^DEAM6ko`fk#_^twu&*0wJ>W5#Z0%q{ftgK2 z!nSb75Zy@%b1nH?xj5=r!h(W1a(=PfWm<4xI~DLpH7%jfsanY~+qYq(G>R~x(!C5t zGJq%te5&v}+c8JGe{iRRrxLwnB_*u+j~#$bI*i}#YE=S6yz0IcE{1-L#6R2He<`WS z$RwYnDB&qjPt~IR;~BDNgWxe0E34~{C3>nVJYvEn+6L1&QmI0^rC$-Q_KsksrfJNL z-^s5y6(#aUNyY_k7P&$WD(o3kcXf?wi+Hwqb;=8LW@zfmJE)aCiZrui60@jF91IY8!Y8Y?d=mVFi+lxOVGm!J)V@1%Q%=li70nRN>JO{QJ~%=1f9`1DPD z-2F-m93$J}t#DpqT)} zvOX!1_WG0one4wl!kQ%zO4%t%xpkA*SV54|`2XVTE#RtLx<6h_j;L@9kj4NJkdkf{ z0Ridm63I<>iUBGmEiKY)Lb^+2Bb}QL5!p0I3kclx=<&S1|NGv{N8JKD=9y<^)|$1x z>o>fs9}8(E5!vq!K9hWS6?S|)>BMOq11yX|0yXKd>|v`0y&4VUU-3(|H`J9WY4ONx zYH`Q>5yH{$+u!?mUPntM1!JR(equn^c0m}=zS>Hr&30ZcN2tPfip8Fcl2EuLZiv)w%-oBzt2P!dvH$ql)yF`(;SEW92q zO($8q(>}F3Cr5Kjj!!=#VtRLUCb!E^*deZ42+rtK&8Vp88BFMvtG!Krew2KEUr@N7 znUeX>G}R~ZsHjWx9nGo3qcq)>)#vPYj&bodr4H#vEu$=ZtIwivx7ZkcPnKrmuEGR+ zyr`lOl2;{|p54z|Dq7}RO{k*$HP)F4FF-o+U}FY53K1O0EwV?^Ntz^jR?udm(R;5& zmCOX3x#zY#66L64GHtuOnv@{{DL1 zh|EK1p7|MxU>BG<;|sy27JB#eavA!Yq&%T<^S`df=$>qlXui63eEib<($cikU!@%# zgpG!_aHB5?sER*}Jj^3vIoQWOmmj z60`{}=X}>IcliDsx%*7K3a)^5PHUnZcF@n>a5eccY=i!39Z7toqHX>AjDrPd;W} z%5S3XDIU0rR)~F6rV@rIm>JIJ~?s-f>Ku{VealNl{hXHt5F;QAwS&Q zJO2(Ixn_9{ja-YoYR!r7n1Ph~CYO!wLv}FwNNl)v7rT;D-=U9x;mjYc#Y>*S#9W;o z$=1YDD16Ws{Gf{8FfX05Q9NvDe~MJ)Ukg??JWTG1x_M?c_6y9bU^#Voo{Z{QrDN}=T5~+!{%trYmb?KCa$q!A$O1P zhBlY($N#^j#&#yF?=*NNy@9-f8mb{*U;n|n9aU1Dg> zc4AqBCxWyb9aW&7-v?=5c~O*6aQv0p!*8V@_TKjI-HGM154E$?#!V_f{pe9<%_9B0 z{kiQuhc7SfZ(%T%ag*x`moIPc5zadPw6=rrrm3`4VBCLCR(P~|7(czu z7%63}19R0$Y-&D$-oZ&Bq5OEjt83(=S=nc1KVF#0$jxmbZEamg{%_j-?gUh2-Nkqm zCfRRa(jF=>_KRfEv7*KZrv!t*V3I7a!ItinXz<8=Xhn*cKMC@x8?2p10V7LJRNg+UMEDpS(|82BwF5y^%s2x_U@nIWu((OvW~)*Q&^F|sd^QBZ#5P{)YfE~C4sY2# zrGe3XVmsQ?^hICyCyw}d(Pk5Sn07%i9pp>h&pN)je=VWz z{&a@zW^AvLN2M!Ud*qopT=3$liTgd!y$`Ku}|t>yK4Hbt)1uMDkj^$#H{&tc$ffr z8_FQYi}Px(t}h7)JYx7ApBz0>tEnXr@!&f60>|4EgrE?I?v=O^!Sh`(_o=tv%5yw= zpeQ3#&M)v3eoPh|4duJ4%V)THY$;@AWTGv((V!igx4f(? z6Qi6N8R;Ym<@(rH_ukp@Q(*=o!=|7nC-q(T;1N{e#EKFxB|8qpw;&6};J%dC(()MB z5uf$)0+Vs+NZ-&Hq<@7cY<+@}TBXS)sf=T*poL}-ucRgm8m#J3ER-|Qv zq)(iv5#_HraYA=`#vO3yG#qX#V4%fj&zaY&R_^Rs8KkN35SntkF7LzL#7NeOx8vil z(`3+C7#H}PZWMFn!lMhQlmU6S!^lVy2J%3L^DndBy`!Dtb6(8n=E3@BlgpF=d9Ugxox6Jc9T6Gi{gwou%$N8{6{5@BUaU-?zO##K1_; zuCLo|>@e1jFZgHC+nVl#5@{;-94{4J*%B)%x1QiT@%gE|f(nzQ`LKfbSAMI_ZHXdt z?DfW}mjSCVO0JzT%nf`v-$xD}{8uM|_SAh4uPui;kt-8R4q&5sfM3Ho5QNt5Hhqwq z>ZPK3@~cy2k;9xFh*;7kSAq%YiM7t{Eonl~vB*39 z_~GOK>Zs3MSfH~~rK1+&o%>_^?H(2tJ3>jU=8&c8(2|oGO%sZC&J_rxf+5Quef3X| z3V~4X2q;%dm+iu}2a*}#8}~tNGYxFjBDSuz*6D;l@$xd$NC}XCW`ICx$CFwSFdHAQlZH z92r&c@L|%&ItIUD+>+PokCo}?f7x_zZV_?fo49~j*l(%Lv{?zV>d~|iS=WtPGz4kb3vweN9)18-u745VaCl;3I(*&@`X;)w%j*>t=BVLt zvMvxZRx~l`d_fgQ7||Jp4hmYXu5gBehxtLHbPHHd8E<@2GMKz=gU(~k)@KXPr)r?` zhuJ_taI&TZt{}In%16H^&8B>5M&b{EiJ*IfhgMn1lbSaY*4 zHg0t~@$^_H_NixebmGFETXnRasL$;rH}}1Z!7Dqsu?d=x_D4#w%K}i^UHDvZq z4i7~T#sBU1fJEWcSf#*)XQRc*#P#!&_=b2_gK@WvTqBo$HShPo|%E9s1%sP+rR?zDrN~)f7X!w2FuQr3&Au?ry zB)NM1i92~bT9PIP*YNNTHze=fQU0fUKM``6bYdNOMh&U^;oo=G6Z^L@OHceo4Ek6r z*G`iaE6ECR812BnN<0%zCYU$0IyS5Hw<4KNg=f;rKl&kpDuV-let&)9o@Vj8szE&* znqtG4s+c||c!tuJJ3alo6YQ&)$$HvpninfJ_Dw>`wu!GqO)@zV!>hA@52)Jm7ppg1Q#^r zH+6te#)YqTe4xz+D}G8sf-o4ptlV5FRkRBHk&!{I?Fhn%R|Tt6QSrpw(o*%tMO9AYgxR9D!TAG&jpwihn ztGZes+3T&ZFs>ePh@_+lrnhI9Nc=%dbcylCH$wMO+U7@vKn(VkB?@CAB90(KalA@r zfBzg8Cue3-l4QO9{qk}?Wc)x$5C_Kp6#-}#RP*zn45}RJnvpd#3xNV$uq51z?1U%x z9u{kI8ewQ<;?&Iq6Q9%zw<Hv6Rdo+ibRjD)`-E$Bbje;e_cdXW|vGKW7sv^dMalbes{9;yqz6J`VLvT_Q zF2EeuCdqhngRFD&scZGwZEc#lP3}>P8|PnUW--2HP%`fu9!?q^r35DU2K0u(EOQN)J{wG2d5d_{F>rM`$)Cf`#Fba2F}o>TluPC>J&IGbqWP;F?2J@>X-F zhip6*YItn;s^o6Ezi{qYWo*O>ld@5Rsu^3+G}8^XNDH&^%uZeVu!Dor!~S9H%B&ts zb;RQI~`sfDY3sJ$Pf@qgBahq#bHivm`sVzmym2cNThhzcp2D-kbWc_+Yw+DbO*vNL%vlgG#N~z#!dt zswKvaOLNV&2lawnqNp)Wto4v7^?$0H9$$MjC8>m^d}$$bqcX2HCVZ-gGEcg2d^BZw zFo}!pC?WRA^K>|RwsxlgHuphR3;igew_TAiw-<*THH*!|%AXO*dwYLG4U=AeTw!IOF z+o+;H+{ITJc+eN;+O$MG%y{FbB5JHC;14qq!0n%Mt`gt)T;kYONr*7E(S3e#wT!Ey zYQ1Au6yR$%eyFmt95O%g^osqdy{_(V`%hyfg#EC!68ZcZI3`kxciqn@38NtA)I4be z3+x*t60*5vTa79H5;HEmulR~y z$$U0ATDtC>*iVd*^xB8XHxMu*IK98-Ry|5Msj5C3)nK3`A`);6@A0vs%3=+Hl7WQ+ zrrOu+x;h*R6WT)* zqm1@^w33~r7e+tK{;%U*9v@qK;GTE1!^cLMo6%0aIJ;6#XZ2b6aZ1}i+y1*fHn$^- z@FR?hGlrKqqr`Py_NE#7>2wx#qfQU~&z2B=;#jKIJa-1oLcdpGC1Y3Fck$&yk`5K_ zJR9ThxXADKMjk&u-hZ1UbHXY1`b=3{s)EvV0eaMUp!#fOJDq;tp9zHDFRDA@US6ms z&3`v0ZXvwaoIOgS@grqazu#52?9>tMqvB_ObLqcdfIL!$yHhx~nuXw|r{73RjQ*&i zB<8c+Ju+7E+W3Dq>TNcGuVVw|x(e@7%z|TVt3;bau=Isd!m<2fmCmB=nAWAH8#~_TSHmhL)??I!WG+kTlMEj;(uNf{Qt4&*0hXFMXBxE^?rCZA2Z2%c!RlD z!pLmVW+vB2yYXcUBnSIvs5#e_HpKRyQ@Z>nhU0s1k>|WoPp|yUm8OE79L>y$P1|Lr zXm9w>hrQ+!R-Nx9N>|Nb4MAdE^9}6l;oGS_#sfv#r5;Y`<-y^s!{H%=grfl!|7P+2 z*AaG~_xFsXgAZI)lKZ!OxmZ~x=r6e_PZq_dQx%<0m!Vmko^{d7brLt+U96ybR>F3D zv2?1Rhn1m)bZ;-~A;$ApizvNvgcKz{3BHDVqH?jNbfk#s`~VS!^FlYyYF+s<`pi<GEKztigTDo(@QkRbN^Lm*yLw`yu5!f79-+aV|(b!>Z!4P_)QnQ z+W8jmeM^k?zn}lJsrirp{Xp@tA3N)tA42K)Jy(Z9Q@AYp=ewH@-k!Q(-lp_lpH2C1 zwzok1vb-hrpV3s(uz&9hDNtM4UD5uR7E(w^6l{o7-`g_;KzpJT`GioxA^KMMeH^&mf)qP~_*gb)>~>gq7T!sYM0@ zFRZ8XiF%oC#^_pgS6P3vKZ_SY|GNp7B5!tkdu>~R=X3i{#pTC~62JV7ryViI-Pm+Z z$A*Rb`4RtX0VGEMxoLqe|JC~o|Mlj-UtVYM@8GXHxBbuXxiS8aY+vtl4cYS4WH($&eB|X=ddF)QsLTAx@jY$|k zuH+fZj-=hkd}*)HzQoA%jr3^-qs5NkA?1n49`@3+g1NNu-T`8pD27cj<7d#Jb>AI# zzZ7mJPE?Ql*T`ebrOf}_4>4zu(b>_!4Ca)2iJ{eML)foNdU^Y}nzr!*a*D93WTilE zVFj5NbO5a*(`$fJx1u3<7?QZOZsD<1Y*K{qtn*o|w=nIkFeUXjj<2P7Tgqf|ndUy+ z{pxp9vy>^dy`3Rm(D-s$aVB4?g>32kmVXYx*RyRDR+hY8!5d#+wY?rB<6zbtdadZG zB}EhM{?Y5fpR*gf=zCqjE^!Eexn$cjfY_$T*;!!*)$N+7O0$6Jwa3Lh9M$z$C0;Me zcHYEBEvz;jrXVvgO;7h*Hib_!s(Yg8Us5EMXDMao)_B`y0SMd8*@6^d&gOTAJMT~*^N(?%d){#g zC_$Th;u!6T|NDmPFY+1I=X7+i5R(u(^hh}yLO6zdUQ~cRxu|JN$2kE(q1BI5 z7#9>u22&tvF*n^a`EIh}4)VhuHmdZVsXY#DeX|S)ddBsE=w)H$ok);@LK+Da@J=(myOo7VQ+t`vDqo1Ss`u%HJ8vHYa^j2sNeJH9mfJ4|?rbVt=V_|wk4ViKl1>zf0l z{H+R+RHRps^e(?1ymmH7z>4dM=-g#RO#=fTIMw7jB4^5Kj&R%s0Pvb&MnkgI^EHc$ zxy0|AXCQNpib@B=&sDZB>NzJpK&Asin2E^<>J4-vgpmTz*+}6RQoDXtKzaw^M}Ia1 z#tA5WAErpNR?}WP6G7OPO2bjTLa4l}UcH0U!ng_W^QYG14FUN0`sDTuQ~_iG-njcZ zmE-K$5-e7xEdvJe=TEyhz0lAUI=w=(_EHr8;Txa2zP?-j{T}Z6i-qZ$;Zxy3<;+Py z9WP} zf)!V~M`d!`-il(Lmx02tq$+q@?gB_eM)|%7lBu`(Ww*H|7EZ-$P z53%(4t;zZwy*^|q?2%>-p_O?fkIF7ADZ%`u)E;dgnp^gTJh?=qbbOciA9!@kf`-Tg zCBn{cw@|%>cCqS7&OH-2`9V2!BU@Mq0^X)eaf!ir!&P%QViL5en9JQ1gl0B!K&ses0E#3dw zg^7smH42KB(fg3p#58C)-y8^ zRD~?{m^z>uFV8LW%fn)o+dXM+dLM-9Q^lKdCiz{@UV7rT+NcKfw>bizpTpa0)k|o5 z!{HDQOIeB^%|W#S#qje*{ZY3CHHW#>s96|>50BUOOy)S?7a_myF27m5vSmEWofcfp z_xG>^0Gd=)vlXG&-O|6)eQTS`>YtmFn5E zBY`{QXY`@WPWhH&KL6ipI*!qtgJQ^GlEBDzUh!^ct^JV&v)G{?(DL;3roSGcM$0rp zVS+iwM7nq*%K=jCf)L*|dt)>Y`+9WRdPZyxc1(;ddwt5lvVht!rP0JskM41U$$VdP zXo^hiI7d{$2T*W*XWW`FU=%F$kY(})Cud5r8#X3@{EvZOr|yK{|8p$TbDt5Kh<2`c zAfX$E-=~@N=9zUfV3;>PT@z_lcj6WKG5Hkp1M~(3ul*Ii{0K3AnlQ}G*j}X8Umk*P z*yz_{+W6K`%X3t3Zdq>57y+dHFR>z4W}D&xG8H%?EB{%D#7na_jELgx-}<1D`*qIA z9noT4UGdt+M=ljgJi_zGw-?f4Yi^u%>X*t}N0@Y49ot5(tUPN-YT zz%1P= z#2$b4^Og*U=qi2Xa%{rRbHHj^?{vnTxAbJm3vA`T>XYLVA32a<#FCY-hY%Yl5nI=$8^ zk_13Ow(FqHfX?=uwYPgqnfLA-O+Qb~Dp&c~a)2xOqh%ld*ZTc0=@aPA!r7dFAi$OP z(TnhTykFG+4Iz9o#6RCgKK%0ZvH!vS;(faMe;Fp+PiHu7y+27E`e|l@YE|Mg9%*5M z*KRQ6rqlp3uG!3~bexHwQ0ArV-`_sej?%VEO7K3QyA}YavE@$eFV{j+6Mi$f{})^O+oy((o4Q{yf-UT1>4t%s3Imgd{bB^6j3nF!FAX@` zm0ga{QrsPc^aYd$5yCGf+F>R@k8} z_|2nyQd+M+hRdS8H~9bV03ht7YJcw69W#>VrHrISs70&VeNZXI1jfn~o_r7s%&M~9 z#CIRx5=N$0z${?)I4*E6uIIzIo5gu!F87m|15kS9bJC2TSi7JJ+;_F+Z2uSqkMo26 z2~^dQmI8VcN?SUDawr3I;uTV<()$3ANb%4bKrsh^MF=lcz0rflF_6y0#Kt(RNzzM&s^)1X7pzq$ z=KawVct+=bZbA2C@x($-&_Afx+YVl``PaRr)F&@$X6 zzp?`R-?Vs-SC;`hsyc`HiN_)E6hiHV{zSFB57xuPm&&GaMA5F_I)wKeAmpr8x=PxR znP<&evijk4r~8Btdw@`_+w1`5Fwt#Z1It5ryd?L>Kqq1JpBrX2?q7xZm=|%BevlUB z7Z|~gjI=KOZ51C+^{VlUUFBTW3H=|8Os6xT2LQ@5!)6uZ3eJT?zKt_#YYrjN3XD4! zeDIgqqi$&fX9^-y5wzg;_2SlakvU6D=%*t8TExQUo2!6zl1>tyk{s-{anxve;$SNr#8LpKHcz$~cyeMrVA|In?DPH5 z50l@7D^aO`@^5>meGNQZ%$n^hw)dQofW!aS-Zj7$Jk{Mc6BewTw_Bd=Aq;3mD0Boe zxn{eXhRoi3)n6hYSF3c?E)1DkBKvdI;!)Yi`ed|R&%eJxL~$f9Ra%cHN@C-G0dL>& zG?uLR*3r|MZ|I#TX@|6R{{S5+kNVTI2^mvA_#=M58nB0SV$hkyPG&S$?)bQ_{VDwV zg-yojB6K>vCCibzH;&z6GYc?0dfTFV1M>lIgiNJMu<)*kX1SdV<_CgD?=R@}XKVE0 z3phM4cC@HQ5dMDfq+{555bh8toj~AtG8gg=v&x|+;j@oBGIO6d7E;tJJ&p|bdQH32k5o*IBR1jlQ$e<^wM6NEh(+3@|_g5JKO+QEWJdxJ#ve_}0l zcUG0#)V!85TNt8Q{L=3c%IOcjRlP;6T4h~oSY1iHY_2S~kDkxe%Tm5&mO$`(@I1ak za#Ik5&VRH=ow5q#LDEp0n*!MGZX=e-V_&xSAZMKEJg#BQ0xmwK>hV%SA{c9!LWj%q zxs}Vk$S^4vw1NmsED~Z`J*24FFoweuRhuX|w6+gz-rA4O`FB#^qCi5=yvij0YxHqh zRWE5&4?ZeQe`1cLZQLD>kivw&5(|GJ5gy-prhC4^KH8O|#mVi4|&}UUhJ6@nyH6N?U!S!VD zQFf*lHRK0FKh@_nJO`E6)x{(~uk2`!^o5TXI&Vc`xWJNi=6P>QgJ*9vx-!4q14ntI zk=1{BwFBiK-V?%t^Q}CxVil|x$TJ}GB5Ah zB`(PNUF_{?Le1t6mgVbGQ3>I1lDmm?(iLtOLJ!wb|1+-G4*rH%9x{^7b?lCso6Qrt(UG0;BodHF_R}V`^#Lw&@{rr#^-w)2##O%1X7c>naG%1B4$YCnMuF=r4vp z41t98+Vp~Pu_lm90aJqKf07`Emex8t5xBPKf&t-->@#o>MrI6ezM@m5Onm&YD=8bo z_LcGG)+><{A~uxtGFi}95nooHJ*n?{vFAL?zKjru>dXHUhmZaw4xN?;yAAu&9%QQ0 zo{#9A8=R@w_eul;rpQ3F8XjmReIDyQe=f|dS91rdJ7i*2(NqGOg!5dSJ?qY816}v? z{5KAmnVA6*QldStA|@t@S^qL=uKPQM9^hxtr-W!fvbTIq0%rw$aW&BVJ0(as@p{k)p33RnJ<#0Z->WCct> z-D`?Bsl)awiuwoBij0{D{ekl9B9hw(zXF41(&nCZZM7`W zG2*kZm7J$JR7YSVnMC2gJy!QTk)pv@#1zE-jS-0}RJIf?t@yBM+!Vih>`1C)SXN(G z7kJ?%=4)Tg;hw&mpI3BrJOLX{oTsnD*3AC#Qpn+(TQC8_6YyHrt458)Uo1Xe2wbAj zf!Ip5w=IStF|i{6;zDr8(F-(;KN7)|7r@*9Y+2y{1 z;@R3>911IjfdX=Z@+vBshWS3w2H=5wFQ}y6ZRy;G(vJrK z4#8Z3<&1o8M_|;#v}`~Ox*70a1dN4R#8pQGmI6wUjN^J%9_!8ErW_!GiCn5l{0Uoa zkKyUxyjtey0*S51tA3DWv!5o8vREiVxou(xR5Z!ETxSxJC201ZCV1gA)|JoPv9YLI z)Zn-%N82|c(shT6wG%y`Md0Y<6rE0pwo=TwnBT6;y!rdUz6G_=ET{pyMq<2i-wQn8mdQHuhHjE9n? zk_8#gGb6Z6ut20xGa@y;>4qJtoFPwwO1D={Q)_NQD|;pu>Ajhup_ zRMfcIoaYSGB^s~MPUCPbk4njEgNLG^B9Je><5-M)1{4GWFGw-6w0$Yds^{K`qjUws zmQ!o$NARzCQp@UTu|Z`z@uf?dIn|=%9_`^LrGN-G4_NB-IndpdKjV28|0o?dv9fc6BbF# z@+Z(tO#4y{sikha9Ms#l12??vXI*p?2ENB)ySCrV**Dyup~Rc&?E2i_74$gyD$hU; z;HR5gTX5dXNqfGA`Zg-i8XQ3QJun=AxP1)Jv|q0y8vS2DEMKPe#CW!gU~asC7BHoR zMjpJP1F`)Bm*D8tI!ULY0-p|uVYLHs>iA=|5Fq78Z9<{s6ws2clzUe*f!WLi7r|-C zT*=ETfdtTas7Y`=r=lDV?n6A85m0*N+Oohh$FO^4c+_Y^jphomcx!7bHor-B0I_TG zuhRj5JNw7>41f%Etu7xfFs^)3?=v$|U*p@>IpJCD+m`1K z1U~cuKxEo~|K?*SZ=1GFz6aEty3eg}@)t)0k^OSBw_&_Cmygoz5z+9jqg8HgD`g2! zQN%dZ2Xig;G;!?}vNH0piH05SM8&M-OK`4Mt)S=oVk7iQ)m72gjCP>Plgnyid&T?6 zWvy_Q?`qft_o(xH#Pjjr_)ajfsrYP;sOsjvagK2fX<)?WOJ$Bz5jgjw7oT;a zx8elak+WI@m^8_QzT`r*<3yjGj-F0R z<^@$yH#d$?ZxVV8Rt_vEs5u9dm#)Z5NX)#ZlfV_Ib9Tli3(!Z+ zCq+l>?)^CBw)c#mE8&(5(Fdr z*jYYpH_tgd>hnpK$;i{A?yOtj-FJJ@XoxwirVa+d4Jgr`b#50PTS1CobLAWsMz&rb zF!8(_iZIr+`!GJUGnY`EXCOrBn;=?I;f|E$uI?N4;+UaQoCg=%iAYW~ig_7P`GgvF zh>~&$zt}$NXXutIT^p^EGtri%8aR?UEwr!MKbD@ee{Pd*i!)xsuoWwzcts~{wx8>z z&!cM=Tx$!=(NdWV=LcTttFt<8WeJh@4pTX@#ItE^Guy6dH)rn0!{)hkHt-w1{8 zkE)uqq1<+=ihYz1zwW#9M}Di+R8hJ)77?fb0eo5kg&K?D%v2N-azDzG9(PMGv~O&z za-#ei*>HL0+d6RCj#jT?7#pWfCA%wENUPk81QT?7X=$uLlX-1#z4(`BmX&dX8zfei z{w`(}t<*cK(=mGDK`6L>PAkjG-~@J$Ey!0T25E(UUHwYhO6XucuLv~-PRpY?Fef48 zV7mxzUEc(ag8N>ATme*ZKgm{IIP&}n=Yysk&UInL30qpyf!X1qDSG+yKn&LkvY;Sn zZDFBF-m==<=9yA&D#A)Iy$7qo#p0#uq6S`Vq6&(N8BqQJhb$g;-Vr8n9*RY!LMNW`x{fpeSpGKet6^ovCBvKlZ-`*2?E3%M)?J2 zVY@g*L+~&BpVTN zvTv;ST2w1TFuhuQyv~~10~H;a+dj8nzCx!lcu#tNir1qX399|n{|!HLnk)4tccx7c zL10TMzRFg9EmP@3U&|oM&6V-j-L@8Ga`%ouwuH=U>BTqR0RR~e}bNVv8dd}Ar>?qXt$NCB-_MfcS4P6j*%OeBH#db znS4c6(Bv-WO`&z+yYc82l)G%dOYr$It&8@mjCqfe*62Ods|5~{?$MeK8^WRyK(D(} zw=(VP#JhHhQYpNoHnd&m>CE>}l`Xw&fhY z6xbYiBQyR`do|p_;$tc+PNR4%Iys$ESV*`zkBHc%7+t2kWm9XO_Fx?CFBa1~7k*Rm zedz%2byrti4QAEku$ZyQ*X>UFRCgY)!uB+?>{A|Opr>c{F8Vit9~w9y?&_L3Jj~At zt^`sX4x$<0tdZp{In2~M%uqpzc=JP;!FQnZ5ak+|_>yI-*4YQV;6Q-qkyV*40gg+- z5Q>q3rDN8^r9!%*ChfjRoMx_EIBp^Hh1lVuV@8{S%H1A@{xZtUaJwaLAyVfBF^iyi z9cs_girWL>xVfWks2$i>3E6 zzXe z&+Ad=fUzqfwo*{MscOSL7M!=K1flJEjZ(LzlJh!>oIEdU$N_pT>WEP`><(h?}LP>UV4ib6b=p~8hC zr=`e%O&Y7YB_VjT`B~EYcr<2nRuWJW*gE+hos=}hYXxcAWLQYM4ce?qng0HUPBQo$ z8*nn%RzoA-)}yz{g;z9@2*OulNGObavTPG7<`zzzeq;`xo`t6Pt{i)oVxG(0DSlOb zPX4ov??`P<4iz*Tvo?p~4TY7t$n?F@V3lj{#<=?k#L<$W_{#zcwKNMK6~a;n1ubqy z(KR(T;!&9!1Kif*oLt=8Or&SbW;#@#H=IMtV_-jPA?Qtn&BgENN+SLaf59dZwYsM%dv|asn{X6B~ui1$)u_}6Cx4-5Hs$xw% zL^<+2G{@Imk;qXVs5S)3iF^$g-;O*LjVh#bGY($l%wf7Lu_FHbw48E} zM#}p`WwDBRY^BBX(MBa@=lWn{`@o51M2&e+#IGS=Ey^e4BCq9c5>vL{n$ob9a|=nZ zSrT0uU-Jv?q_^)f!^h7)FJ`&ezpSo(c3+{opQN4U~ZH_Z7ic^h?-D83V&-7Yowv4R|`TlkmDwvUr=KkM32^YP(U4u z`x2|9IDX6%kHp-ZwN^dyE{=n6>dnR?{>UC&O~&%V3&w~Cq*Ux))Q%Yped&+SyA{!A z(d|pRGBXHaDbz|EGK0UWJ7W7z#SqV7`!^|yw#KTxF)ziF-5vKx=e{42C^Y3Xui_>+ zy+%y%{35~gubVDV5CRKXn}3F*b1b4B0*lqo{&O;_bVS`pwxiB9DXl`PGA1U_io-F? z9HceqBIQj(LEpvj14h>ZDAQl)>Ko4(ugjtzJ0`9KQ|wM1cRIO^ewf9|Z~ z?D~~-uOa#z!snaG2`Ot|6cDdTCi890rEo!2w4J4@C;C(7LLb`2xpdY23tW7RmL_PR za3^2u=#qT}N+{xsoRLv8DsNNN+uND#f^4kFmIW`qycd|Kp(wt6RsSY0tXfI+wb6^_ z=BftubzHTgmG@JlHlcT6jb1&)g`J@TzQ_N2t2wN22pI1v0knJ|*$#HF=_*$aAv)){-s{<7eqHu7}M0=*Rt zs$nXb+1d)D7!w(Dh0A({{%ggk2JswEXHQJ|&3(t9jUyvU>3wEfx^9H{8`Q(^o)s$h z-^;tYbBu;_dT2jl+L))xDa{k|P>U(0y0)XV5H&F{}y4X_$R^Ccl2Tt(_ zeerm;afLO!cdqTbMmfYLN>&Ex@|-VUew~}z)a#RB%9(|1y9ZM^e&{+5#qU00O3U$N zAB(qH;CT6V{CydnBz@|K-9To!OLTWz)D*4NN7qtAV{+O~n+>#N4p{P4bQ1UXX-8R- z%&7?oY`nRq7e6M{aPS~;Jaq9Tb+C2XU;K8G#O%FOlLORTtXYHDz?h)+5C z1zFQqZZqp^{7>T8GesearLS#vCJ8OA@;Cz zMT3PpcxBTu26UF7c+#S^-)AEKO(z|0g&4Qu4b5g`S(6Uk-P;RXXJ8|tY;!*Xf>Go0 z_o=AjG25SUk*YtpP`hOOYNEOlSQTRPv9Yu{E*1VxR0zkpfvJ3-E-b`J4lPzmN1S8~ zC)(xvTQaHrRce$K^M-DThJob?ZS6ub?!cDIwHVoRij z!zgU*t&U&#;z>oYmL-<_5W$({NkKvKZ9FSegSp43}*rOq0 zX=;%X?)i2qf{r@eH;#r#*^SQ`wgDSfoc#8PMZ9V9#I@qe_&}2UI{CB;t1>oIk0S~) zYizO~4f6vMBjRP#;Si^Q(<6RPRFc6&OB=V6F3YK@T+D*JkD6fSK;^D@)td>lP@>$p zWqZ|Yy{DI!tw8rj=A9PB-c`5UYZ*D73e}$(dTL!$zKpZ1U+vN7dG1h30xqxT)A;K> zwWkNMeITP4WWYK~Mdao#y7m=!gWg0=B2Zqh7F^8vMe+l~xfNL!>~{JY2YHLxB_+`h zS3f$T{35#6yVFmt(U6^(&;OI}qjrU$q2IEql^cwcO&^VBpS^)j>T`ie}gQlo1XDUwuy0GED zsd)8F-%EE`TQ)c^bVy(4q$gwNpVbbVRjmn?k{l)vnlBG}do?8E6_r!Gl2UG5jj)-` zNH0|>m{qTjgj#0c>c7Gmk{x*^e)r0ubh-%oHQX^hZPb!f zb%_-A8ssy7opn8oB6LelojC2}M#yIQSIFZ3M2QiK?`x$OLE2II|B`{kFD63ecckCxdc z&fNbcVMUh2d^W*(ZS7=*H!;aYM2+vR7Q}jL)l6GGI*za%48To7Dy_Z3bibWC% z&N-n$9DVA)Z_yKnb$1 z$+zF$6BF~|;siL8f3qOLz2s=R&3F8$f=b)+bM#@x6PkD(1eLel;Q9N`u zOS_C1mKi->P(Cf2svIsg%MdGJtu?l0`q^vus-C19CKAmuglw=%bF5H>gT+wDBknJ1 zO_!~BC+Voq`At83uiQM)oP}-d=9aIriUtyq25pMso$4H*d0j&C+aFPs8oa%C^@_KF z5A6D2#~pI=kVQjVJ0%TA^3SF*u<>iLM)CU_dU{OF*j;(`&L&h0B@wzWw9BZ!D!_8Cnq^I;(d3RCz>?mTHs~zNj`_g9<}ZbLN`_*a<#t$*FC$bYnN~7CJ%V zSw$VU zm6(SQ3Y9?YBe&GjYD#box_L_RTuwm+rx0H|Yu5MlynhAur2DYdKH~?eo6n%N`>XiGH zT2YL;J=@9&2#NgKf7_MEwb)i-$9j_wYzAG%8mDYw7YEVttg^w{0r&dT`?_4XuVzVH zEE2TY#Hyt@`l|#tk|qY%iY&iz(G;mWsxq#VXEJ2Ip)NdIHRCceuQ~|+e6#R$dgy$( z%Avq_-BlD?D>d?&lh)!|>dCu0 z&#H9Qk&r7XO_L?cB5z&#MqfH4Y#`?n{@{ACg<2saQws;~Buwe~WwNa}4&4cpqY{;` zvNR$d5lemGcl2KX02oOmq{Yr(;&)f3S*fK#?ac^xlc5w zPo|;0w@;!DT4y2x*32^T#5)6853agfB|RCLP-W!f_7ZumB`lF!MS$}7p}1L!x`kLu zn~S^qi{{LX8>UKn_ZIHb{P0tr8N3-Y)vQq7nrn?hVOgCB9TqV@=vK%1?jf!$o1tRC z!91$TNr7Z4S%4-$9ZrK*XLXs7d4YO1?bzi#+XQ^JII-u{`(94PWK- z8@EX%=B{;dcy$Y(eAv$UFfsJ$*pI6^n*>W95`1*MD(=fVfOgn?3~$>H*M5GXuhxD2 z%_)?mqW6LuT^M@=)uF3B((4jQ?rD)oE_mg5gTz-uFUfhil#Sp7VeGcVX1nB(c%^WY zgeU(GZ|?!sWcJ02qK-N?97h2agi%4HE4}0BC%H~9wM0nyzH|23?d-GnZ~HnKiEZ_- zYHVIYRCQfYypk*iLj^am?s+8DHAV2o>n3YN4=NwN#W|*Y`jI?`cz~Z|-tCH%V|ndG zU!wSBUZv1_xH{pHe!F&7$z>L(_ z@+-I=%$D$^kkY*hLzVOd!Vo}ft3BF`^01>sc3eL*3(vGAmc_H^d$4Aq#O(FGmBXwB zpB7UPtEkl-D@WBh*yOV^!YUOc{@LaVvQ+IEHO7n zN38HFZue33V7C5>ipkmIvvrZD7?S>?by(io`wOvp={nII&tU5JKmJx{+J3Qd(_V6aUPPXSl8bgxJ z=l#J(Gl95)jQchzWzyIFP$CImIF>zkhx$$vEQP#=PpZ5QnR3Knn2(znxG7)@e+C>C zwK(0&%!Mco%8)ZiFLwW*GGbpclwLt-K2O``h)DIA$FE8R-^(yDf)faZx%tG;@!n_2x(% z+;8kuQQ1nH72C!w`KmNwq!aOjiqg5$9x*MJ_eyhghu&-ozw=2i1ECZDlv=T~8YN0m zUqBQDGyUg`CO@$#!y+7Gwne^JQx)q^*cSDk{AZ?%udZx8d#w|= z%Zs^ii*p3948KLT5P~1T#eMnuQt`BbjdJqV-aCg(alNz_2e9gwFM~+^_v_ z`;v+tp2Z~4@B&=3B!Dmbqq^H2c%iT&Q}o`0mje% zx(yIXwS_+SV((&UU0k{bLKp=R^a7uJ^kA(wJ6pi9e~apFQH0H$h&+i;?v|6|G*hmf znTMz5=n61Z#SB0GfVsfNu4FOzr2h82M#ENX+D$;x}t^29<4UB!0{6~y9M7?+j(XSfDS6<((qPX zv#)-JRZ+QmGg?l-qh}?fL%sG9W~q;^B)9GMyU|GjmZ-o6R@w}JBdonX3f9=7U8q?f zDf*bV-AgO%ceHBp7clYKU;k5y|5>B@bq0`cp|0X?(~E9dzZn%SToQig`3gKb0KWIf z@BaEF9%LXj^`8uK6^TKBm{JE_w)!A8%>dQCr!9%AFW zt~2TUX5GfdpY^cb+oNS>^}5`R76@d&R^IXl|0n(4g$~}L`Qtui!p^kTv=oZMUF^&o z!QSxuv6{x0vm;{bZYCH`NJX>pJdU3_FxR4R*Iedqu~Z-Sm)I*evG#}r#C@tN+v2~i z@qk5Y$}zv5(~|OR(E%eAn0jv3PTy~EnsJbghZ7NPC>wxmGU_qC*!}ae9}NFV|H*gW zR>=91Lo&MU`#Pd5LMHZz(ye&-eK}4Ts0&xDx?zYmrlCd99?HpCW!hTJZh!|veu36! zjA#sJxMV6tCH%T{sPl~Gef%}XlHZ})?K}S#&%Skw$6Dc2e=8X1MS~zwLdZ zYbaSEQMB;-w7td4ZU^xL^3Q=_orh)Fjd;7tw}5rgl#bN9A`rO(4FPb;cZF2@&h=w` z(wA=_Dv>`Nd9KQ3x^oNyXlm^SEpmS^3M#V&cq%U+QzH|Ts?FRdxq_?!GE93AD@a=B zs`3Kpyy!M~iu|E z7FU|KPq8g>|EmNn+YfW$ZdX4)IOxt~mCrL~SrEbscl8P%!`9o_v+D}lsOFwc5-#kf zEI<~S+&&)cHn{%+!1&ZSrSMM!Fdx0p-8HUzT6k>*)&tA_5`bCdzp($&BM7@$T^F>} z=M);~TkQQNGKeLTHn;b}y!-^anI)UgPeCIT`B@Nk%QC9r;k^x21B@HL?!J~&|G`PP z0!NAlm{nOtAM<}wuPD0d66VH#^C$WkkdXjLMqmL64K9shus5lC@oH?9jsUuI>(9k^ z-$JSHHX9jsyiE&H>EBl6q+nRd*VmDj+g#7tUUB`6*JBx9u}M;LTPN2z@B%=a2Pbq) z_`hSELb~K?icIBk%jd8|9YmSGRs%jn~|zID#4CG(&`z_;f{4p*|-^z z8QK;ea)C5Q`a}$zyMkwEJMns1%Pi&tkgd!y-JcvBYKHnQHSgx#reikGvO@FyWa^(V zToA@zTi|*^2}?L65asqM;S<0?OWPVIy?R06DJpi)+SRAhUR8PFm}gPfb+Lz`?0PYK-mrZ#Qcj9&=BhS5G9`x@0IRu zPl)EvLl$>^jVA)6o0_f7&{cr1bHf3^l|}OJ?orjKf56-tHUMTBzEB$mFpRQ_QwEjo z?OX1LR!AIvc{e*RF3MSnW+dvKhVS41^$BO77Cr(g+h}^we_br{eCgMwCl_$IF3oE{ zzX?$MR<3?t-M;8PzM)S2rwtz2!$*{~F3sCV{XQE8wJT>)n{N?@h!+dy%Trf6Jws z@^-HXCZxBsbWqz}O2GF5hwW#r#4CnW9~U9k)^e)VDwGQ2O-DLkRTrq1c~z9T_H0i5 zoaCombz8!9HCryMihA5cjML00KBHpRW43W%eea|0!wF7f0aCo%0N?1n0yAV_YW&IYljOl7MNI1_i?bwMZc@Qt-nA9(C?jNmzxdCId6 zZ49;*cv!$ai6zx|2GFRxz27z^@h77M0(4u*;&E6g;N?f}RB>K{M>hV?MyS82{}UP{nbbIw<%P>m~c z!*zd6c2IxV8u(JGr~U)h070LnY~kg`gQL@2otgL5&?KwAMPYhsZpnAtV`Wp>aP zKrb!zP!#Muthumw#W)?TkO>igimpKyUlvHZE5L8gGX&kOP5CO?!x}rrKl$) zzM@7vXqZ@vfW&T82tlPp0}LJ~BmT2z1g;DgDY&$y-E5m#)xbZwtU3u2@gG%sCs!E? zXjhmb0)e~HoWKqPN44g_Av~wSPs~+HeUi}zyoCb+W~WB4CyPCbfHvp&>Zcm4-7_4D zMcXR%)jz}^(hUqY=CM9{L-rpy7=ZSXU?7||geEj6&dNm>y#npy- zOpT(|=YG-k*^<#_9i*deX(=@P+FR*VO)ZiTrtc}yX!YPnu}3|CIt3CPr(Y?xnDt{r z`jY%x@@+h84vgIR4+_v{jlmbcUymj<1GgP0`SwZ|mc6%D*3&xEBmSSRmCnP{^k51u zfnc4Q7KFm;Q8MkzKpURlPqbZxN48vcrtVUD z71-VW`q?X`qQmsyjpL9*)&xk=dnPcaCoi7@$fM#!|UCfgi2UsbSN!Al@@$5&yT97IvetLdR!Iq%L;9dDLghDi@rG& zA?YjqmcT{x=Aiyr_%c@t06|TPS6r(hIiEz!_}dpf8nwlzPC8aU__q!6tu>VKo``_u zt_znoz#$8+54%dneNdED1_uhYXF97`0{y0{;Ea~hb>1>^5Sg71*cIAK2U&`BmM#o; z<{xv&*kO+YgGy&8P8OKBT3A+;{Q%P;ABOPH++GZ#it1B&qDidAAJGSlAvNT?>5GY` zBLdU0Wqdy1g!Xn(g0 zD4o;4ZI{uT1YRv*D&O8t#`OTp3%^y0DX>0uR0zKNl zJ0C^XSF^V_bX2zepQ0aL1Bq3}8V!>|2|~vArp{itl<4nrsJoZAsUWjIp7AZf1PspI z-TB2P_(Mza;A0N^{4hNx(p3cPl;ur!Nm=@8!=1@Z3gTK$q2@n6b1)A9O2~}t7j2T_ zjJa^lqQ57VT)r(m9G!BzqRmwG3Rq|cb`YQ+ z{bdgD3ZAW*^lMd}gEr!zL!tfoAJtly%OmYniuf`u$wt!D@u+T8rwq4yc0fDVEyOq! zWm9*uwXrloQArJZZ2;=> z_IDGhM?r7u6*=4@Vgr7625CUC04-DcG+*TL^!SuxHood$*LFK^QFv(BHqoW8bT>Rg zUm5PJB|@B!iQ_o2EELFgFM7}{6GU+n=GZ|L7sS`k+|+3jF0(40T!GuRoTUo&ZKQv5 zCsHE1pLD*E5_WS4GemA(F*&<6GDP)4BidMu%)e~AarU;I1P@=Q8ujywAc6=Y&&NSv z0A=M^GXol_2nA@p?9Rtl^RODumOFeBucF+Y;&~(r1)2Eygxb41Yz$D~6e4(}>NuBIFyI-Wa)6pY2f(FcNkvjedDX zneb#Yk+#X)Fnvk*LLH2@ypn)IZmR)7Wn+7fL}|MEx`oj!ozZiF*)m?9`>&)x%a$zO zj4Q8Gt4p1u&F6lM$r$+s#9>r!RNc1OtU{e^1TjGPjhGucN>9ZD;oU0YpbO125CpcM z7ib2Lo)-V*$jFO&5VCa2&sm$L(EKmf-OT%O4FEM7L=Gg6ueg*{X6SI`p`^iS!`r`W z%-;iEaAjp72A8%!dEA`o{JPhY>-9B~KY`5li05+Y%ap?(^Q!vko7u{fEi0e{O_Qh5 zXuH>4#o4xQ_BZu0IrKUc1*ToZpR1Xh`+J%oSdU6P!j_WnGy{%i);u_-Q9xHJVz51B zD>)HJMP#0cUyd1J*ydaBl~*8aIh%g0KHFWPMCIr1sOmq<#}*eCAImso%(%oilaVY_ zb;2G7nFFHOZQV<%bOZfd?(D#c0+W(7wQMb4-MjbzKYA`_VEUw@i~v<2C)HwM?#nz9 z32N7aegz)q$*ET}Pki%8MoL$m^A=9k5Z2EGpg?**pq$w3LbuGUN0!Px?Sr+WQqrYX z7_T>uays{m1@4q@UQG-tTvWqM=)8dxLaHXGQE#_I6>Bg5j>?RdXw(~J&Z=eLVzZr> zz&92AEK7h6rjGB_&&=2ZK(b!FT$F8a5Wzu>aV#M9dL3zL9P)LI19zu?ZrdKs?hsMRZ6GH zc9q+W`|Y0EufpT`C1L!6$IjRu2|IE*^p`ghIwvQQ&H8uTe(PNl$+pOwxy8C^(5b75 z)Id&#AvkPP@0KL~_&WCLp|Arn0pal{Yt-#{1?ZNx2S_w^nu(>!%fz{wg?3QPvR;;4z9( z=pxi$)UFa41M6ND5^EYM>RP>yj7Gj4g+#J^63!0+{x9{E zFL<%Ck9{w`Z(6CWZS4yDExK zkm-+GtX@>~T;EQRgw&M}0y6&hUewd`kjX0Z`l}PO4&1^AtSBF5}w6-p?6|=;li+?y)RzeMn z_FMkR|A=n!SQG?zGWW|5hVMdJ&$lx$2aaqjKC zHYDekp<%mDZx^`;)kGIfV0DNl?uF)>$`?}<+1$^ey%v%Z1N`KIV`W?3D0Eo&7Gdk} z47mlz5g)W@d#4)bgv7AGNzHiHz?%RNfj~@~bcqI(I3^q#AU+`Dt*7agwu;hr_=ez% z0x(3bS+pDiZneibB3 zO$4E-5}qUF-5aZ1_VjK;HBtI(^pAEQ1H$$@4)xMx(0IZsT_|IYE)Ji?M@Jbl>L+vF z1XNu$ifg4skKI_J zrNCkBvxWL0eOaQ={OI52H&Y2Grh9(nwCzoGE|+$UO^B7zqTCU>sc_A6h&PHr{oSNHOB?Sd?exUL%na_oOG6`Q?wN`qFHRgy$H^NWrk3?cq5 zs+nxwL?goM?{NPH!-fJv#Wb{;SdD7p+TwA$(vc_9IZlIM703a9vQ0$CbhtYv>CT&^ zIj7t+u69Qc84(p7b4|jV-DdU5tkJ^M+?JW#nv6`{lzT$95hc&)@@c``8I{K4uFoj^ zN-}n_{8)$nX8KJVT?ap3zfP$GmENc$ZN|~N9^MsR6fSmDd`pOJytdVBV{b1adMyusGaME07yH8Sbsf+{ zecCanps(RN4-=qlE`9u=O(NwF9J)oW}yPoYT z>_t7(>yj07r-@mqtPd1~_!$$QI;0PJ_@xgqUy6GB>MdV^IEiiXGvF7O;W$l~y};sb zTwS2TqcM@qzb0ZfyO@Njfo{emsF!9-oO^;8e8Cic@ct(Mwj5|jJdi7`nv z)xSs~3^)j!k1D)77XLJ@^mNW^d~swx`pi{!LNDoR*#!QC%b=Sfr<@>non8OZ#iOTa z5@=dU|Mgao0I?`{N93Z_Oy$I)1Sn)opbq!A(Sz+U+kX)IGdxmu_HwVWNa(CkSGx$I zV#;LJg;~i=Z)XWG@&YkLRnz_mu3Q}1*}lBr$U%vzfQ zfW&l}C(2oGt;P^(0B>u;z+m;W@4Cu6`^@G@{yVQuX3Kzdb5b-`6aV`l#c+rg@wn>Z zWX~@5q=$_xEYP~iuOi=ZziGp5vp2=AySjJ4auy{bi|gMyj_h6g8tdv9y))5sO=0_O z!%HU!ruNGXO0FsXu*8l+_r8~N`i^H!&gmY@K49fE^H z#bu$4%jV1bUDV<9g{t)sK!@uFr2zQU8T6mV@60>mbnve8w6q(tFd9*$qbI8y&p(ym zfw-m>YihKXnWCL5LsEr!6<}?V#u#-N&<{m0BgxMNVEHr$T~bobIx_~W#{4w52SE!T zR8;^=_sM~UoG(?q(M#4$d9X>@B6aY5xh@tf2$UM66Pr>m%({H_Z+N-KWVegw<~6BF zET=6f<~WCN)2=t3LPu1zo8Y#Vd)0EA3d|kV8V~q#TXhAwy_~wQ*B7`&Tjh>r+_t4o8gN@L}w-$9^Pkf2Ba#x4YoMX8%X*9y#f=2yRQye0N|nhS|Yq zwa3IY$3_OeG5lsG*lMlq$rXH49Tso-FGxSTmFW3IZ)P$7kt)F(9U*J6#B%<^7ucv*GsIBz8PlF8ox7 z+|$qRA#EpKHu3zTov+Q2Qy1Sd+m%EBISuI`Za2_dDbVCBmoN51`a)chc=RB1Z5$#{ z$36(LSnRoPF6sMKlPK@1BrL*{f-IsZ=A8`NNU^hO3k|Ht`Hkk<_slofFgs6o%Hvm< zEMHjB`s6G*jp1(ajXvL4hpix`&*5Vp%6DtE8MOJ70StlXKf#$xC?!_4CDq)RA0W3> zZ?m_oPD>RpR)2z~)Cv|D=F+1p$eHa5pxK;XI#Eg4=8KuSS5GA8t<4Vzz!H+Bz|H;9 zZmXT@PwW0T%8Vq$>q8Uze%T8Sh?TM$xE(p`O!^;oqIxpJhz<6E)7>_JsBie2fRt8t zVoqL=%v|#9E4U1i4>Uio0qB*sF#Otl3ub-LvIqvY^|LQ%S#6rtPL73MX zJq=}_3C(1F?6hmCu4G0svxBL=JeD%}~?59vF60dMa+XOtJr`%&i_+qfN~VN`L_w?)D|ytE#?wqhG%p7dp6-#@x3kdc5;EfXB!V z>F3!-X3k+GCe_s{h|g^QW=z%GR}0>c@K49aPdo0v0ZmY9NdwH;9451d&{h<=Og@EE z+ut@x78^Mw995WngQjqHSF_Wt&}eP!kK!QD9iCa??K>6|5%E(Y6B7o2!+@j-KyHHY-Y|A(G5FHaj~U#B$f6Z>m)?2B3SlTaGtO1WD#4Y@Ri|Sdy|d$|tfgWQ{By zDi?OR6tCBP}g0M#{zk;2Mg=$k@3re{j81_} zYQKRh{<#wC$a!18x0j4Ube03gnfTLkUj&-d&MISgB2jJ7BIgYS8epJB^>wwakLxqJ zLvF1&-b5W9oPoCDd~2Q8RGW8k!Om&IrhCKQeAt6H1u3osocm+CD&Hmi&2<$cy8(xq z$@HCt)9Vayza&0$=6vNQ<++!L@86PJV5$G@6nW%OYEh9SOwwgyuWYU;Fq~haa!Ic< zbDiKYSk9G&D6a zeUDS{{1uDU$Pm@7KR<*Kwcaf~y7s{H252zP=kn>)aL2Dlch#5QqKk;LRim#KGb$_5 z0MrPx%ThZ-J9wN^+|=O5$G$*xCjygHWEyv-Mzg+_wQM={jD$|Sj85llFkGdl{gfW7 zi1sRXpEu2^p^bdxgW*lxSiu+Emi`=D;BP94kqYPk#!o<`1Yy=4iE;d!t+s-b9=K9D zSQjKkbC}srMZE)&sRgI{A0Du;d2w$_U2Vf0TAIIwXleBOQDMQ0in$^YW}{k&kin1! z{>>ZSvW+q3%E0hYJXi?IMT=Z8fmiH~d{DpW42MUj7C{0EYK&*bzuloZc|?{Aj$%n#bKo8T2*3@`t;z^0X7&h5yLP z&cU1l3lkd59S*2&vp%>rku$vEu&~*^JKdf0~v&FwAHKvbj>8$M=Dx&;SO7b9Ib{p8Z`-)0PEpOu^Yz}D6l{}i~Kn-hW^*Lh?4 zrzv@M+KSWrjB!4`1b*yV{}iU-f`u?IsaKXb)FNI{`tU+7jo{~|?zfr}XGcT>IKux& zEf`ENd;5u9p#U-9cQkJwr`cBh@&wmp(!P?=@J@Sg*=|(aN`)Fd&U?=l2d$LBDqR4! zQZHc&#Vq^q!m3?8dl`kU_Bqe)N+XLb)VrW>S`8g~sWYM^-GA0R}rFDk@boy4|?cNf-1= zm$0Jb_Sfh1iGCDQ6;;jsnD+$YY=~iffN*~ElD-XPu`KpuUPFBX(AnGift+o6aH8S~ z&dNwoDZe%Fss{Al1|xFQ(2V0)H1|IpByOf?1(Y|W*#Nw8%-DigWK`5Sx!!M!1r%i~ zV8ohIyKq_ZkfR^d8(KRoc3@{6hpQ;%espzxXWH){QD$@h5z5pncmdjBzScmVdJkqE zE9a<3KUr{Rd*0EpovX(4-WnbA2*|j;ahaq#pYLyAp;KV^mnUWk(xp?0hk!!n;u6MG zE!An(-vR5A2zn9n!tlv=)>}K(`E-?^UPTrS@ndJQgf{CX{KEOOGQSq~e*CvZfM?Cm zATR@h8Xw_c6C;!n{|>asj;$LHlu(tJoJ8vz8^`42Z~gjs&MMk09!ySjXZNc*b)w+Y zJptG?Z6D!iGk2@Ua}-a(*pMPHqFkcKtuSV3c^ir4s^$6=`T52in9} zBL)BvCNmWG;4^m04DUR?r<+4aZ*Fc@-kxJ__7WC8_uJsoN|j(MDSU(Rz`47|ecK2! z_Z+ADKS$+~)A@Er)FBgtpNP=cZvCd*pel%OS6{L;syA!6e5?W0mcy{#)4F6wblY2* zF$u*wg7m{{92|oy6X6{k9)*!>G`r9TNva~uDGBj~gWwnpxM=7IU<#}zHPCuf;i-X4CEA;9$5B>_ z0()Q-t;80ZVi1pl^woPOVM(fkfdM^5+Y2gEE)!o)@~J*6{yl7YT#!MeGC1Y*LxF>C zy);tY@4a|ny06e|wCcKuUF7JeqgE52ljBagY9(x$G=wG@(c}5CD@{|9c9cpmvQ&pb zMXQaaU!iZT4SCnz^F{uAJ(ry~gh#=(c(I0e8{B%s|9*F?lMU~W6hSD zuLXEd6*T{DS*S3ymwnd@sA+)6Z+*id5`Ky!`N%06C=gQ0xD&9_nz(CiQgR(O)qV*q zUP5<<&U&tS)iuz5Letnd=j5ewb+9K(Tv;iqb3ets7UnwFC%(G{Ple}jf_>KEyB+1` zEUyapL7|FyN=m_ys&9FQeujI$W$4g!XNn!Cs1Y8Xll_gLk81O?GW!(3jYaI46wu?G zABc~n_gY-NSsdJaND)0iYM<+O1Qq+_G@8Z_ebc-$D&I_r zLVFc(0{OZjB@VVn@x-!zA_k3yOEUUK5*B85wS~ zQP`d3rk87+Vj6n7onko%INE*il48Wva-*P4Lr}kQ!6RqA4)4wncbho*xZ<`RfS*}Y z#pam(s0itnN-VRuk+;gOYS?$nRVU?MQ@fG}J)Kn@zJ7{LHAq7vHeELbQ~;vjK$$0F znG9oczB3}<)Qo<(mK`-uYtFUpDldgHBfedvii8S7ewcNQtnW6Q4zT)-L3ioIs&(GC zd%N2c^;|aRP748kjFB5QeV5=dB;>m_hiA0K0gaG5^XB1rqt1iyYr!XaU&l(@;%yRR zVg-|YR8_oOVfd5hzX*0HOA#ObnvEoD!|-@KBSvMrEr?I;CVIeOi;)C2-4HpZngo+{ z0G}M6PfHU3bPd8E6gdv=^1++(0)LtB`R&2UUmmyV4Khr zs(rmvb93Q<;9MSPgjsI~;H#*+fl=oGgx`-eU?HCFY`n%YVzTl zQE)gA(z3@p4cqo$SvT`g&UcwIL-@C0$JE+lq)J ziW+nZi{xC2$lWxzpLf=!+7wlff5`9fS{xc&sXNgv<+t;fsBsYh?=>z{y&>o6Gz`9@ zF-s9Eep26@XR^3G>ia!L@tyRZWHfmM0ptOwN7?-?s#J^u#(k|X#bf!ci5F`oijs%4 zp6M|>ksOxS3Di;0`J4P#)!DVc{9mq3wulrzZ7Kp!%l*m6xU4Aqq47+w;ncZF#NHzL;2|j(Xq36)8L(_teIY5JI&LzeZ~5JO1vQXbp0eRT~5p-qUU0b3J}in zB`gVrKK5Ny<1Hsb~HDeSQDzYAmt?_A)#5}KA^@X4cdIPzPqVpN6Bp~c)Y8Rpa=ur z?Rb7TP;N`KCqr=w`oL}fyz2EQb|Hb~s^M{p;&0SuL3?iQ!zT>$O(U(_VpEG;tUx$R z6Kt-F{x{^TaJMoh+1~{%fMVo^j2?>6J5$u70qIhgN{d|JQKH6CTo$Glg_)^OyCYxD zbd_NODmTW0l()Wi8&_8rl`4VgiBL&>Ul(BF!pVJS*1}E?xe(Ely5NM|pWs)TlsS zX^~!7>Rn+>%odiYmcM#QDWC8IIB0|e%E}OG_N>d@2eUq|-LaZ%UY#qeE;l9$XhzwL z){%3Zf`=cz&QW!nF9xf}1h$YXioo7b#l>j%6$#`N)5_4E?;@d%p`{0kC_OjV>IgeM z?;$)}JyiUH?A+D*KtZtUh_h*nm4T@&*00HnqfDwRC9SOT^bnM6r%D7OU!yT(ex-r? zL>E9J2b%c->2cL!G|&tGxkd)NQn5J+;vx>Yl&AAWrmhoPxAcko)i`usBNEkL)a*J- z5rQ-yxRa!1!`y9w_arnj13ggG8edi|4B9BQ=mEXDyS=Vm;f`KumC}cVsq-S$Zn#1f}TgJbo|8uq;4Sw zw9yR%-yp0L(HhGbhhShbK!kKq&%^`|88KQ3^_#eult@D(CzvZyX{X)#Awy4g?1+ev z)&z>)7$`qrw6d60M&+*9a*stk&@Sm8o=ick3lPE~%Xsp9ft|3hyLiw%jc5rC6JUIE zu350W0@wQiX`~+AN?M)nt|~Ysv(Adj-i$}u0XcwdG>z;Smz~`U%#WcIu;9=wrL0@E z1K20A%k|SQo8dq;X|FFNNCBFseq|Q8&zJ9P4-){*h;G$fNQ~(@oNBgOxZ5Qz(7i90 zSv&;JxO^tA`T~xb6*aGv23EOarZ=ZMqeC3Kw>b^ksF|6N>dp8Rz2}MQAUX*D(GZ;n+^8vF zORQNlZG7B-VI_fXR9^X<3ZCuXhWcN4f6M72FAo-sXJ(tcg|{hwJB<4_x>|QR*Wp9q z{Ac-a^1*>hn@&cBPtv|14uQ>>A?bPv8|Wtvw@yr*&Q)sJ%NASOR#0-f<6WIE_c31PN2E@ zuY**Ge_69KG`+r zPE3}u67|?>-F4x_UvgsI#2ug*F?9LQJAAD^dJT3B>}tP9&%VD7ex5=XbC9c@O#@8O zI4>`t=D>zCfLdAKv}0AD$5!AghD;v=84%yE#na#E`_JEOm4ULz@0AWiiw6HraAfyZ z{oiq+@1OMd2>X9e4w?VO1`1m6kt&1#lR0bsf4|;FDTsuvJjiZTq8u2*J%tG5lmsE4 z1u5 z3KV|c0paJp@8RcF5G3DnLr198EL4JIxql1!AU=nfwC{lL+|^*0h6BNvcC;O|U!*3{ z<>mH$^O})te7`(L`WU$`&{V`sNW%ZHhyQwHGe?Wm6w5F$Znh`e&DaaE+8#7bc-r43 zP(P@||MzVtml|y0c)E1{5U#HHaJzD*ZdBfbYFrH)Pwi3A`+<*>!`HoIHA~{0+@Zzi zVk$!+YReHPd5b*oz>iIzAR+zqlz-^^LrjID=sts&@RmEG5(?Q56{@P7vv-fHL_CC=C1C3yDf1mS=}8Eawt~y zpZt$Ja(FSHvhV-V)?6=Eq=waNx|v6?-VaOZ!qtw9J-&6Q&t~Iu5Z^i#x@U~!W>fsu zbTLTfIaNzPG7wsJio{2SJ=)&5;dAt#;)8<2_jsJ{-{ZsF21L<&ma|u1qvTMb;LSdm zf#54ZLzDvJdVA(5kKVI5IS==u(RbdcF*Qu#!9D~-woi2?b|6X=9I$FeLko5R zvwrD<@7!x*)B%##{(%=#Tkp=I4&O7!p{?-~$=i+m+zhpm1l!(n(EuJ*MewiONk6ab z)X=5BZ#AZPtWpHrQuXWbf$yD!fLd+%YN`GCS3adH6{}w(b#QwvSzoK{pd}kk{}XyH z{l)s^m#ZP-=I20o!X$d~ghly{inaOZ$J+}@;X2zs=?@a$?HyVd4Z48oNSLnHd>O|- za!Hc>aZQ&>Uz?NC$+**~{jzMX-zKr$j-c)FNv!hD?$ML&f@-Y(xvmt$dwkwcAUc7j zp2HVbI(<)A`r#VI`f(GPCM^e$i#<9?k;$LdG>5DCnx@*7)uhsEo;bYl_#F^DX{;;{ zJ}XIujhH0ZTET4L1R}%+)9F&y#Xe)1?#Bf*M zal7QmkbUOqcF8Ww#vyL$t2`j4k?%+ zfnjBmvm(hhLKoz1)oM~Fs)c6X1e{x?XXz%sBZ(hfHRDTF1Zf3jYXm!~r7jr-kRZe& zUGf;GffOOLh1k;kFYfirT9UhMZWlbKx2Cl4SC7axugX!aHnY#wJ!WI;Avt|S!tmod z$^te%d-V9_O$=tmHc5i_h_rupHe6w|q+_ZTBi{by@uzTp5kmy$R+2Ac`ho9snd{<^ zl)i;mzLO|u8!8N(K8c`1vgpz0WW7#rYF#A){1mmQ&ZWE?9(LAz#XcZ`<7IBosks=8 zUQ5MyaoXzAiYP|!{Z4RIMnY05)lnv&5~^_dCi!E<6FUZ}M#a@a(QQVrR4D6iAVNq; zC{Knn)4~ih@TPh46lfaqBzpg$HpYv=nP{stvuwE^4}jc*V}02t8TQ@g2Dp{bh+{4OV06&sqKg zG|AOLX-q9t!r<-Bd%vRvgU^vvbML#*fi9HKkclVgX-_^1sPqLh{kQoZHKNM&CD-&An@w zF43Cf~?|(*s1r z8`@~M95{L@7N|lzSEBc|?UQ`Q=b6!Jg9$1D3*j|8(+ef&ZgDO%ue;StX(yPgskmMf zt^!-Zc%OUtr$hAqm-`MtY4066BFOD0<29q%VMQL?p6Xn-WCH!(iskaVTD3iw*vQ9i zVP|%07t%IsJmos(2?}BfiXLrE8NNfnqTt062402A-|*NUB|&`9Ua`cjF!$MVrQ;Y- zpL%X>XdSi9-_|xhC%%m96I8ut!jotKN+I5(ER?_ zZL7JyWpGwM!TGWQ^euY>flAI=3F-{s-gVkj5+-T+tR4)7{KudCg*sKcocuP z1y%v((ukI`=}6vAwagHgiDDbdBB5!Mg!RGjo9pzLVfsoqL`ZYby_krIsB;dbW+YeG zke8)7qy_)cl@$w>GPu%l!}^>8 zq@|%zZL%aBo8MI|e%5gW&Um@MR?e(q(_c8%sJ%mW!%oOfZ$qFw4_#7nYo9YFOrG}G z5r)2nbz_vA9I(NG_f7zjMUq@!1Cb3TxjStCf;+lYeZm1s2YZ>VCo_OTFk+QA3qkwW z(C}06Y$&OT?!9=4n5_#p%uoc0Uw*X(z-%?9J-_aTVrirEwei#VH>}Z{ZQmIm5;U{L%!_~?l4^PN`7)oV?jyN|N z7F=QgXlcND2>cQ2)%C%+X!zCkOPr*inIG#bt;CVF)>lq@ z(`G@cu0s%2%C8L$2&gF#VeP7^&X;+Pu-$Umd7Uv)a5WSLvxTX;ZN*IYWobgL1SE1r zqYRq!>7nR5q4MRPx+9m2N<4q1krzP@+n+a0wpmxQ zWd=~vqWwJkXR9f13?EcJ^$MXXl5KXCNeLh+s@~t0p1xS|C3y*VH)1Uj76Ihz zPU?7M?ANMbfVJ%guCn`dr-+DfG*Bu(PC@Pq_zo)fSYLd3e)!2jo0Xr;wx`DIyBQrV#<3hNekLZgKMA9?)&u6kDRi%nnX?`0ts9-Kw#z7d6o-r*UkV5*T91&lEKjH zJZ?R&>jP`9LTOMSap=VFIk8YO7C#6f3%;p9WwHB$WT;>Ie|q2zl6hdkU#L*WS&(uB z0_=u%qR@IT{QsQaw)9xa^YhT=JOLNQze!1(nhM5ZBu6`)Avdq?9ZY9W3MgoEOQA=a z@PJ22V`wE3>@sWv7!q1wwv_9r8=BubARBi#ZV0;wagtSNyN zD{~PUsKaj?RW~wD4tVU-od?<=&p%M2>Wa6|Q_x{|NrxD9XhznxZz)KATEfI;SHY}z)`Hnh<+dc)j8dfQBXiJ9|N92IMb6LYipA-HKk>ltvOK$Y1V+YzU z$Uh^P`b={Ofl87;)OquXq6LM3|Da)nJ(?S0Ds;FIMKZ( z?3qa5v||_wTvPfPNya(5fC@!VJ3pAH(Pe=INZKduwxJ77WlxdHtB>9w|N80wV(&e` znoPI0QQdBJW>DEPj#93r_6{56@bsTePm&#szparCJWAz-SXnUBJ7pvoQ#l5TJm$v*iW!2+o>yA zu2{=_n;GM(!U*UN8LPAkrN!MTotYS30A8v3;P4oqbctQhaMy2~NVeV#Nelat<{cw> z&gBT?8|qAO)H!j%Esu}YBXAby*EJj_r(j7r!5L}{mRL=x$R={LG=H3FXz{`Ic3TkL zY5SG5<$WDssn2BS)9KG7;^UcaiR;*_vt2Az2TEiY9CgcSMn}eI0sEXP)_x?_)nBJ8@+J2W;E=gev7rUc}8KYpG zF*~(16!oO}^WyPMv6`BiUSk*BZny$_v`HO7EH_o^;Z+*YeBA5myERYxtKH7_oHxcX zXU(je5Qs<7WF~DiHuYY`=I`fP9PHj_3!01So7Ca=wozs)9wx0-x*s!Z6`;5nL~2cgd4xo%Y#mHHG|zaCB>f` zQ?VYktC#7-)zV(Br#n(LI#ghuAj7gu`a9bdqfIcpwN5fz)wSyq;xPk}d#BXiD?Q+! zoHGzjtFOoN&qT>m{mIgaAuVzlRLXgxLTpq5+Sr@bby8in$(qip!O&i zToT3+^%&|oo_M#i*igBN^SW%jhUa+xoAnq7e!fS}BvaG9acR;0((L|SkZr&=gKZBl zaE)aX$I_yw>sm`Sa2AhZuqqH8#gDzoGdrPgF~CbJk4FOxNG>>N*_?FlF&e}-3sSRmV@8w z*dkXNl+@9HkS@J`xDrEZG167XK($S&ZA+BgT3NqCAAH5gP0Hx#GWrj>Z<(p_nMryv z5m>5K*f}_dSpERecG37snY6$GvSGM)zg8ohxH##RmDy(2qYFGvpMm>)=K`acgX)+s zwqyKoK;EssNN&vje!ZQioGag1I5?85%cINwnTrwmlc>+5NyvU$PIN@WX8{$KJC zP2uOy#fPZnw4y?>-3J5_Q8x8TmLNx^86~gpC9{z}Bt=xw#mIK?E1ehD;sy0Y#v|GG_Bvj&pX5g{lA&D0?^^uCT zdBzD{$w!Kc6n?8=gtWz&H8w8AI*E)@mswz?Dkw;>SeXLIKw|G1gh&xz_>p__)7qQo zn}OFH$7!;(@%I7>SnaJ7*rWvB%_D4p+>C*TxRQY3>vo=ae!_PhH5ww ze}!XOZL9CnfnkjUvcCJ*uToQnD6MA&7T|@_3)9+hre^&o&U6epsZbrJ-&GY@A1#0g z^cx1&%We|pn8pnV`~9x`Cy7p1nI$h;(vcOd*}z2NMAPF)Iz-=Rz|C8xxBB#5zq3EqKmqtTt0J?zSfZp{2OKR(tu>uQL4qKqJ+*VG`7fd zpqv&8O81138^CVtky+E)4=Dyib0#Hv;ic_JXP(g{jepm|rotKwTM>s6t1O71R@Syv zOJ@)A#QzzG04(xfur}EFyIrHfHkiM6hsotY_QI5LGv-+0_LWK{N&sx@&whJ717Vov zfW8EuiMA1Q^P+EC63fDWH9GmD>egUn6*)sqhNA0)Aqm~Z!@UpGs$rxbnvCVf1-wzq z^Q?WWHNEhplNh=ZdAc2#vN@WR$H*~<;Zm{k```nIY&Ht-LjxSapPglOUmKxj0%oZm zgk<5@LT#VQ0#+lST0pJqM`M{N;>D22y`BbW(Lp%9Y`olxg?0H(*vLo)%c5v$O7l== zSe#E&)uKR}+Nwc;kGhWXHb9Hok*_pjxb-L#+MUe-+@nr(&f+D4|2hqck^aySx5)G7eVJdsBBO2TV#>J&~0U4erGhZP)%W~Nel1OQu-YMn?RuT2E5AqoG{+K zyTt3a4EcF|zft2|0}aZ$#@$w@l<({)T+Plz!^fN04{3H$h8oJV?L&EGYMIy3%yJ%6 zefF0pIHrQ`o=KE4%A-%+FB;*=hi!RF8kOp~u7DD%XUf0R}eP z4aakWH2qDIPk2mi(|h_f|A)CBJ5D$x;I0bQFZl6@mrhMCR!+?IE?j{S=+fI4tD~oC zDj{#M2IV?0=xq%v5nZudvtf(H*m0&ik$r1l#?^5XS(`S_Bj_GOB94iSQh4n~F|`~r z^sdi>dq8a-T?>0IQKNL7i#5Cf+6#e+UK{UG$ml(fxdWM)7ww(hc$6D^)*gE0=_|j> zZZ|TFSzarU57j1c_vD+1ED!vO-~)X8msJ~TQI;2#KRI-R+IKg_@*aEm$P@=O1o1R5 zjeVvcxKZAR3U)e24L;s(+2+J&^99AakTEdx*K%{+objVZzEgOr$}}}1fNNkLB^EFo zx8}S)kxgJBvM8K{8=K`fI3~IOB5R*j;ck{-Qe}^ld#sstbb^Gn_a01h7RwD@^d?wtDydGG6S=MxXKO!Mi^qT4rD^qg4znB-AR`)`chS9Ez?r8X|8L zCcqqYXm?gNhJ4xdcMoLpGMn{;vJye$c?w_E3W$;MMv)I>?`60G|HRyae=x z8h|LCX51P~L@tYMN*pzBKlmUH2V;NsIJh$ETz!iGv5PZ0?w^Fn{&pP)0O|hY2 z+aTEpJ<)#ERcj_A!VDL!Eb`BZ^jnD6CZZ(BBCqMuK!f+q1(sm#$@xxg8kKrm!z)9z zR8f;0L;}xiVNya-<|Xm(1BN>HgdMQuorMVF#$bJv!@@5&n)4jUp6t{2Z|GjT zbX>;oTzjT@SetX|Omi@Oh*4e$Rewr@4qxUTW}_@Um@ZBUdBBE>>VEVLVi5}h|ye~ts zsm8T&$fIZE7mdlmX;df6L)W2>-W&<}O-c$|GqBCs)FEj@`~k;z{bTasq2KTBm*MH# zpNw?^Lvo7MtqQ?g^iu0aAP$^{DRgqf_fxMMeDU`7P2Ph?iSd_)CpTe8ommEE%LT;1 zVnh!o4P*sK#{yCKz{Z_g=iDRGV>VH5iHpu%^-{o_bZfkSD5_zU`(N0$``Ub`O>Me) zUa&+)7*sS}3?WM@sdG_~)ipQXxoe}0bktiIH zI0RWO4h(kYVZ-v zgO&+cjJpMu>{BMpD$5!`7*0e=!)tvQYP6_fIcCm z7X)^Y2)*7j9ZMdrc_UIoP%qUaEe;}w4hR6`irzQNdw{vkpx!=^Z8yr_&TH zo)LrQe10hxF3O-Z{9L1}SMN0(g7o=r*vLh9+I_IcjY0nYY35h;mn)lr8X+KY0mTFG zd>ep|KLpg+O-HP%dNEhhEUB4`i}Zj8Gcy!R>8{&gLoHJtb2A}gz5I3>^2_OM;s=)< z95Pl#3(zFwEAG(Au|7D5VR!K!?jzBQ&0EeuhpP`QgdG?OkfmQ=DT@`PMuWfeK-g1tB zgkh2Q?x_u}bJB-k#5k`?i!w1sRw+|mEx`EnzcWN-(jQ6F{j#tXV`L<{tsR(aEFyI) zarVn&+nr-U{B#ngk#HtTcL1q}ZfxKI-@c&xN+s9Wx>ps>11%Er$Sx+A#a2*WZ3_xD z1ma3_3XUtSJTSv#_(M#kwEZ^-I1i9*=cRX+W{oq5u>`5${ zRk<(;P-$wYk)Vyqbs70ejd^616Ts9fwtQsHVOb4A_#Pazay?p=@GIo!165V1>g^9N zw0XtL{VK(LbiIu$T>(+zHG{9V+$(Y&`@lRnm4wznz*7GMIP!CI7l8PIcfs^}_W%N} z7(Zs=?3V+>C#m5{_Y;gsv`h6CBmD%B%+YucM%hFl^0L<7S8O>sI5VdvoM=tKp#tDe zo&ArzKYP6bAc9&6d;d2<(mp3mGtwI%N16oBAL{iT3)y<*^`p-I?F9R_y1FGuc1eh@ z+)@GlA81XAD7!)$NcmOdX{=d_5CQQ4^E@9)tQ1++%8L05ZcN`03;ZZG6Ueii)S~DB z<7x}n`0~cvn3FOGH)$&#&l2g^~)OYqPC>7|Y;0BS#1!gRU1kCE8FtXMY z@5`j8Fj>_{o{C~a1N=Nm1Dy_Jx}<~O9*oB_zuen|k678E{+_rDih{`}0zja_7Fco7 zvje(&q&*kXf2S-5$gy+qc+t;! zVsfus5Nuk<1$@se?cA4O-Q@nqKxsa4NAW^p#7yw;yZPS&!_7j_ggARFi-tDt(usftkoz5_BP)RD z04K11{y{x}qzBW#lj`4os8F9uLdrWjG&O?)Ju)OKdH}N161o0Yf+wan2C(Xp5`~jy z({n$ME>igG9&&vL>;mye=N&aKErP4l7y71|3?Thtk&e}t? zH;B`H*0Vm$NXM+Z%Crk8atDaK^agTyVWHTHJ|ZY8n-98`Y5?C%Ve+DUKG4ve8LEx% zsv@eeD_Z;iK-G^GEt2`SOISD)6S3S>^I=#Dzdbr8KSA7p@AkTdAf7xBTlw>@khq12 z$^fzF-wk<<_gJt?GJt+R%Vw1n`UC^BP8;5s!NIeE!#~oVVSJUd)3w9sce zScHI-5%Vat~*c9H?w>)=3SyV z4LagdcgI>#L_dAu?{|5;BQ8K##QwgtAVr{kr7v*n0jIMvM3*C189U==Yd6lk?#NNU z-1-PzsYzGVZ6Q$66=zuCup1;*QvcCg?A1VS$#V#G-9Saer7>4VpDB`A0B0NMx7OVz z`apC=rUGO&8cL<#X_v6AK`@h-Dt}~?+0DIs98EuadDiS^sw7ELtI++zc=iR^+P>#R zwJ+$c&z?RtzqOwKW5(P(Oob9CZiBv}_Lnb@0s(e!%9mxGq*L^gM+UKx7@&{Z4;Bq4 z+Ksj{NOGVp7`Q2sIQ&MBY?x(IX9ztO|Ked`pHJ%csj4{q|D|eJk1^lCb`-NCOFF>*H^b)OL3H! z&gd=&TC}cml}RZYSRjzQaC}*5pGdgCh4J|z8#*-@>5Ovj7wx%aw3Hw$_g))pLt7$=U4D%cgt3nM3^>=50rKwQI>c)jNMPR%axujpONMElhzWajGusG=+K3*Eh|Wns3&oID zuHp?uJ0x!YNv&;L)Su)4l+2v@5EaK}Il8W{wvo=FpN7}usmn?V3bp;AMz#5ldCe)t z&`n?XPruFkw3-b^R}brep8V4WnHS=-H_MN2rbP0=8Q2p`KT*|}=%hMF8%(GR(gzHLE2 z(Nuv&wRbp<;J;xD{xTYq{=0nd>Ah6*tX|p|CS>3F@zbAOz;akDeIMpb9By)Pv8s{! zwA9sS`f;?bC}Zov(bs;%C9Had@&%tqTiPeeY0BD!`I`6JLwBD|Pn~pT2`2~y5;B8Y zgRb>r^=N^Qu1lO7?U7fucj5Wpg9*6%Y;LNx8QwchBiRI-;#_lYnSWTF_z z+7=J?7$@wROl8bQk5Tg+=rYKXzMIsb&CclWaksSoY|4OOXW={V$4`)fTR%UBbPvG( z2G{=%DHsaV3~9c2eGp10<44mh&lV(~qq@Z(xcKrOGM@^Tk(;}sl(HIN?d5{z;m8zl zzf)gaqwz-Lj+}Q~oT+O7c0T67g%<-aG)B+hXe#IxP&8=d**D6cHIC7kD_AF)OIRa5 z84HRVrx2EmX_htCTU&GDtab9wt+{rNyxGnjh(H~z)U?~eiCN&(b^yrPDQ)dQPY;iZ za!r2Snsw^U9?VdKk1{6LbA-tzVEO4l(4X&0vq9=I&_v`rQw6IIDLXXP-jU3MZ|+(r z)vgOvX9_RRTG~5C9cQ?$!jwhGQK>$LCD$5AOH`5P;A0^_-IO=WJONe-L?Z_#x+0#z ze1vlSplJqIFja;uC_E~HdJeA*IjMT~&IyuDFK_JWaePwDtEI&DZItp{d2YUAh^d_G%BX&hnYaidV2tezLKAdD$e4d&D=%+mS4*-3X8c_F(wQ^4BXvjc z$bVS-T|JHzLHlg1&Aa1~q_0c=M9ikW(i6G*QJ{C&yQL=^@Hcr^!h#p5#Ny(;CeL-# zdXTz6!Y1ziU1^5d-z-75VVqPJ!>|cZ#+FRBp65S;{G0E*l}!&Eo3f)GRNzdL!dLFe zFHOkB^PMw;5lD3>R&TbpzgG-5TowW9qC`-m#R}5JLAv&?DohSk#4zA7PZPKo30oyp z6l|=cb8}6>3YmOnYw~|5%Fs!_on~k<_PUIC)flaJKq%jU81(g#stm8x;&0DlQ;%MV z6+5w`Hm);IOhl|#@=riM0WD;zXujzP0do3K2t9}2?T8j8tULqLq^|CDK z>_7!x-ayC9z%o}hwXHjgwK&Q3Xet_(kdXzy9v|@%1|`so4m)VTY1z1&4__f2gI%4z zlnEzA6{HGC;V0yaH-YAF*?f!dLA-x7>nD3O9r`MIa-pg!hw1gh9R~4|*{$_sHvhCV zDcHGVME@g->JR3RPDq156C%EFAI|2l#eEoa zpq@B2aha~|MXy&XhyA*cc8kcpJzg&AYn%+C&38Td$4MmW1Y2&*ChT|ZO3!yKDJyQT zxqmcl{o(Ywx(KKQ<=|7?$=af&Sr7swy*87++m(PCtUdoe0_)YY0~9okz|>S-G`9hz zN5<{5DmIp2eK_oZa#AbD+NJU8X>#%1U|y+^Cj}6}e}s|sEr?Z5kU$|Gt%$u=x3n1C zlJ6K69+{ctPf-~o>Xy2rWeSg}3u*yE%PIp*$X3Yh+4aZF-?(q|_IfiJY0U$7QMtXFL*n-#3$60`|lt4XwSwc4_h ziapF5rIDiGpS(5Mz1 zfnx-kYPW}`mw$h1;--W>lEp=TcfkV?nJH+1p>obh?V1Hwy+f+qoVK*lXh{=pxCy2L zva2EOAl)iOf(_(40kb{Ho*c!yHbFNyhhzxZDaJO;-EpQkf*QB0R{>U6WPo5Sx*?il z54sAg&n~xh>#A^%Vx4YY) zuea@CwA8f(v%%)z9WsRP=)Op!Z=Oe)Djaf7EAk^Q%Utoqonsn`PV)>1`ASjqkWLFU zMe+r`!7d$;9CUHVGxlRV<_Z`)j$KI0!g`#(;DN$Swk1xe0%#db2am<#^=1-A8H2qnG8LKA)xtTB+K=mBg9Z7NyOf zHq3D`vlaT;xQQm>)i1RsBi{klZW69ZyWDhjDoi>Q49vu{GsXADLm+@a3doWg3~nW- z8UQlPEE*~XS{($RItU%08`#R9Hfr6X22&Va>_X4YVdkm1QQlZ)?bT|cmY9UXzOz}W z^+#>1H&co%z+l^*mo@^hST=-n46N~3L3=l=3b`%tfnbtW)^46;u>H7%=!1@D z40!{e-<&8FP`%o}xL~4d)5yTmv@y+TURg(;DZ(;2&-|Cd^`TXJ;e5YJc}VHx<_?)> zKb(*H)g}Jgga)W0P0Vv1rxuC@N}v5yI)e)Za*I%4>2N-|3!yE5X7`sPE@YEW#vDxf z$9vv)=y!{4*#IBjc*a1CGi2R#S!T;A43`(LiQ*?oC;gT#ET=K)8wCVr*`RWg6b7k9hSzSrf&^l|3|7EOl2x8apo@+e{NkpD<6_$N_ zLg0t&(&2AWvO+T(s=3e1^L8Sk2GTj@o_VGaDE|BDV=H=<*sf-cT>tdO^MHiz?JM^^Qcdht%hff*!zX})s7l`=& z7l=0h{SNv+jX;ABkN-C{v}{W<|AqPD{3e!?o4*l}f15pwv-v)4S!p~98EI}eFIH3e z@>D_CMEF z1}eTJNMuaA;zKf=X&8?YJCrAi6y}-kH`!G$qF{O*yosX}TK*Qgpa6h}W6!e3P>Ixq42{QE__h zEV)qya}LQ!QJJT z?;2=HiVMHLRwm9^R}k$txP(LZ;gnuLkrj2;K6$4mD*zxtv>4?XL3Z1+GdS7 z9HTt6}(v~Aw zhR>%O(r-v?%KsX4Cyv2pH@vBqiP}aW9!&D*DKGX&QwIk&!kwV$Yd?Fsdg!T0Lj~QY z`jwZxvFlvhR4A6zNqi=Ey*$og!m-vDSqAKU)sESL8X_tO6lk9Yhi4Fv$CE ztYJq(jMS+m>duQ@w^G`7;maaXnQjs;DzhMg1J_w@F_f0kQk3X&p3G|$6wkJqVNZ|I z#@jOpzH^iD<)H!J%k~h+FA8spZN4;ceXT=MyvF7($amwTmu8K9(4?4XAvZpJPO#5< zRO!K?`&((HM=I;^Z!Qs+Di`?+S8Hz#@AYS)g%nQ?a)N9UY8#P1S@vdlvegK7#}X{| zqP}RMxcZ>J!H~*BWuwp+i|}=h1+RcIJ6r;2%sHTTeEVd>gPm&&eqzY~w3kbIu-+eQW*hdtS4`X^4D!0}zn>(W8m zR3%~aBP>a~*9k{~$CU58N?D~%-{8#{npD2|nZ~ZiK<*GGy??gg* zxDICkqwOlqltmHo!H{ zr*W_1&rST4<)^ZI^_o4kIh~!(Pe`{Qp4t0M)Bs4&Kdj!1?QWTH+s^sBvNyO zzhKVl%3CvIu=TK6uVBJXI2=0C{cOyX4I>^XeYla6G&3`|sYF7-;+*YECS{;B-LBqr zE+NmYu02k#-3xm`zbPr$wRYZGAdvqeB4;#h%F31emOsd%pG@JF=69j7%ujJmW5<=9 z!!mPI=Gv1o1(qzrn}2|Yt`6+CJhGl>J{eex$3R~%@uT;Q=$=2Hfd^yZV)WZS6l`1c zwyjqOP8SK(sGt-X6YBU|m3au&ef(b7O8WFYFB)2_wprZqJE9jm3ifu4-h))Cz?}1i zO0wRg0R8#O`R-mPYWGshxQgdF4bS(dx(n{Zs(n0F-`^Gy>$X@$Z-)NbR%1e5bzCOg z#XH2v!1n-Qy|n3je#fJrVenTER*P*Oh>Q)exXdCEO(%X5D~~}g4Y`M~^=duZ>eIj8 zDdJA%U+(-CIh&I4=IyXW83smz6FS|Wd-=@^3uexa)Ji99`F69d%FbhoSoccfhjHu$CpLB;A_@Ypxh<-_Q)(Pl+lTYB#u*IBG1N3mdv&%kZ5d z*h)5CK|3^E$6c{3GdqPdQtZ+=KR@0HS$LpWU`rZ>$<>M_vo)6PG?VU9lTl5Pk|{%- zSWw*CuYh&GeZ)9r*!LKbeeCF-%))}AvBR))yXg%bU`$rDf7s=4g}1CGm{4{5*$ay! zq3#WLBw)?YrU{($kEuwkbc`*5+FuZu=~@@oVg4&DYtvY^P_CLrOE((pOU%q zY?{hYQ*``xJz4D7nnY@^uQFJk1lX2z_-U9?ZCyk}w3<8YO9<;KLdkDFe~a@ucm4UJ zTh0^4&M@Y6pjR(dDyiwh&&J*b6Y}U3eaNks7kYo~Gq^#mrJ8b&*_`TUEE$0qe-;_k z>)Yp>Byh-KYkz6}&;6mjiLrC3 zCgtsot8-Ji(_lwh`Hj0`DIcvdT1Y!Tz&$#*A#)0Ockx}OFbD^PTm3R}jygbhvAB*o7&(a6`hCbg=DYaJvOKbyz zBy)1fR_E%w+M+oLUHXgFVz(tS80~Is1m$EkXQyD?^xgONnKC+xDb%5mld-%ic8p@- zR9ewQldk=n$2VgItH&bRTLseqd0q3=P*;t=_xG$6KXc|xOcqfv^J39h z^{i9zoSK*0e5uP!i_xHvFI+}N0Jw=^!}r&_S~ew7FA>t@9c>76+?gO&&wUz5fd>U_E`t#ESzg+4z9KR-9Y|TQ+$ptkUsw6Ewyn z?Ke&sMc+I54*L;q!kL-fG6|=k~@Q3*J10%prn?@7xwD{s}m1xuaiK zhVGv9HChHa(D7fmLc6o86pP;fEs z#AMiN?LR(`-q&~ZL>nq9d2>H*QUZVY{g}c7h*D89*v{&XMvmjH`|CdK;2@U>H1CiL zgsnyc&E41>JCK3FfvqMW~R1__U5yMv6h^L zpY?Ep5Z#Qnc?k2)c`sR~j%m>Uln!69;+h{G`*-FR)S7|BJut_`6&VM-b+4}f+lnoQ zK90e0-4};votkrD@=;v|Obj`oyzB^t(Cpq;>`L{u-)8&d|p zY=IoR>f1dt^#_lwx~q5g+wWiftf7uQVGw((c_(|_G5xjmv6bu84<7KHd(kZ4SyQuH zdA4%T@$&n37&{g6nq4k6ocV5}biiYoZ>m}k9oi>-pI8=9)9ImezPKm0(w^^KXstg# zCJ>JIo2M06(Yon^u01E7oyj@2zTv=SIRG`MbXNgT;mo_#m+)tmWL6#uUCc6&;yfGH z+@euffd5AR<~L@f3AcA2yl`OrCBo5crw2FQT&^4R=<4d4Vf4!?%E028O|BB(q1MgR zREkT@OC)QFpvlTJ^b?EktB!beIw{P1ntju`Bm2vqpDb`nv1INYg8R;`+GR{Kbwl8eMcRezcsl|vA>)Q6 z4V@eIhlhLnuNy;+C@xJFe$3{r+(#QdYO5p$dkK+)JT^8qZL@W>k)h6xV0X(Hbj?Hq zZEef}0mnGczo&R#nX6;jcl~ioGntw=0XH+_=K}O+oF?ZdH{G=Roy#{?q3BLvS)W~x z`)*4}2=E9GJ;}c6T>V}B!}}emi){NhuLyZ~TGfqa;^Ge5`G49+3^lQ0!v}uor{K5k^A zubCLq@ciNrRB{0?yFS?Ln$JdE-!o0|K8JI_rmQ%$YV>4QjFWQxlj<;mKOZUbH{f6++7eCp=F4}=+&Ha~)(n4N z)XH&{^M{&ZRCh#K`}q$R#UK8({ntF)I!xdRRE6Dmu4og&o}>6~A)T+F>=oWE{G-G6wp@Y{(9iJK0$fq3fmYJ#Yac z2pc(!scz0*DK)qE6vs4YTQegU)*l8dj5PDKZDLl`_^NngB?vg0|YRK2k z(KM9DkgGLbOWfc2RcRNlQ9KuVW`sIDxz5+)FzFI`lZ1UuKc|?+(id2?mFjTj*$Ybj37u`_=sng~oWX&-;KZqw_v!f$URSlx@_6$}*-bxs#iuT8|9 z{NC5k--i*uI51#*0A>Q3jlIf~v}o12S@c@&j_fwOzK4g4E;Su10)+rc;d(}ku9`|U z@%_(r%9Xc5Yl@VWlC@g8x*|W<3#Es;^G@GdFMI!2S?xW_bbg6kEqW#~K-l&g9qF_p zBt@C#oC^C_TafY+4QgMn>V@sh8@eX#Gq^O-1FO9Ex7`HLwO#~Tf$q{1@k`!g&(UN{ z_rGW|T{!tWk=^%4v+Okaz_x%1gW5<1E26dU-p*Wnn*0wYX>faqtXs@5Ie}_#JeoXW ztL~=8QA=l?-ly5M6wflfy?9I9Fbv56#Qt&Gvwf>DBujq}9O)9+KS}kOd+8QM-*S8N z_F+7Rc9L>ojK zF#>yZO+VRX*U&MK{Dq;Yn=S4pDC458dN}>{jdO5#o%3ewedtGJVKR5PK{C&ye?7zg z{mM#@nhQ_Ra}G_VtD}|O5AWz!ah?bDhn<%~Elx`H5AUBwNB8r&9T^P%u5qms5?T~&vf{kElu`=lMSyQ%r7VyY)=v26be=o`!eg5 z-!7#&=Zw-`u&teA(eAq}k64b)lh3G2@hWVdB5Nln-;2{%Xab4SzT2x%ZwbFF#XdMs%0OHw%*E&DVq={5}dGG4S~7&z@(9ysO_+ zp!ICy@B3gbKbsu)fGB(X=6deGW23s zGwPv3p?i}4@)fO%YfN1uY=)cQQ|Xf`ieah-O-~KN@-h#We$_n6DAGYsoQ@qHzT2DR zj`MQOx{;g9I32-_$#?YVH7RpT^FsT11WG3r9!~4}W8>G`pBk=Pr@%7ld^~q?J~eK= zlE|~3LWS$Wf(q;(l>Arf8g^>&Sx zGsY@m%`*J0yqLU-9@WM99q5HEEPdj<0wwk0hT~86MAbVwJJ)9z!w#g&5kb8uFI>sL z+{;=~lpwdoL>UloK82F_y@XruL!b=y5P1@zD;`!aF%m=I^h{}U&O7&D zJ?){?RY_l4nk)|Vi`~w+RX|gx7jEArhnXz4%|R&o!$b3jVR>f34+-cmZ}~lLuTv>8 zzkV|P6?ada(6Fg>NAt15^7#H=Ok7nq{w1(gtouucFJBmcy8Gdu-W(|1H*Mg$$ag3w zwUC95h6LWcRpGV6GD~dT-PXvG2PU2|1a}#Iknza}zFy(B*n?S2gY&eE{JFoTcY9uz zVYNnD+B|qLQeLEErmaTvro9td@3MzQU~aZ0!I|$@d9No~D()wSqb8-!U9q8|jMG9p_Y?2ym>I*R_S`-QWA5en}4c>k@2z zGZXddYfENFw$G`YxtK|}MNdQT#nO{q2i29r*Vx--J@Fvax1vAMBDx1>-N9my;G;i2 zS0YEX(O&JaJaQiERqZAWz|0WH%PYwu9L=`hM=EfQS~AX#G*B5U^jhO7)WGbO%99zJ zyS|jjsFB0KOzoN6Rr`7d8&TpltD`-3qSA)*p}8gwe>EouOX)Kgou%9dn%awBmVv7+smcQAOFx4r?1s6n^^wAaz4C!caqyP-syZa2b)6} z@lr2laf2rqo(n_nLwYo&hQ~T$VRG!fHc?Mh=~*rf7Of5!A}MjEe)~GVTIk|gqh-}v zG_zh8rPWuojh;lN_5@)ZciADQ(~fFjB(XfVUth5v&2!H&*#tqOL6McArKRP^h`8gJ z)m-9*ejWg5q$=&aV`HTIGRN$u_Jo}QjxGgnl^es_iI zukKE#l$IEY-hH`Z_JOD?f4_}y*>-2^CD-ZX>ZO)nls3U~8{6a{VY%KJLglM^hChHwrp_b%8OL?c+q6pJR)y=R{byU#*5c2RD4-wdtRa$MYtag-J$30 zvWcU-D=ppiLk^R6926}UP4c90yx~MQ&bG7+vL?iiVRFiJa=eJ}ya9nwgsWt=CM%<- zu8R-#u>H*dmA0naP*4yTd@FzO`nA`Sbjo6e@>dgy0 z>^A5wX{#^v-7o5&XL3f21U`cY=Y;8rRJEv}&&!V2~8S5M`4Yg8*c=}xZ zkj?t0dR>1rRhHMGY2PXV&9LEJuk!7QR0Y5kT&_k=M`kc=eN&Cbjx>-P5JN@-D;IIT z-8tH$%OMPQm0GIH!^~V4mkEPF%fv_5J1u26s@kO|me9F`qOpD*&m(vFuRo8_1ov7q z=?J8AD^DL^ahZEj4A*n0Vy?v93i5 zg+i%=Gkmhg_K2K*RAs4r8?WR(Y%3Z6%*FqTDBNrUtJOIOeEk_eVOG*msP4?Jswb`u zf*|#1;mtfsXF7i2Eqi2sOYe!>Hh(h?RSF#$EufSguw0ln(5*uev!ZBpDZ~E&tnJKI zP3qc2y{-53jI@)y|2}@?gUfYsI06YiNQJiJt0#2R{GiBu{H~T!WU$jIY8Q%Kr@F`d^)Z7!kEqr&9C zZEz}eY>)v*(6pO1_OdRX6>&=rlR3c|Ob0*N9&yXzH2G$Pf)!(a(F6VESnn9&P^?N+ znACnUQ>GvY8txCc<}}n`c~70Qd0+sOWMAh;L$==w4&3^qh zBsrW?G@Mqr){Jr$_GYG)YYjDNMx9l4Tfg;SvPW6L;Tvo4{Fw(}!{33G>PSf_d_S`^ zbenx?Ja_E2UWMXQ1QEKrX7lJ-4T)XV(r+fll^ss95*c=5!--^~Kj~8YxV|z($W>{Y z;U6$jh3RcsPYc+}B~#Q}Q02_rt;4+`RTh=iK#rQPWQ9eGhR2b0XwM?3rpeHh%FoTT zY`yw&Ax>D70@H}CwYYHm9TU)0N%l;a_U#PUa8Zd@j>+`JHTKPkwd!vNIl0A*LQo+n zke9tXCU&O-Am9@#oQb{B=#Llm62rZbMwj5-(Ey&I3wL2|MY8LZpPlx}ZB6LmSoya& zUqU_0O*bL|7SCiVW9jSn=tjb)lk%(m)vug$MmahMgILn4ppY8aq%RzLaJa)(H@sfx z=wCKHXLjTqlat4c+KI_LHx*L%DuXNA9?uWC!Qy@-+j0n}C zI30FSU`ACVSD6JC!4R3-&S53%o+D!8#kUWqJEhe_0k-lI-AavnWw;LzPVO>yxz_30(o*#yc!3ncxTT9p)z&-Gu52nh zipKTPLr%m^AQ0brzl`WbzpW=b-mdfsM31(E6~4A!iCC`flWCLF(_^i4iK=UEIz9x5 zaY&7J+#Y&!m!+z0eEx_M3J!{Bc20x64;oob!ua}Jn8I=Bh0KFm2o%Zo&X$MC>027s z%fvh9=_NGXP}rypvB&&-tJpyW**ZW^7}9iX`F&UxgE`i+$)#+B&j=PmhhA&z1h0s! z`c35;`-$Sb9|pBBZl!O#y8ZfrX4I=Y%wzkj=`PlWmc(;-4F`IQU)^z~OEhWhLLs(X zE#%f}uF7g`!^}Wv-Y`oyY6Lem{AjIg&7e&@8NA#*mKMizkPgSh{1gof-sx>b(NY?6 zVrD;)FeoM9#}^4K=a~T_KV;c8nP9y3R;*ruKkz3+Gqq+NnQ(25-&BoUZC6^ryvZX0r0DW|q z=?=@kVa0m`+;z03jX1&2bnA0VB0UNIC>b+!$E?x<%K`b2QX@(?sgGlAJ(lzg>z+xF zZG7lze*#S(!i;M~rqoX+m0Rx|U)EWaP@)2Sf2<1?SEQ7T;QR7M1bX5U%q+?7Q67P` zZ&G`^yOI)nbN2}ngsW&tVMwy`ix+!~d>kRpR76(i8lAUwac0oGn{b>oFxAL9NlG7| z)9dkX|2ax&a&x!E)Re4!W#6wwmv;HfUsXN;Ar~YI4hi7D*PnqV2!Dau25E*S!fb?+ z*2n=!CUxeCtj&G-8AbMQHbn>>njVz(^tGeejuLFR@`Gt#z0-j7Wdo$^WeVNR*R0zb zmla^=Ms?^-pJ?=m<|&CGHJ#Hi?Yz;gOL zI{00=!umbdwGd64O}e;(aVULo9RTrx8yaRiF}I@J=~FWki+IPAgV8;CI#MV2c*6W( zk{i80P2+$=?@uQRLNy;VrO|hFSg6ySQXj9Kw2ahO($Rf#oaz8$bi0~axcF*J*{fdS z%M8f4`U?j7BZiNMxY4awt@%2kkH!VECawTm=eHFJ5JEn3)j$9vFKQ25b}~je=(Waz?0WbjCu8 zTAWYDk?l8hr@VG?I3fDu)LEQ*soPk0SI>hJ!tf$YHbTCq8Z~735h$H(H@k5J z*B}^~n-AGDrtyc-otbxp|WI!t)H+09mX!;gQ z_OnW2-bu)XtTwB+S96@vMJ z$1n7^-@O2Zwj6kU6t!u~;q5NnF+Nl4VcsZu4{YzTCPU3+X$iOoa~so&=cJy`55Xz1 z%Q>G9?O(A1&p=tI_c6!J4qm!E7V^6aX!#AJkFEXyUq624ltk5fi#F3gl%alm^FLqy zDX3q5_LRinnSYg}`fKFz@y)ZTDKQwFK=tF7p`R6oE#{*pkkuICx&HC_!1zREm|FJD zR^`jNl#j1vw}iK(L2{~bj`{Ja<)4}c4k>03#l?&*Z&vZ?wQDgSg5^JC1eRYLKltHB z9Wz-dTL1LuaMbuuu8(H=zi5tUq;K2V#-~O8QlG8?zno9nlXUiv(ev_)4;3}^3;tN+ zTYh%*ao(#xCalnthp^%Q`kiMj{}7UYyr^^f$DnQb8ThaD*dK$bkIx1c?`E9)h-N=N z`JW~r*IoQm%)R{n^PuiRjJ1wh{xJ;Y+k;2N|7luUeDp807yRkWoPSwwO^rik-VN$5v!+y= zw!hR^sl&c8pHg+djoWg+MZt+@wcCP1ngXxi;KU}8>yYJi`P`EzkQV`Yzm(lpZ~3n( zlw%$JyX>Lu+PTCJJG^}y}qq+$y{>s%hs#%lUjM9DQ zE5joMC~ zStL!f*}D3{44wT)8~@E3!=fxZYoZ)48qReKJ%+_@rJvuH6*X7tyKt~)4A}UR~ zZH9>mSb&HD!ia(b0R?G6hy!!b(SwYUGJupBMFgZs?`0fRItoJQp!8y-BtSxv^X@Nz znxLM$&bt5Z_d}Lh$yfIN_Pd|=d7gJ~&}^Rr80}}3hkitz3K~2oe`r}z>`%*o*lbNE zS6KLI7y;FQ8_PU_KOfgR>kI)FUcu{!ukG^q)Y{d}*-S0cVml`?{Rl0BKNfgb#li@X zc+^Yx_;w=%q>A3~_5ogyfmb9D-L4A1SzaCh2Ddn%Lt|LuTB86omn3G#wMgIdDFH0Ig~KLvcTf1;^=DnuzC6JAS}-Xkl{K|y ztido?XHx=9Qz1d1zWlxPs}H6(O4~1uN_Je^VHudU(OV%jy%Fu31-dr^4x3IXmKU8r ztf>I}MRhJ}EzAFz_R+YoJc;b_epB_Yu1cmno^lAkGFcoZ-pqa?1`Wublx^`Q`r5iX zN(#VXNa?iUWyNGQtdO&R6v4IM58(E5Q&UsFA>xv1Y+G})=>2=N>((}B9}@Tx#GlRm zBOLCSz4n!)^!7R$|9toy($Nd!xx!!9|04FRPmPWLkE8v<$8&u-3#OYW4VFr33VkrS z=|S{O4D+1dC&z5apvT?-JoYdxO;JKZ0@H(Z3&BTpX5l;>vj&V~XO`fcLxM=2s73Di zQSZ}ZOFfh&O>7kr5Pd44vI*}{FL4uX2!{bW`>&0V<>t1SF7&yAT*^}MU)L?b)#|r- zx<`#)J#?axydMlkl%qX5>ysz5v`1bu>el#C%5!d!%xn$2cIX&`)X_`gTR(l zP?61nZ zRa+$F#{0MB8ytzLJgBh9tDZx^18`9q?PHmf}*Ujv2_*yhKFR`C6x8A^%~9qW;A=!uu8R&?5p#9W+;~ zTFrqmdUw7u5=8@*;(XCIz3d!lGfQKm>!70+4`)>u(Nm9RJrFs8$K^nqxbLQEaKW!X ziKy5D>~mds4h>V}iQpvF?SQ_fBgo8YAHr@94uD&QZcJ66qFoa@tyEa(9CxOTX=*Ek zG&N1tvNXe$@BL)h75ndDlGe9E?`)VYfESUAAskR=gr>A2MVbNp-__U!u@F;9uzHi?fKMEDyJ|um*>9!q|i6YL9Dorq*ZD1wr zQMpLJj%FEYyj}h<8zGVaHI4V4Gwd1<{Sa(vJkwyRgFI`HNvfeFPX(L@u+rnAT=}-_ z5gUQI=rsX-+ThOcNM|o{HRSW=--wrlb-ZUf8~v@tXFctI`+=VarKWeOZ-b4UVS&36 zxj^2|`3sj4 zmW2D^zW<3B19iY4)@LCDzCb4HYHMqQu`zeC2WKcC zf03@94u1t^3<*_Ec&;Ns=qhfDmy=}vzDerTDOBEe%M?ja*h|q3GpE!m&5XhFW+0?atGuE0%v3k1&qCoLrex{4g#_9 zah~rUizdewrt)e?^OJN`y05!*7Y*o@?9t9m0rBEQsiM*72ZRRw=hMU{q)Dx6a&ls5 zlp&MSP2dygQB$KTQrpt6njXjU;lm$vu5+aQR2jjs(MpS8yOo%3?_?O16;x66x+%~u z<-h=#J_&DEdz%C3?5B8w{WGJ11>@Ma{~AeiyRzJ*;p1h4H?TzT!$ui2*UId0Z~EmS zlJ*F)xqDaMl8n&VmA?)7rI1P2XK8~P`YgDIYl{4h(kd?9|1i#<>X=qHd5YfV4apsG z1Ffr;@S zF4;3E!Y}(LlBZoXlGv-E|KT_wS*=;u92h;i+EQkca>kDGDE-y>MFCh z%v^h|e7Xi{-@x6wdnZAqC?MF_*gy~6AmiF~dz8iXqDvdMY^kI=YM?nL5S3k7|*HdBd#XSgL1B$RIV+zV&SVyTOzyOLkj+@}+^zQoLiHBX^{FY9iR9J13qNe3NKr z@vglnfNbK@nx*i>M@-HP?y+4rdp!JH@WrtSyU=3zKQMYIo0^IExl!D9ABN#U1MJ4W zJk+UMY@NU$4qJshLFa_wKBaUZX`c7O=#&(B{N5`Q*HHw>9~*acEcPOJ?b7G6hnH^H zy%CI&0oFD)11!nvZP*)AK;?vN@SJcTNogW2Q`A!#O37mU+?6$2NuXHiapI;rIJYW6 z<*!oC=aus77A@a!Dl0;oGn7HfsE2ljV}A-F0jFW8t4_{TT;eb3>8<{+z{B_Z$FZ$TB()8Bcyb3wF7DI(ufne%%|Z5VHCkGVq~C|Fe~Z2M=EVlL zS`K*16PB&7>#5h*48FZtET*}yF*D71s1f-N43+G3p@EU}x~tX4sp^5jjxBgg((aVx zOEP%$Hmb4IcH7izp3D;S9rTfE^|!dCVi($qj4RUX)Lkz|6c)H#9LZDRwhhmj$RhHchl9ggcXKz0_7~7NSks2qa)smkLJTKh`DW#rlrp=} z@LiafD6%8B)~XEzyKeKrA1$7yTRm;yZ-sT$f5N0wD`fsbHN30*H0klASwvSGFQ#!} zu)NiH^h!+f9y^=1sk#E#A&NbU3PfDJg&4U%>%nYf?wW`&xo5@*5DT^>qx3wP^|As-~-M>^lgq%S5Hbvt?; z#^Dz2z#l$fkg#8%*T8jU!y4YBxvLVLP+^3uEAkNdZzAFl9o2VLmFtakg^jv?l@8=r zA0i0&>eWx=e^Q9c75Va<2_OcoY-B{Lb*kt47*gQVg4t@Fp`~-9^=Fc>3^JMiTU16{ zh`s4#+LggKpoCGC+>W4<8tT|Zl7gFXI3^q`-}sKyvt8&T1P^knhNh;vX? z5nx5@Y`=Z2t2KvuTiO_s5Xe|I0sB}tq^Cb;?m1^7WxwsJqIrA!8JlR~-~5^4=%{Nr zR_IaY&{y1JRolyY{lb}iif{Wkt!7R{OTGjtsUu2D6UPS&2-BrAKLR-lO|qNkfe6qp zJ(_y*RMEdwro?E{h$`iA7hyVDOW$_kCPrLP$*~l}$pWvnU;2 zSNi?=0f?-h~Bu`=fD}iY-|hxFBpV- z*OhEmlT6;V)M!H6CMC+~lw_iEk08>S2aQt>CDmJi3N%7S z2(6-Q=X~6#7S5H-(^x!s1g=#RN1wT2>~Eyf$1&;)ov(4eCEE%7Pf7oz>VNeSgBrPL ka=$7rSBW3KAf$vZw()yIH|Oz#HRvMv@AVER95na(H(-4rIsgCw literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/img/TQC_Inventory.png b/packages/tychon_quantum_command/img/TQC_Inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..058052945ca0f4e8f210f72a70120750fbad7608 GIT binary patch literal 180360 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

      99qv4UXM)fgWi=`~8VC*Fax@Cz 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 z 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 literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/img/TychonLogo.svg b/packages/tychon_quantum_command/img/TychonLogo.svg new file mode 100644 index 00000000000..47b482d3444 --- /dev/null +++ b/packages/tychon_quantum_command/img/TychonLogo.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/tychon_quantum_command/img/tychon-color.png b/packages/tychon_quantum_command/img/tychon-color.png new file mode 100644 index 0000000000000000000000000000000000000000..0e2c6d9f1d5022d1a93366f1cad641740a2ff0bc GIT binary patch literal 8355 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 0 ? data('cost_totals')[0] : {total_cost:0,labor_hours:0,labor_cost:0,hw_cost:0,lic_cost:0,asset_count:0}\\\"\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"width\\\": { \\\"signal\\\": \\\"width\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"topH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#f8faff\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#dbeafe\\\" }, \\\"strokeWidth\\\": { \\\"value\\\": 1.5 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 10 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"width\\\": { \\\"signal\\\": \\\"width\\\" }, \\\"height\\\": { \\\"value\\\": 4 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#3b82f6\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 10 }, \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 10 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x\\\" }, \\\"y\\\": { \\\"value\\\": 18 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"div1x\\\" }, \\\"y2\\\": { \\\"signal\\\": \\\"topH - 18\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#e2e8f0\\\" }, \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div2x\\\" }, \\\"y\\\": { \\\"value\\\": 18 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"div2x\\\" }, \\\"y2\\\": { \\\"signal\\\": \\\"topH - 18\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#e2e8f0\\\" }, \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.40\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 38 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#1d4ed8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.total_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.65\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 }, \\\"fill\\\": { \\\"value\\\": \\\"#64748b\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Total Upgrade Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.85\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#94a3b8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.asset_count > 0 ? '$' + format(r.total_cost / r.asset_count, ',.0f') + ' per asset' : ''\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x + (div2x - div1x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.40\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 34 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#047857\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(r.labor_hours, ',.1f') + ' h'\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x + (div2x - div1x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.65\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 }, \\\"fill\\\": { \\\"value\\\": \\\"#64748b\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Total Labor Hours\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x + (div2x - div1x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.85\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#94a3b8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.asset_count > 0 ? format(r.labor_hours / r.asset_count, '.1f') + ' h per asset' : ''\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div2x + (width - div2x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.40\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 34 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#7e22ce\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(r.asset_count, ',')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div2x + (width - div2x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.65\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 }, \\\"fill\\\": { \\\"value\\\": \\\"#64748b\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Assets Requiring Upgrade\\\" }\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"signal\\\": \\\"cw\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#eff6ff\\\" }, \\\"stroke\\\": { \\\"value\\\": \\\"#bfdbfe\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }, \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"value\\\": 5 }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#3b82f6\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 }, \\\"cornerRadiusBottomLeft\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.34\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 26 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#1d4ed8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.labor_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.58\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 }, \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Labor Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.78\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#9ca3af\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.total_cost > 0 ? format(r.labor_cost / r.total_cost * 100, '.0f') + '% of total' : ''\\\" }\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"signal\\\": \\\"cw\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#fff1f2\\\" }, \\\"stroke\\\": { \\\"value\\\": \\\"#fca5a5\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }, \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"value\\\": 5 }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#ef4444\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 }, \\\"cornerRadiusBottomLeft\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.34\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 26 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#b91c1c\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.hw_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.58\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 }, \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Hardware Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.78\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#9ca3af\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.total_cost > 0 ? format(r.hw_cost / r.total_cost * 100, '.0f') + '% of total' : ''\\\" }\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"signal\\\": \\\"cw\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#fffbeb\\\" }, \\\"stroke\\\": { \\\"value\\\": \\\"#fcd34d\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }, \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"value\\\": 5 }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#f59e0b\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 }, \\\"cornerRadiusBottomLeft\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.34\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 26 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#b45309\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.lic_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.58\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 }, \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"License / Software Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.78\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#9ca3af\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.total_cost > 0 ? format(r.lic_cost / r.total_cost * 100, '.0f') + '% of total' : ''\\\" }\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"e96a3b6f-c862-4732-94f6-635d6e64c5d7\",\"gridData\":{\"i\":\"e96a3b6f-c862-4732-94f6-635d6e64c5d7\",\"y\":2,\"x\":0,\"w\":48,\"h\":13}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"939918a5-e238-5f2d-88ff-e2f67ab75598\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Certificate Operations\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Upgrade Cost \\u2014 OS Category cost estimates ranked list. Reads pre-computed total_cost_usd per OS category from tychon-pqc-system-readiness*. Styled to match the main OS breakdown panel. No cost arithmetic in Vega.\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.os_category === sel ? null : datum.os_category\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.os_category === sel ? kibanaRemoveFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}}) : kibanaAddFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"os_costs\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"qa_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment\\\" } },\\n \\\"aggs\\\": {\\n \\\"categories\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_category\\\",\\n \\\"size\\\": 30,\\n \\\"order\\\": { \\\"cost_sum\\\": \\\"desc\\\" }\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_total_cost_usd\\\" } },\\n \\\"hours_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_labor_hours\\\" } },\\n \\\"license_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_license_cost_usd\\\" } },\\n \\\"hw_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_hardware_cost_usd\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"buckets\\\",\\n \\\"expr\\\": \\\"isValid(datum.qa_only) && isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"buckets\\\"], \\\"as\\\": [\\\"item\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.item) && isValid(datum.item.key)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"os_category\\\", \\\"expr\\\": \\\"datum.item.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total_cost\\\", \\\"expr\\\": \\\"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"labor_hours\\\", \\\"expr\\\": \\\"isValid(datum.item.hours_sum) ? datum.item.hours_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"license_cost\\\", \\\"expr\\\": \\\"isValid(datum.item.license_sum) ? datum.item.license_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hw_cost\\\", \\\"expr\\\": \\\"isValid(datum.item.hw_sum) ? datum.item.hw_sum.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\",\\n \\\"expr\\\": \\\"datum.total_cost === 0 ? '#66bb6a' : datum.tier === 'LEGACY' ? '#ef5350' : datum.tier === 'CLASSICAL' ? '#ffa726' : '#448aff'\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bgclr\\\",\\n \\\"expr\\\": \\\"datum.total_cost === 0 ? '#66bb6a18' : datum.tier === 'LEGACY' ? '#ef535018' : datum.tier === 'CLASSICAL' ? '#ffa72618' : '#448aff18'\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"os_costs\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"total_cost\\\"], \\\"as\\\": [\\\"v\\\"] }\\n ]\\n }\\n ],\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"os_costs\\\", \\\"field\\\": \\\"os_category\\\", \\\"sort\\\": false },\\n \\\"range\\\": { \\\"step\\\": 72 },\\n \\\"paddingInner\\\": 0,\\n \\\"paddingOuter\\\": 0\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"OS UPGRADE COST ESTIMATE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38},\\n \\\"text\\\": {\\\"value\\\": \\\"TOTAL COST BY OS CATEGORY \\u2014 sorted by cost desc\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 48},\\n \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? '#1c1c2e' : datum.total_cost === 0 ? '#121a12' : '#161622'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 48},\\n \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 4}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 110},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx')) > 0 && data('mx')[0].v > 0 ? max((datum.total_cost / data('mx')[0].v) * (width - 4), 0) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"opacity\\\": {\\\"value\\\": 0.35}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"},\\n \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 113},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 72},\\n \\\"text\\\": {\\\"field\\\": \\\"os_category\\\"},\\n \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.58 - 18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 92},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.labor_hours, ',.1f') + ' labor hrs | $' + format(datum.license_cost, ',.0f') + ' license | $' + format(datum.hw_cost, ',.0f') + ' hardware'\\\"},\\n \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.58 - 18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 56},\\n \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bgclr\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 41\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 68},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 79},\\n \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#333333\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 41\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 91},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? 'SELECTED' : ''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? datum.clr : '#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 84},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.total_cost >= 1e6 ? '$' + format(datum.total_cost / 1e6, ',.2~f') + 'M' : datum.total_cost >= 1e3 ? '$' + format(datum.total_cost / 1e3, ',.1~f') + 'k' : '$' + format(datum.total_cost, ',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? datum.clr : datum.total_cost > 0 ? '#dddddd' : '#66bb6a'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height - 8\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"\\u2191 highest cost at top\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"value\\\": 100},\\n \\\"text\\\": {\\\"signal\\\": \\\"length(data('os_costs')) === 0 ? 'NO OS UPGRADE COSTS IN SELECTED TIME RANGE' : ''\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#333333\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"length(data('os_costs')) === 0 ? 'OS costs appear when scanned hosts run RHEL 7/8/9, CentOS, Windows 10/Server, Ubuntu, Debian,' : ''\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"value\\\": 136},\\n \\\"text\\\": {\\\"signal\\\": \\\"length(data('os_costs')) === 0 ? 'or any macOS below version 26 (Tahoe). Windows 11 and macOS 26 Tahoe are PQC targets.' : ''\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}\\n }}\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"499d6919-5d84-47bf-8bff-653bbd5d0ecd\",\"gridData\":{\"i\":\"499d6919-5d84-47bf-8bff-653bbd5d0ecd\",\"y\":15,\"x\":0,\"w\":17,\"h\":43}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"3a5225f5-247d-560e-b33f-876471396e3f\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Upgrade Cost \\u2014 Effort vs. Risk Bubble Chart. X=total_cost_usd, Y=tier, bubble size=count. Reads pre-computed values from tychon-pqc-system-readiness* using new row schema.\\\",\\n \\\"autosize\\\": { \\\"type\\\": \\\"fit\\\", \\\"contains\\\": \\\"padding\\\" },\\n \\\"padding\\\": { \\\"left\\\": 90, \\\"right\\\": 40, \\\"top\\\": 40, \\\"bottom\\\": 60 },\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"os_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"qa_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment\\\" } },\\n \\\"aggs\\\": {\\n \\\"categories\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_category\\\",\\n \\\"size\\\": 30\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_total_cost_usd\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"buckets\\\",\\n \\\"expr\\\": \\\"isValid(datum.qa_only) && isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"buckets\\\"], \\\"as\\\": [\\\"item\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.item) && isValid(datum.item.key)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"label\\\", \\\"expr\\\": \\\"datum.item.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cost\\\", \\\"expr\\\": \\\"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"datum.item.doc_count > 0 ? datum.item.doc_count : 1\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"'OS Upgrade'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"app_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment.app_group\\\" } },\\n \\\"aggs\\\": {\\n \\\"families\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.app_family\\\",\\n \\\"size\\\": 20\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" } },\\n \\\"instances_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.instance_count\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"buckets\\\",\\n \\\"expr\\\": \\\"isValid(datum.app_only) && isValid(datum.app_only.families) ? datum.app_only.families.buckets : []\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"buckets\\\"], \\\"as\\\": [\\\"item\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.item) && isValid(datum.item.key)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"label\\\", \\\"expr\\\": \\\"datum.item.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cost\\\", \\\"expr\\\": \\\"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"isValid(datum.item.instances_sum) && datum.item.instances_sum.value > 0 ? datum.item.instances_sum.value : 1\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"'App Upgrade'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"all_items\\\",\\n \\\"source\\\": [\\\"os_raw\\\", \\\"app_raw\\\"],\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isFinite(datum.cost) && datum.cost > 0\\\" }\\n ]\\n }\\n ],\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"xscale\\\",\\n \\\"type\\\": \\\"linear\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"all_items\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"range\\\": \\\"width\\\",\\n \\\"nice\\\": true,\\n \\\"zero\\\": true\\n },\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"point\\\",\\n \\\"domain\\\": [\\\"LEGACY\\\", \\\"CLASSICAL\\\"],\\n \\\"range\\\": [80, 260],\\n \\\"padding\\\": 0.5\\n },\\n {\\n \\\"name\\\": \\\"sizescale\\\",\\n \\\"type\\\": \\\"sqrt\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"all_items\\\", \\\"field\\\": \\\"count\\\" },\\n \\\"range\\\": [200, 3000],\\n \\\"zero\\\": true\\n },\\n {\\n \\\"name\\\": \\\"colorscale\\\",\\n \\\"type\\\": \\\"ordinal\\\",\\n \\\"domain\\\": [\\\"OS Upgrade\\\", \\\"App Upgrade\\\"],\\n \\\"range\\\": [\\\"#ef5350\\\", \\\"#3b82f6\\\"]\\n }\\n ],\\n \\\"axes\\\": [\\n {\\n \\\"orient\\\": \\\"bottom\\\",\\n \\\"scale\\\": \\\"xscale\\\",\\n \\\"format\\\": \\\"$,.0f\\\",\\n \\\"title\\\": \\\"Total Upgrade Cost (USD)\\\",\\n \\\"titleFontSize\\\": 12,\\n \\\"labelAngle\\\": -30\\n },\\n {\\n \\\"orient\\\": \\\"left\\\",\\n \\\"scale\\\": \\\"yscale\\\",\\n \\\"title\\\": \\\"Risk Tier\\\",\\n \\\"titleFontSize\\\": 12\\n }\\n ],\\n \\\"legends\\\": [\\n {\\n \\\"fill\\\": \\\"colorscale\\\",\\n \\\"title\\\": \\\"Category\\\",\\n \\\"symbolType\\\": \\\"circle\\\",\\n \\\"orient\\\": \\\"top-right\\\"\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 60 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"value\\\": \\\"CLASSICAL\\\", \\\"offset\\\": 40 },\\n \\\"text\\\": { \\\"value\\\": \\\"Quick Wins\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"fontStyle\\\": { \\\"value\\\": \\\"italic\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 100\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"value\\\": \\\"LEGACY\\\", \\\"offset\\\": -20 },\\n \\\"text\\\": { \\\"value\\\": \\\"Plan Carefully\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"fontStyle\\\": { \\\"value\\\": \\\"italic\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"all_items\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"tier\\\" },\\n \\\"size\\\": { \\\"scale\\\": \\\"sizescale\\\", \\\"field\\\": \\\"count\\\" },\\n \\\"fill\\\": { \\\"scale\\\": \\\"colorscale\\\", \\\"field\\\": \\\"source\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.65 },\\n \\\"stroke\\\": { \\\"scale\\\": \\\"colorscale\\\", \\\"field\\\": \\\"source\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.5 },\\n \\\"tooltip\\\": {\\n \\\"signal\\\": \\\"{'Label': datum.label, 'Tier': datum.tier, 'Category': datum.source, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Count': datum.count}\\\"\\n }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"all_items\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"tier\\\", \\\"offset\\\": -16 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"label\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"53bd2970-764a-498b-9632-f3e37a82d528\",\"gridData\":{\"i\":\"53bd2970-764a-498b-9632-f3e37a82d528\",\"y\":15,\"x\":17,\"w\":31,\"h\":23}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"702a251d-4e87-5dbc-8cf6-25f5098c4de7\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Cost Composition by App Family (compact). Stacked bars: labor + license + hardware.\\\",\\n \\\"autosize\\\": { \\\"type\\\": \\\"fit\\\", \\\"contains\\\": \\\"padding\\\" },\\n \\\"padding\\\": { \\\"left\\\": 110, \\\"right\\\": 18, \\\"top\\\": 34, \\\"bottom\\\": 38 },\\n \\\"background\\\": \\\"#111111\\\",\\n\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"chartTitle\\\", \\\"value\\\": \\\"PQC COST COMPOSITION BY APP FAMILY\\\" },\\n { \\\"name\\\": \\\"topN\\\", \\\"value\\\": 10 }\\n ],\\n\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw_all\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment.app_group\\\" } },\\n \\\"aggs\\\": {\\n \\\"families\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.app_family\\\",\\n \\\"size\\\": 30,\\n \\\"order\\\": { \\\"total_cost\\\": \\\"desc\\\" }\\n },\\n \\\"aggs\\\": {\\n \\\"labor_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.labor_cost_usd\\\" } },\\n \\\"license_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.license_cost_usd\\\" } },\\n \\\"hardware_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.hardware_cost_usd\\\" } },\\n \\\"total_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" } },\\n \\\"instances\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.instance_count\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.families.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum && datum.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app_family\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app_family_short\\\",\\n \\\"expr\\\": \\\"length(datum.key) > 14 ? substring(datum.key,0,11) + '...' : datum.key\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"labor\\\", \\\"expr\\\": \\\"isValid(datum.labor_cost) ? datum.labor_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"license\\\", \\\"expr\\\": \\\"isValid(datum.license_cost) ? datum.license_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hardware\\\", \\\"expr\\\": \\\"isValid(datum.hardware_cost) ? datum.hardware_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total\\\", \\\"expr\\\": \\\"isValid(datum.total_cost) ? datum.total_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"instances\\\", \\\"expr\\\": \\\"isValid(datum.instances) ? datum.instances.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.tier_terms) && datum.tier_terms.buckets.length > 0 ? datum.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isFinite(datum.total) && datum.total > 0\\\" },\\n { \\\"type\\\": \\\"collect\\\", \\\"sort\\\": { \\\"field\\\": \\\"total\\\", \\\"order\\\": \\\"descending\\\" } },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rank\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rank <= topN\\\" }\\n ]\\n },\\n\\n {\\n \\\"name\\\": \\\"components\\\",\\n \\\"source\\\": \\\"raw_all\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"labor\\\", \\\"license\\\", \\\"hardware\\\"], \\\"as\\\": [\\\"component\\\", \\\"value\\\"] },\\n { \\\"type\\\": \\\"stack\\\", \\\"groupby\\\": [\\\"app_family_short\\\"], \\\"sort\\\": { \\\"field\\\": \\\"component\\\" }, \\\"field\\\": \\\"value\\\", \\\"as\\\": [\\\"x0\\\", \\\"x1\\\"] }\\n ]\\n }\\n ],\\n\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"raw_all\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"range\\\": \\\"height\\\",\\n \\\"paddingInner\\\": 0.18,\\n \\\"paddingOuter\\\": 0.06\\n },\\n {\\n \\\"name\\\": \\\"xscale\\\",\\n \\\"type\\\": \\\"linear\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"raw_all\\\", \\\"field\\\": \\\"total\\\" },\\n \\\"nice\\\": true,\\n \\\"zero\\\": true,\\n \\\"range\\\": \\\"width\\\"\\n },\\n {\\n \\\"name\\\": \\\"cscale\\\",\\n \\\"type\\\": \\\"ordinal\\\",\\n \\\"domain\\\": [\\\"labor\\\", \\\"license\\\", \\\"hardware\\\"],\\n \\\"range\\\": [\\\"#f59e0b\\\", \\\"#3b82f6\\\", \\\"#ef4444\\\"]\\n }\\n ],\\n\\n \\\"axes\\\": [\\n {\\n \\\"orient\\\": \\\"left\\\",\\n \\\"scale\\\": \\\"yscale\\\",\\n \\\"labelLimit\\\": 96,\\n \\\"labelColor\\\": \\\"#d1d5db\\\",\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\",\\n \\\"title\\\": \\\"\\\",\\n \\\"zindex\\\": 1\\n },\\n {\\n \\\"orient\\\": \\\"bottom\\\",\\n \\\"scale\\\": \\\"xscale\\\",\\n \\\"format\\\": \\\"$,.2s\\\",\\n \\\"title\\\": \\\"Total Cost (USD)\\\",\\n \\\"titleColor\\\": \\\"#9ca3af\\\",\\n \\\"labelColor\\\": \\\"#9ca3af\\\",\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\"\\n }\\n ],\\n\\n \\\"legends\\\": [\\n {\\n \\\"fill\\\": \\\"cscale\\\",\\n \\\"title\\\": \\\"Cost Component\\\",\\n \\\"orient\\\": \\\"top-right\\\",\\n \\\"titleColor\\\": \\\"#d1d5db\\\",\\n \\\"labelColor\\\": \\\"#9ca3af\\\"\\n }\\n ],\\n\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": -10 },\\n \\\"text\\\": { \\\"signal\\\": \\\"chartTitle + ' (TOP ' + topN + ')'\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"letterSpacing\\\": { \\\"value\\\": 0.8 }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"components\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"height\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"band\\\": 1 },\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"x0\\\" },\\n \\\"x2\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"x1\\\" },\\n \\\"fill\\\": { \\\"scale\\\": \\\"cscale\\\", \\\"field\\\": \\\"component\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#0f0f0f\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 0.6 },\\n \\\"tooltip\\\": {\\n \\\"signal\\\": \\\"{'App Family': datum.app_family, 'Tier': datum.tier, 'Component': datum.component, 'Component Cost': '$' + format(datum.value, ',.0f'), 'Total Cost': '$' + format(datum.total, ',.0f'), 'Instances': datum.instances}\\\"\\n }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"raw_all\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"total\\\", \\\"offset\\\": 4 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\", \\\"band\\\": 0.5 },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(datum.total, ',.2s')\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e5e7eb\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"align\\\": { \\\"value\\\": \\\"left\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"raw_all\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": -4 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\", \\\"band\\\": 0.5 },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.instances > 0 ? '(' + format(datum.instances, ',.0f') + ')' : ''\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#6b7280\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 8 },\\n \\\"align\\\": { \\\"value\\\": \\\"right\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3b9211b0-164b-495c-b3b6-479193fe6c1e\",\"gridData\":{\"i\":\"3b9211b0-164b-495c-b3b6-479193fe6c1e\",\"y\":38,\"x\":17,\"w\":15,\"h\":20}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"26ab7837-9182-5ae8-9186-6a46abbd5428\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Priority Matrix \\u2014 Tier x App Family heatmap. Responsive, compact layout.\\\",\\n \\\"autosize\\\": { \\\"type\\\": \\\"fit\\\", \\\"contains\\\": \\\"padding\\\" },\\n \\\"padding\\\": { \\\"left\\\": 92, \\\"right\\\": 16, \\\"top\\\": 34, \\\"bottom\\\": 46 },\\n \\\"background\\\": \\\"#111111\\\",\\n\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"topN\\\", \\\"value\\\": 10 },\\n { \\\"name\\\": \\\"showCellText\\\", \\\"update\\\": \\\"bandwidth('yscale') >= 18 && bandwidth('xscale') >= 64\\\" }\\n ],\\n\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"matrix_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment.app_group\\\" } },\\n \\\"aggs\\\": {\\n \\\"families\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.app_family\\\",\\n \\\"size\\\": 40\\n },\\n \\\"aggs\\\": {\\n \\\"tiers\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.tier\\\",\\n \\\"size\\\": 5\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": {\\n \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" }\\n },\\n \\\"instances_sum\\\": {\\n \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.instance_count\\\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.families.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum && datum.key && datum.tiers && datum.tiers.buckets\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app_family\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"tiers.buckets\\\"], \\\"as\\\": [\\\"tier_bucket\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.tier_bucket && datum.tier_bucket.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.tier_bucket.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cost\\\", \\\"expr\\\": \\\"isValid(datum.tier_bucket.cost_sum) ? datum.tier_bucket.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"instances\\\", \\\"expr\\\": \\\"isValid(datum.tier_bucket.instances_sum) ? datum.tier_bucket.instances_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isFinite(datum.cost) && datum.cost >= 0\\\" }\\n ]\\n },\\n\\n {\\n \\\"name\\\": \\\"family_order\\\",\\n \\\"source\\\": \\\"matrix_raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"app_family\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"cost\\\"], \\\"as\\\": [\\\"family_total_cost\\\"] },\\n { \\\"type\\\": \\\"collect\\\", \\\"sort\\\": { \\\"field\\\": \\\"family_total_cost\\\", \\\"order\\\": \\\"descending\\\" } },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rank\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rank <= topN\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app_family_short\\\",\\n \\\"expr\\\": \\\"length(datum.app_family) > 14 ? substring(datum.app_family,0,11) + '...' : datum.app_family\\\"\\n }\\n ]\\n },\\n\\n {\\n \\\"name\\\": \\\"matrix\\\",\\n \\\"source\\\": \\\"matrix_raw\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"lookup\\\",\\n \\\"from\\\": \\\"family_order\\\",\\n \\\"key\\\": \\\"app_family\\\",\\n \\\"fields\\\": [\\\"app_family\\\"],\\n \\\"values\\\": [\\\"rank\\\", \\\"app_family_short\\\", \\\"family_total_cost\\\"],\\n \\\"as\\\": [\\\"rank\\\", \\\"app_family_short\\\", \\\"family_total_cost\\\"]\\n },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.rank)\\\" }\\n ]\\n }\\n ],\\n\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"xscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": [\\\"LEGACY\\\", \\\"CLASSICAL\\\"],\\n \\\"range\\\": \\\"width\\\",\\n \\\"paddingInner\\\": 0.08,\\n \\\"paddingOuter\\\": 0.03\\n },\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"family_order\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"range\\\": \\\"height\\\",\\n \\\"paddingInner\\\": 0.08,\\n \\\"paddingOuter\\\": 0.03\\n },\\n {\\n \\\"name\\\": \\\"cscale\\\",\\n \\\"type\\\": \\\"linear\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"matrix\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"range\\\": [\\\"#1f2937\\\", \\\"#2563eb\\\", \\\"#7c3aed\\\", \\\"#dc2626\\\"],\\n \\\"nice\\\": true,\\n \\\"zero\\\": true\\n }\\n ],\\n\\n \\\"axes\\\": [\\n {\\n \\\"orient\\\": \\\"bottom\\\",\\n \\\"scale\\\": \\\"xscale\\\",\\n \\\"title\\\": \\\"Tier\\\",\\n \\\"titleColor\\\": \\\"#d1d5db\\\",\\n \\\"labelColor\\\": \\\"#d1d5db\\\",\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\"\\n },\\n {\\n \\\"orient\\\": \\\"left\\\",\\n \\\"scale\\\": \\\"yscale\\\",\\n \\\"title\\\": \\\"\\\",\\n \\\"labelColor\\\": \\\"#d1d5db\\\",\\n \\\"labelLimit\\\": 86,\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\"\\n }\\n ],\\n\\n \\\"legends\\\": [\\n {\\n \\\"fill\\\": \\\"cscale\\\",\\n \\\"title\\\": \\\"Cost\\\",\\n \\\"orient\\\": \\\"right\\\",\\n \\\"titleColor\\\": \\\"#d1d5db\\\",\\n \\\"labelColor\\\": \\\"#9ca3af\\\",\\n \\\"format\\\": \\\"$,.2s\\\"\\n }\\n ],\\n\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": -12 },\\n \\\"text\\\": { \\\"value\\\": \\\"PRIORITY MATRIX (TOP APP FAMILIES)\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"letterSpacing\\\": { \\\"value\\\": 0.8 }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"matrix\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"tier\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"width\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"band\\\": 1 },\\n \\\"height\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"band\\\": 1 },\\n \\\"fill\\\": { \\\"scale\\\": \\\"cscale\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#1a1a1a\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"tooltip\\\": {\\n \\\"signal\\\": \\\"{'App Family': datum.app_family, 'Tier': datum.tier, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Instances': format(datum.instances, ',.0f')}\\\"\\n }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"matrix\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"tier\\\", \\\"band\\\": 0.5 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\", \\\"band\\\": 0.5 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#f9fafb\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"showCellText && datum.instances > 0 ? format(datum.instances, ',.0f') : ''\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"279b7812-2cf0-43a2-8c2f-410ab21ba53d\",\"gridData\":{\"i\":\"279b7812-2cf0-43a2-8c2f-410ab21ba53d\",\"y\":38,\"x\":32,\"w\":16,\"h\":20}}]", + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "timeFrom": "now-24h/h", + "timeRestore": true, + "timeTo": "now", + "title": "[TYCHON Quantum Command] Cost Analysis", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "managed": false, + "originId": "1f8dd314-b88a-4fca-aca2-091d52c84ab2", + "references": [ + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "279b7812-2cf0-43a2-8c2f-410ab21ba53d:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:26ab7837-9182-5ae8-9186-6a46abbd5428:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "3b9211b0-164b-495c-b3b6-479193fe6c1e:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:702a251d-4e87-5dbc-8cf6-25f5098c4de7:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "name": "499d6919-5d84-47bf-8bff-653bbd5d0ecd:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:939918a5-e238-5f2d-88ff-e2f67ab75598:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "53bd2970-764a-498b-9632-f3e37a82d528:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:3a5225f5-247d-560e-b33f-876471396e3f:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "e96a3b6f-c862-4732-94f6-635d6e64c5d7:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:39e70128-521d-50c8-913c-d745903e2b64:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.2.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NzMsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json new file mode 100644 index 00000000000..c5b5d22962b --- /dev/null +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json @@ -0,0 +1,63 @@ +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", + "panelsJSON": "{}", + "showApplySelections": false + }, + "description": "Aligns to schema version 2.0.3", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "optionsJSON": "{\"useMargins\":false,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":true}", + "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"Inventory | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"57dde807-dddf-51b2-832a-36d295102863\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"totalHosts\\\",\\n \\\"update\\\": \\\"length(data('hosts_total'))>0 ? data('hosts_total')[0].n : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"osReady\\\",\\n \\\"update\\\": \\\"length(data('os_pqc'))>0 ? data('os_pqc')[0].n : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"osPct\\\",\\n \\\"update\\\": \\\"totalHosts > 0 ? round(osReady / totalHosts * 100) : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"osClr\\\",\\n \\\"update\\\": \\\"osPct>=90 ? '#00c853' : osPct>=60 ? '#448aff' : osPct>=30 ? '#ffa726' : '#ef5350'\\\"\\n },\\n {\\n \\\"name\\\": \\\"kexReady\\\",\\n \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"kexPct\\\",\\n \\\"update\\\": \\\"totalHosts > 0 ? round(kexReady / totalHosts * 100) : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"kexClr\\\",\\n \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"\\n },\\n {\\n \\\"name\\\": \\\"barW\\\",\\n \\\"update\\\": \\\"width * 0.62 - 18\\\"\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"hosts_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"hosts_total\\\",\\n \\\"source\\\": \\\"hosts_raw\\\"\\n },\\n {\\n \\\"name\\\": \\\"os_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"host.os_pqc_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"os_pqc\\\",\\n \\\"source\\\": \\\"os_pqc_raw\\\"\\n },\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"kex_pqc\\\",\\n \\\"source\\\": \\\"kex_pqc_raw\\\"\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"QUANTUM READINESS REPORT\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"value\\\": \\\"PQC COMPLIANCE PROGRESS \\u2014 unique hosts at PQC READY tier\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"OS READINESS\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(osReady>=1000?format(osReady,'.3~s'):format(osReady,',')) + ' of ' + (totalHosts>=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * osPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"osPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalHosts>=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"0ccceeab-cd4b-4170-99a4-8e45770e048b\",\"gridData\":{\"i\":\"0ccceeab-cd4b-4170-99a4-8e45770e048b\",\"y\":2,\"x\":0,\"w\":31,\"h\":14}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"30c0b8ba-7a54-5cab-ac59-232baa7bb8b8\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Certificate Operations\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"headerH\\\", \\\"value\\\": 48},\\n {\\\"name\\\": \\\"maxR\\\", \\\"update\\\": \\\"min(width * 0.36, (height - headerH) / 2 - 10)\\\"},\\n {\\\"name\\\": \\\"cx\\\", \\\"update\\\": \\\"width * 0.40\\\"},\\n {\\\"name\\\": \\\"cy\\\", \\\"update\\\": \\\"headerH + (height - headerH) / 2\\\"},\\n {\\\"name\\\": \\\"startA\\\", \\\"value\\\": -1.5707963},\\n {\\\"name\\\": \\\"pi2\\\", \\\"value\\\": 6.2831853},\\n {\\\"name\\\": \\\"lx\\\", \\\"update\\\": \\\"cx + maxR + 18\\\"},\\n\\n {\\\"name\\\": \\\"hostsTotal\\\", \\\"update\\\": \\\"length(data('hosts_total'))>0 ? data('hosts_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"appsTotal\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n\\n {\\\"name\\\": \\\"osReady\\\", \\\"update\\\": \\\"length(data('os_pqc'))>0 ? data('os_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"tlsReady\\\", \\\"update\\\": \\\"length(data('tls_pqc'))>0 ? data('tls_pqc')[0].n : 0\\\"},\\n\\n {\\\"name\\\": \\\"osPct\\\", \\\"update\\\": \\\"hostsTotal > 0 ? round(osReady / hostsTotal * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"appsTotal > 0 ? round(kexReady / appsTotal * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"appsTotal > 0 ? round(sigReady / appsTotal * 100) : 0\\\"},\\n {\\\"name\\\": \\\"tlsPct\\\", \\\"update\\\": \\\"appsTotal > 0 ? round(tlsReady / appsTotal * 100) : 0\\\"},\\n\\n {\\\"name\\\": \\\"overallPct\\\", \\\"update\\\": \\\"round((osPct + kexPct + sigPct + tlsPct) / 4)\\\"},\\n\\n {\\\"name\\\": \\\"osClr\\\", \\\"update\\\": \\\"osPct>=90?'#00c853':osPct>=60?'#448aff':osPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90?'#00c853':kexPct>=60?'#448aff':kexPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90?'#00c853':sigPct>=60?'#448aff':sigPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"tlsClr\\\", \\\"update\\\": \\\"tlsPct>=90?'#00c853':tlsPct>=60?'#448aff':tlsPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"overallClr\\\", \\\"update\\\": \\\"overallPct>=90?'#00c853':overallPct>=60?'#448aff':overallPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"overallLbl\\\", \\\"update\\\": \\\"overallPct>=90?'PQC READY':overallPct>=60?'MODERN':overallPct>=30?'CLASSICAL':'LEGACY'\\\"},\\n\\n {\\\"name\\\": \\\"lg\\\", \\\"update\\\": \\\"(height - headerH) / 5\\\"},\\n {\\\"name\\\": \\\"ly0\\\", \\\"update\\\": \\\"headerH + lg * 0.8\\\"},\\n {\\\"name\\\": \\\"ly1\\\", \\\"update\\\": \\\"headerH + lg * 1.8\\\"},\\n {\\\"name\\\": \\\"ly2\\\", \\\"update\\\": \\\"headerH + lg * 2.8\\\"},\\n {\\\"name\\\": \\\"ly3\\\", \\\"update\\\": \\\"headerH + lg * 3.8\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"hosts_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"hosts_total\\\", \\\"source\\\": \\\"hosts_raw\\\"},\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"os_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"host.os_pqc_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"os_pqc\\\", \\\"source\\\": \\\"os_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"tls_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"tls_pqc\\\", \\\"source\\\": \\\"tls_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 20},\\n \\\"text\\\": {\\\"value\\\": \\\"CRYPTO POSTURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38},\\n \\\"text\\\": {\\\"value\\\": \\\"4-DIMENSION PQC READINESS SCORE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 46},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.875\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.875\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"osPct > 0 ? startA + osPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.655\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.8\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.655\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.8\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"kexPct > 0 ? startA + kexPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.435\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.58\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.435\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.58\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"sigPct > 0 ? startA + sigPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.215\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.36\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.215\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.36\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"tlsPct > 0 ? startA + tlsPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"tlsClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + maxR * 0.06\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"overallPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"overallClr\\\"},\\n \\\"fontSize\\\": {\\\"signal\\\": \\\"max(14, maxR * 0.21)\\\"},\\n \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"baseline\\\": {\\\"value\\\": \\\"middle\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + maxR * 0.24\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"OVERALL\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2e2e2e\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy - maxR * 0.1\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"overallLbl\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"overallClr + '44'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 7}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"OS PLATFORM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"by host\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"osPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"by application\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"by application\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"tlsClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"TLS VERSION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"TLS 1.3 required\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"tlsPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"tlsClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"63e69b30-7da2-4962-ad90-575262384727\",\"gridData\":{\"i\":\"63e69b30-7da2-4962-ad90-575262384727\",\"y\":2,\"x\":31,\"w\":17,\"h\":14}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"6801ef79-6e41-585d-b31a-e75702561c24\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Quantum Inventory Report\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 20}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-KEM / Kyber\\\", \\\"desc\\\": \\\"Post-quantum \\u2014 harvest-proof\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"X25519 / ECDHE\\\", \\\"desc\\\": \\\"Elliptic curve \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"DHE / DH\\\", \\\"desc\\\": \\\"Finite-field DH \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"RSA Key Exchange\\\", \\\"desc\\\": \\\"No forward secrecy \\u2014 deprecated\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"POST-QUANTUM CRYPTOGRAPHY READINESS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"df9e2eaf-bfe4-4443-9b68-c192dee2365a\",\"gridData\":{\"i\":\"df9e2eaf-bfe4-4443-9b68-c192dee2365a\",\"y\":16,\"x\":0,\"w\":16,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.protocol_tier\\\", \\\"size\\\": 50}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"TLS 1.3\\\", \\\"lbl\\\": \\\"TLS 1.3\\\", \\\"desc\\\": \\\"Required for PQC key exchange \\u2014 carries ML-KEM key_share\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"TLS 1.2\\\", \\\"lbl\\\": \\\"TLS 1.2\\\", \\\"desc\\\": \\\"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\\\", \\\"badge\\\": \\\"NO KEM EXT\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"TLS 1.1 or below\\\", \\\"desc\\\": \\\"Deprecated \\u2014 contains known protocol vulnerabilities, should be disabled\\\", \\\"badge\\\": \\\"DEPRECATED\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"TLS PROTOCOL VERSION\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"PREFERRED PROTOCOL \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"b36ed613-82db-46d9-9173-888fa0d6a3f3\",\"gridData\":{\"i\":\"b36ed613-82db-46d9-9173-888fa0d6a3f3\",\"y\":16,\"x\":16,\"w\":15,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 20}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature \\u2014 quantum-resistant\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve signature \\u2014 efficient, quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA signature \\u2014 quantum-vulnerable via Shor's algorithm\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"Broken hash \\u2014 deprecated by all modern standards\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"5c4c8a1f-627a-4bc5-8a2c-a45cbfc1cd5b\",\"gridData\":{\"i\":\"5c4c8a1f-627a-4bc5-8a2c-a45cbfc1cd5b\",\"y\":16,\"x\":31,\"w\":17,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"Windows 10\\\", \\\"Windows 11\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"Windows 11\\\", \\\"lbl\\\": \\\"Windows 11\\\", \\\"desc\\\": \\\"ML-KEM hybrid KEX in Schannel TLS 1.3 (24H2 / build 26100+) \\u2014 native PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"Windows 10\\\", \\\"lbl\\\": \\\"Windows 10\\\", \\\"desc\\\": \\\"TLS 1.3 capable \\u2014 no native PQC algorithm support in any release\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"WINDOWS WORKSTATIONS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"2c4f3e75-eaf8-437c-8d64-17d896a31239\",\"gridData\":{\"i\":\"2c4f3e75-eaf8-437c-8d64-17d896a31239\",\"y\":35,\"x\":0,\"w\":16,\"h\":22}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"Server 2025\\\", \\\"Server 2022\\\", \\\"Server 2019\\\", \\\"Server 2016\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"Server 2025\\\", \\\"lbl\\\": \\\"Windows Server 2025\\\", \\\"desc\\\": \\\"PQC-capable \\u2014 ML-KEM and ML-DSA available via Windows CNG\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"Server 2022\\\", \\\"lbl\\\": \\\"Windows Server 2022\\\", \\\"desc\\\": \\\"TLS 1.3 default \\u2014 no native PQC algorithm support in CNG\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"Server 2019\\\", \\\"lbl\\\": \\\"Windows Server 2019\\\", \\\"desc\\\": \\\"TLS 1.2/1.3 supported \\u2014 no PQC, mainstream support ends Jan 2029\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"Server 2016\\\", \\\"lbl\\\": \\\"Windows Server 2016\\\", \\\"desc\\\": \\\"TLS 1.2 only \\u2014 no PQC support, mainstream support ended Jan 2022\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"WINDOWS SERVER\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"b7978898-3127-443e-91fa-cf36712fc0b0\",\"gridData\":{\"i\":\"b7978898-3127-443e-91fa-cf36712fc0b0\",\"y\":35,\"x\":16,\"w\":15,\"h\":22}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"macOS 26\\\", \\\"macOS 15\\\", \\\"macOS 14\\\", \\\"macOS 13\\\", \\\"macOS 12\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"macOS 26\\\", \\\"lbl\\\": \\\"macOS 26 Tahoe\\\", \\\"desc\\\": \\\"ML-KEM, ML-DSA, SLH-DSA native via Security.framework \\u2014 full PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"macOS 15\\\", \\\"lbl\\\": \\\"macOS 15 Sequoia\\\", \\\"desc\\\": \\\"ML-KEM hybrid KEX via Network.framework \\u2014 partial PQC, not FIPS 203/204 compliant\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"macOS 14\\\", \\\"lbl\\\": \\\"macOS 14 Sonoma\\\", \\\"desc\\\": \\\"TLS 1.3 default \\u2014 no native PQC algorithm support in Security.framework\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"macOS 13\\\", \\\"lbl\\\": \\\"macOS 13 Ventura\\\", \\\"desc\\\": \\\"TLS 1.3 default \\u2014 no native PQC algorithm support in Security.framework\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 3},\\n {\\\"t\\\": \\\"macOS 12\\\", \\\"lbl\\\": \\\"macOS 12 Monterey\\\", \\\"desc\\\": \\\"TLS 1.3 capable \\u2014 older cipher defaults, no PQC support\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 4}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"MACOS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"aa1550df-8d69-4c14-92fb-6566f846bfce\",\"gridData\":{\"i\":\"aa1550df-8d69-4c14-92fb-6566f846bfce\",\"y\":35,\"x\":31,\"w\":17,\"h\":22}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"CentOS 9\\\", \\\"CentOS 8\\\", \\\"CentOS 7\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"CentOS 9\\\", \\\"lbl\\\": \\\"CentOS Stream 9\\\", \\\"desc\\\": \\\"OpenSSL 3.x \\u2014 TLS 1.3 default, OQS PQC provider available\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"CentOS 8\\\", \\\"lbl\\\": \\\"CentOS Stream 8\\\", \\\"desc\\\": \\\"EOL May 2024 \\u2014 OpenSSL 1.1.1, TLS 1.3 supported, no PQC\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CentOS 7\\\", \\\"lbl\\\": \\\"CentOS 7\\\", \\\"desc\\\": \\\"EOL Jun 2024 \\u2014 OpenSSL 1.0.2, TLS 1.2 only, no PQC support\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CENTOS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"2d7ed859-178e-419d-9500-bfc7e9ee1448\",\"gridData\":{\"i\":\"2d7ed859-178e-419d-9500-bfc7e9ee1448\",\"y\":57,\"x\":0,\"w\":16,\"h\":18}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"RHEL 10\\\", \\\"RHEL 9\\\", \\\"RHEL 8\\\", \\\"RHEL 7\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"RHEL 10\\\", \\\"lbl\\\": \\\"RHEL 10\\\", \\\"desc\\\": \\\"OpenSSL 3.5.x \\u2014 ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"RHEL 9\\\", \\\"lbl\\\": \\\"RHEL 9\\\", \\\"desc\\\": \\\"OpenSSL 3.x \\u2014 TLS 1.3 default, OQS PQC provider available separately\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"RHEL 8\\\", \\\"lbl\\\": \\\"RHEL 8\\\", \\\"desc\\\": \\\"OpenSSL 1.1.1 \\u2014 TLS 1.3 supported, no native PQC support\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"RHEL 7\\\", \\\"lbl\\\": \\\"RHEL 7\\\", \\\"desc\\\": \\\"OpenSSL 1.0.2 \\u2014 EOL Jun 2024, TLS 1.2 only, no PQC support\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"RED HAT ENTERPRISE LINUX\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"2b788a90-8404-40ce-832e-cbe6cdc4bfb5\",\"gridData\":{\"i\":\"2b788a90-8404-40ce-832e-cbe6cdc4bfb5\",\"y\":57,\"x\":16,\"w\":15,\"h\":18}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"Ubuntu 26.04\\\", \\\"Ubuntu 25.04\\\", \\\"Ubuntu 24.04\\\", \\\"Ubuntu 22.04\\\", \\\"Ubuntu 20.04\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"Ubuntu 26.04\\\", \\\"lbl\\\": \\\"Ubuntu 26.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 3.5.x \\u2014 ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"Ubuntu 25.04\\\", \\\"lbl\\\": \\\"Ubuntu 25.04\\\", \\\"desc\\\": \\\"OpenSSL 3.4.x \\u2014 ML-KEM/ML-DSA built-in, NIST PQC without oqs-provider\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"Ubuntu 24.04\\\", \\\"lbl\\\": \\\"Ubuntu 24.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 3.0.x \\u2014 TLS 1.3 default, OQS PQC provider available separately\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"Ubuntu 22.04\\\", \\\"lbl\\\": \\\"Ubuntu 22.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 3.0.x \\u2014 TLS 1.3 default, no native PQC support\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 3},\\n {\\\"t\\\": \\\"Ubuntu 20.04\\\", \\\"lbl\\\": \\\"Ubuntu 20.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 1.1.1 \\u2014 TLS 1.3 capable, standard support ends Apr 2025\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 4}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"UBUNTU\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"31106bc5-1c4d-4890-a085-22581cdc5f4c\",\"gridData\":{\"i\":\"31106bc5-1c4d-4890-a085-22581cdc5f4c\",\"y\":57,\"x\":31,\"w\":17,\"h\":18}}]", + "timeRestore": false, + "title": "[TYCHON Quantum Command] Inventory", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "managed": false, + "originId": "12463d6e-8b26-40da-8b6f-b477801b0de2", + "references": [ + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "0ccceeab-cd4b-4170-99a4-8e45770e048b:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:57dde807-dddf-51b2-832a-36d295102863:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "name": "63e69b30-7da2-4962-ad90-575262384727:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:30c0b8ba-7a54-5cab-ac59-232baa7bb8b8:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "df9e2eaf-bfe4-4443-9b68-c192dee2365a:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:6801ef79-6e41-585d-b31a-e75702561c24:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.2.0", + "updated_at": "2026-06-11T17:21:07.71Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY2MjUsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json new file mode 100644 index 00000000000..a66869e78ac --- /dev/null +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json @@ -0,0 +1,134 @@ +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", + "panelsJSON": "{}", + "showApplySelections": false + }, + "description": "Aligns to schema 2.0.3.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "optionsJSON": "{\"useMargins\":false,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", + "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | Application Report | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 20}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-KEM / Kyber\\\", \\\"desc\\\": \\\"Post-quantum — harvest-proof\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"X25519 / ECDHE\\\", \\\"desc\\\": \\\"Elliptic curve — quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"DHE / DH\\\", \\\"desc\\\": \\\"Finite-field DH — quantum-vulnerable\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"RSA Key Exchange\\\", \\\"desc\\\": \\\"No forward secrecy — deprecated\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"POST-QUANTUM CRYPTOGRAPHY READINESS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE — click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"↑ at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"b5127f43-801b-4411-a631-e5c71ca96645\",\"gridData\":{\"i\":\"b5127f43-801b-4411-a631-e5c71ca96645\",\"y\":2,\"x\":0,\"w\":16,\"h\":19}},{\"type\":\"visualization\",\"title\":\"\",\"embeddableConfig\":{\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"totalApps\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"protoReady\\\", \\\"update\\\": \\\"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"protoPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"protoClr\\\", \\\"update\\\": \\\"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"barW\\\", \\\"update\\\": \\\"width * 0.62 - 18\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"proto_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"proto_pqc\\\", \\\"source\\\": \\\"proto_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"APPLICATION PQC DASHBOARD\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"signal\\\": \\\"'PQC COMPLIANCE PROGRESS — ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"KEX COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY key exchange'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"PROTOCOL COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — TLS 1.3 capable'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * protoPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"protoPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 218},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 238},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 253},\\n \\\"text\\\": {\\\"signal\\\": \\\"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY signature'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * sigPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 282},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"1192b05f-8047-4601-ba71-3f601169574b\",\"gridData\":{\"i\":\"1192b05f-8047-4601-ba71-3f601169574b\",\"y\":2,\"x\":16,\"w\":15,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 20}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature — quantum-resistant\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve signature — efficient, quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA signature — quantum-vulnerable via Shor's algorithm\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"Broken hash — deprecated by all modern standards\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM — click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"↑ at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3b53c655-5c7c-4910-9b19-657d22031234\",\"gridData\":{\"i\":\"3b53c655-5c7c-4910-9b19-657d22031234\",\"y\":2,\"x\":31,\"w\":17,\"h\":19}},{\"type\":\"visualization\",\"title\":\"\",\"embeddableConfig\":{\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"rowBg\\\"},\\n \\\"update\\\": \\\"datum.family === sel ? null : datum.family\\\",\\n \\\"force\\\": true\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"rowBg\\\"},\\n \\\"update\\\": \\\"datum.family === sel ? kibanaRemoveFilter({'terms': {'process.name': datum.filterTerms}}) : kibanaAddFilter({'terms': {'process.name': datum.filterTerms}})\\\",\\n \\\"force\\\": true\\n }\\n ]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"procs\\\": {\\n \\\"terms\\\": {\\\"field\\\": \\\"process.name\\\", \\\"size\\\": 80},\\n \\\"aggs\\\": {\\n \\\"kex\\\": {\\n \\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 5},\\n \\\"aggs\\\": {\\\"thosts\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.procs.buckets\\\"},\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"family\\\",\\n \\\"expr\\\": \\\"lower(datum.key)==='w3wp.exe'||lower(datum.key)==='iisexpress.exe'||lower(datum.key)==='inetinfo.exe' ? 'IIS' : lower(datum.key)==='node'||lower(datum.key)==='node.exe'||lower(datum.key)==='nodejs'||lower(datum.key)==='nodejs.exe' ? 'Node.js' : lower(datum.key)==='apache2'||lower(datum.key)==='httpd'||lower(datum.key)==='apache'||lower(datum.key)==='httpd.exe'||lower(datum.key)==='apache.exe'||lower(datum.key)==='httpd.worker' ? 'Apache' : lower(datum.key)==='nginx'||lower(datum.key)==='nginx.exe'||lower(datum.key)==='nginx-debug'||lower(datum.key)==='openresty' ? 'Nginx' : lower(datum.key)==='jsvc'||lower(datum.key)==='tomcat'||lower(datum.key)==='tomcat.exe'||lower(datum.key)==='tomcat9'||lower(datum.key)==='tomcat9.exe'||lower(datum.key)==='tomcat10'||lower(datum.key)==='tomcat10.exe'||lower(datum.key)==='tomcat8'||lower(datum.key)==='tomcat8.exe'||lower(datum.key)==='tomcat7'||lower(datum.key)==='tomcat7.exe'||lower(datum.key)==='catalina'||lower(datum.key)==='catalina.sh' ? 'Tomcat' : lower(datum.key)==='dotnet'||lower(datum.key)==='dotnet.exe' ? '.NET / Kestrel' : lower(datum.key)==='caddy'||lower(datum.key)==='caddy.exe' ? 'Caddy' : lower(datum.key)==='traefik'||lower(datum.key)==='traefik.exe' ? 'Traefik' : lower(datum.key)==='haproxy' ? 'HAProxy' : lower(datum.key)==='gunicorn' ? 'Gunicorn' : lower(datum.key)==='uwsgi' ? 'uWSGI' : lower(datum.key)==='puma'||lower(datum.key)==='passenger'||lower(datum.key)==='passenger-ruby' ? 'Puma' : lower(datum.key)==='varnishd' ? 'Varnish' : lower(datum.key)==='lighttpd' ? 'Lighttpd' : lower(datum.key)==='java'||lower(datum.key)==='java.exe'||lower(datum.key)==='javaw.exe' ? 'Java App Server' : 'Other'\\\"\\n },\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.family != null\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mapped\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"kex.buckets\\\"], \\\"as\\\": [\\\"tb\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.tb.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier_h\\\", \\\"expr\\\": \\\"datum.tb.thosts ? datum.tb.thosts.value : 0\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier_ord\\\", \\\"expr\\\": \\\"datum.tier==='LEGACY' ? 0 : datum.tier==='CLASSICAL' ? 1 : datum.tier==='MODERN' ? 2 : datum.tier==='PQC READY' ? 3 : 4\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"by_ft\\\",\\n \\\"source\\\": \\\"mapped\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\", \\\"tier\\\", \\\"tier_ord\\\"],\\n \\\"fields\\\": [\\\"tier_h\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"tier_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_totals\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"fam_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_risk\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.tier === 'LEGACY' || datum.tier === 'CLASSICAL'\\\"},\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"risk_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_pqc\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.tier === 'PQC READY'\\\"},\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"pqc_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_rows\\\",\\n \\\"source\\\": \\\"fam_totals\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"fam_risk\\\", \\\"key\\\": \\\"family\\\", \\\"fields\\\": [\\\"family\\\"], \\\"values\\\": [\\\"risk_total\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"fam_pqc\\\", \\\"key\\\": \\\"family\\\", \\\"fields\\\": [\\\"family\\\"], \\\"values\\\": [\\\"pqc_total\\\"], \\\"default\\\": 0},\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"clr\\\",\\n \\\"expr\\\": \\\"datum.family==='IIS' ? '#0078d4' : datum.family==='Node.js' ? '#68a063' : datum.family==='Apache' ? '#d22128' : datum.family==='Nginx' ? '#009900' : datum.family==='Tomcat' ? '#f8a51a' : datum.family==='.NET / Kestrel' ? '#7b5ea7' : datum.family==='Caddy' ? '#00acd7' : datum.family==='Traefik' ? '#24a1c1' : datum.family==='HAProxy' ? '#7db8e8' : datum.family==='Gunicorn' ? '#499848' : datum.family==='uWSGI' ? '#cc4125' : datum.family==='Puma' ? '#e040fb' : datum.family==='Varnish' ? '#ff6d00' : datum.family==='Lighttpd' ? '#909090' : datum.family==='Java App Server' ? '#c7a008' : '#666666'\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"filterTerms\\\",\\n \\\"expr\\\": \\\"datum.family==='IIS' ? ['w3wp.exe','iisexpress.exe','inetinfo.exe'] : datum.family==='Node.js' ? ['node','node.exe','nodejs','nodejs.exe'] : datum.family==='Apache' ? ['apache2','httpd','apache','httpd.exe','apache.exe','httpd.worker'] : datum.family==='Nginx' ? ['nginx','nginx.exe','nginx-debug','openresty'] : datum.family==='Tomcat' ? ['jsvc','tomcat','tomcat.exe','tomcat9','tomcat9.exe','tomcat10','tomcat10.exe','tomcat8','tomcat8.exe','tomcat7','tomcat7.exe','catalina','catalina.sh'] : datum.family==='.NET / Kestrel' ? ['dotnet','dotnet.exe'] : datum.family==='Caddy' ? ['caddy','caddy.exe'] : datum.family==='Traefik' ? ['traefik','traefik.exe'] : datum.family==='HAProxy' ? ['haproxy'] : datum.family==='Gunicorn' ? ['gunicorn'] : datum.family==='uWSGI' ? ['uwsgi'] : datum.family==='Puma' ? ['puma','passenger','passenger-ruby'] : datum.family==='Varnish' ? ['varnishd'] : datum.family==='Lighttpd' ? ['lighttpd'] : datum.family==='Java App Server' ? ['java','java.exe','javaw.exe'] : [datum.family]\\\"\\n },\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"risk_total\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rowIdx\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rowIdx - 1) * 38 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"stacked\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"fam_rows\\\", \\\"key\\\": \\\"family\\\", \\\"fields\\\": [\\\"family\\\"], \\\"values\\\": [\\\"y\\\", \\\"fam_total\\\", \\\"risk_total\\\"]},\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.y != null\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier_clr\\\", \\\"expr\\\": \\\"datum.tier==='LEGACY' ? '#ef5350' : datum.tier==='CLASSICAL' ? '#ffa726' : datum.tier==='MODERN' ? '#42a5f5' : datum.tier==='PQC READY' ? '#66bb6a' : '#555555'\\\"},\\n {\\\"type\\\": \\\"joinaggregate\\\", \\\"fields\\\": [\\\"fam_total\\\"], \\\"ops\\\": [\\\"max\\\"], \\\"as\\\": [\\\"max_fam\\\"]},\\n {\\n \\\"type\\\": \\\"window\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"sort\\\": {\\\"field\\\": \\\"tier_ord\\\", \\\"order\\\": \\\"ascending\\\"},\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"as\\\": [\\\"cumul\\\"]\\n }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"WEB SERVER DISTRIBUTION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 30},\\n \\\"text\\\": {\\\"value\\\": \\\"HOSTS BY SERVER FAMILY & PQC KEX TIER · sorted by at-risk count · click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 170}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#ef5350\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 180}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"LEGACY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 228}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#ffa726\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 238}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"CLASSICAL\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 300}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#42a5f5\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 310}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"MODERN\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 362}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#66bb6a\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 372}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"PQC READY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 50},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"rowBg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 37},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.family===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"},\\n \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 37},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 14\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"family\\\"}, \\\"limit\\\": {\\\"value\\\": 148},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.family===sel ? '#ffffff' : '#e8e8e8'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 170}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"width - 245\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 2}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"stacked\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"170 + ((datum.cumul - datum.tier_total) / (datum.max_fam > 0 ? datum.max_fam : 1)) * (width - 245)\\\"},\\n \\\"x2\\\": {\\\"signal\\\": \\\"170 + (datum.cumul / (datum.max_fam > 0 ? datum.max_fam : 1)) * (width - 245)\\\"},\\n \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"height\\\": {\\\"value\\\": 8},\\n \\\"fill\\\": {\\\"field\\\": \\\"tier_clr\\\"},\\n \\\"fillOpacity\\\": {\\\"signal\\\": \\\"datum.family===sel ? 1 : 0.8\\\"},\\n \\\"cornerRadius\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 14\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.fam_total >= 1000 ? format(datum.fam_total, '.3~s') : format(datum.fam_total, ',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.family===sel ? datum.clr : '#cccccc'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 35\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.risk_total > 0 ? format(datum.risk_total, ',') + ' AT RISK' : datum.pqc_total > 0 ? 'PQC READY' : 'NOT PQC READY'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.risk_total > 0 ? '#ef5350' : datum.pqc_total > 0 ? '#66bb6a' : '#ffa726'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 7}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 37\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"0634e4b1-c33f-45ed-a33c-ba3937c4ed1f\",\"gridData\":{\"i\":\"0634e4b1-c33f-45ed-a33c-ba3937c4ed1f\",\"y\":21,\"x\":0,\"w\":26,\"h\":19}},{\"type\":\"lens\",\"title\":\"Weak Ciphers In-Use\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9c6edb36-c71b-5cf1-8dcd-a37de6214334\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true,\"width\":314},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Weak Cipher\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[\"svchost.exe\",\"dllhost.exe\"],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Process Count\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1}}}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"2e9c8eb8-3234-44f1-aaf7-95b6832d1657\",\"gridData\":{\"i\":\"2e9c8eb8-3234-44f1-aaf7-95b6832d1657\",\"y\":21,\"x\":26,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"title\":\"Insecure Ciphers In-Use\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"b0c9f1de-0afd-5b7d-b3a1-fb28c055a10a\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Insecure Cipher\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.insecure_ciphers\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[\"svchost.exe\",\"dllhost.exe\"],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"ae78c400-d497-4d7f-9541-3e14fb724097\",\"gridData\":{\"i\":\"ae78c400-d497-4d7f-9541-3e14fb724097\",\"y\":21,\"x\":37,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"title\":\"Port Usage\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"0ba322cf-440b-5ad3-a615-62aad7cf634c\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-8e8a2d62-de50-4140-91d5-4d323f4bfe51\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"8e8a2d62-de50-4140-91d5-4d323f4bfe51\",\"layerType\":\"data\",\"columns\":[{\"columnId\":\"b9ce2593-2e18-4a93-997b-fea289547d59\",\"alignment\":\"center\"},{\"columnId\":\"119c83a6-13f7-4470-b14e-00f524c8f68c\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"57ed4372-97b0-41ed-a161-eb151f832cdb\",\"isTransposed\":false,\"isMetric\":true}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"8e8a2d62-de50-4140-91d5-4d323f4bfe51\":{\"columns\":{\"b9ce2593-2e18-4a93-997b-fea289547d59\":{\"label\":\"Port Number\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"server.port\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"119c83a6-13f7-4470-b14e-00f524c8f68c\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"119c83a6-13f7-4470-b14e-00f524c8f68c\":{\"label\":\"Not Resilient\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.name\",\"isBucketed\":false,\"filter\":{\"query\":\"omb.kex_primary_quantum_safe : false \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"57ed4372-97b0-41ed-a161-eb151f832cdb\":{\"label\":\"Quantum Resilient \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.name\",\"isBucketed\":false,\"filter\":{\"query\":\"omb.kex_primary_quantum_safe : true \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true}},\"columnOrder\":[\"b9ce2593-2e18-4a93-997b-fea289547d59\",\"119c83a6-13f7-4470-b14e-00f524c8f68c\",\"57ed4372-97b0-41ed-a161-eb151f832cdb\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091\",\"gridData\":{\"i\":\"5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091\",\"y\":40,\"x\":0,\"w\":10,\"h\":19}},{\"type\":\"lens\",\"title\":\"Vulnerable Software\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"d46a3ff4-c28b-57a1-a225-f58957519288\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"tychon.index : \\\"inventory\\\" and quantum_ready: false \",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"tychon.index : \\\"inventory\\\" and quantum_ready: false \",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Software Package Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[\"svchost.exe\",\"dllhost.exe\"],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"Host Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1}}}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1\",\"gridData\":{\"i\":\"bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1\",\"y\":40,\"x\":10,\"w\":16,\"h\":19}},{\"type\":\"lens\",\"title\":\"Non-Quantum Ready KX\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"e17bab29-a9ff-52fc-911c-0fbbde37ba9b\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"9d644013-9636-4968-9154-38f0c5207120\",\"key\":\"omb.kex_tier\",\"field\":\"omb.kex_tier\",\"params\":{\"query\":\"PQC READY\"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"omb.kex_tier\":\"PQC READY\"}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true,\"width\":314},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"9d644013-9636-4968-9154-38f0c5207120\",\"key\":\"omb.kex_tier\",\"field\":\"omb.kex_tier\",\"params\":{\"query\":\"PQC READY\"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"omb.kex_tier\":\"PQC READY\"}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Key Exchange\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.supported_key_exchanges\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[\"\"],\"exclude\":[\".*(mlkem|ffdh).*\"],\"includeIsRegex\":true,\"excludeIsRegex\":true},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"d2885626-4e44-41c7-b5ba-45c5b524280a\",\"gridData\":{\"i\":\"d2885626-4e44-41c7-b5ba-45c5b524280a\",\"y\":40,\"x\":26,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"title\":\"Non-Quantum Ready Signatures\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"dfda3f15-fd80-541a-a930-8a72e988f26d\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Certificate Operations\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"7503da64-ec7e-41aa-962f-15507a9e77a5\",\"key\":\"x509.signature_algorithm\",\"field\":\"x509.signature_algorithm\",\"params\":{\"query\":\"PQC READY \"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"x509.signature_algorithm\":\"PQC READY \"}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"7bb8af8f-5ff6-433e-9a1a-ca36a3af873d\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"7503da64-ec7e-41aa-962f-15507a9e77a5\",\"key\":\"x509.signature_algorithm\",\"field\":\"x509.signature_algorithm\",\"params\":{\"query\":\"PQC READY \"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"x509.signature_algorithm\":\"PQC READY \"}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"7bb8af8f-5ff6-433e-9a1a-ca36a3af873d\":{\"label\":\"Signature\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.sig_algorithm\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[\"\"],\"exclude\":[\"(MLDSA|SLH|FND).*\"],\"includeIsRegex\":true,\"excludeIsRegex\":true},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"7bb8af8f-5ff6-433e-9a1a-ca36a3af873d\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"01b3101c-246d-448d-a05d-3a05e7747926\",\"gridData\":{\"i\":\"01b3101c-246d-448d-a05d-3a05e7747926\",\"y\":40,\"x\":37,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"d0188d05-be4a-474b-8825-cf250d80d88f\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Application Detail\",\"config\":{\"openInNewTab\":true,\"useCurrentDateRange\":true,\"useCurrentFilters\":false}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-e75aaba0-a144-4cc0-a761-f8be87375cb4\"}],\"state\":{\"visualization\":{\"layerId\":\"e75aaba0-a144-4cc0-a761-f8be87375cb4\",\"layerType\":\"data\",\"columns\":[{\"columnId\":\"b5fce59b-3087-426d-aab0-9b9bbecb3ed8\",\"oneClickFilter\":true},{\"columnId\":\"590cd120-8a6e-4be0-bd3b-0ba0026d28a6\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"78f4e7ab-8d4a-44c8-a828-9c575851796c\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"f9d9e11f-6962-422b-b6da-2fd7558dd085\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"text\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.3\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":false},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.2\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":5},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLS1.0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLS1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"434e93db-3c69-4dae-807b-d0719c662bac\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"d80e5fa1-371d-4474-b958-366159cfdd27\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"331d730b-580a-4d92-a2fe-6a84c9d97da7\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"3406b6a3-14cc-43af-9f24-ac050dd0a821\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"d4469a63-4cf7-4e5f-bdcc-b9a494d4a232\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"5b34e39e-686f-462c-9121-c0695e10982f\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"c01e7181-5ff6-4dcf-acab-76dda3f5a746\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1.0\",\"1.1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1.2\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":5},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1.3\",\"2.0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"a5eeb316-c12c-4532-b3d7-60b8f2f06876\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"}],\"paging\":{\"enabled\":true,\"size\":30},\"headerRowHeightLines\":2},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"e75aaba0-a144-4cc0-a761-f8be87375cb4\":{\"columns\":{\"b5fce59b-3087-426d-aab0-9b9bbecb3ed8\":{\"label\":\"Process\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":100,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"590cd120-8a6e-4be0-bd3b-0ba0026d28a6\":{\"label\":\"Primary Key Exchange\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.kex_primary\",\"isBucketed\":true,\"params\":{\"size\":8,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"78f4e7ab-8d4a-44c8-a828-9c575851796c\":{\"label\":\"Cipher Suite\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.cipher\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"f9d9e11f-6962-422b-b6da-2fd7558dd085\":{\"label\":\"Protocol\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.protocol\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"434e93db-3c69-4dae-807b-d0719c662bac\":{\"label\":\"Quantum Resilient\",\"dataType\":\"boolean\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"quantum_ready\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"f998a85c-6b52-4d94-9644-c76256e90cc5\":{\"label\":\"Port Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"server.port\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"d80e5fa1-371d-4474-b958-366159cfdd27\":{\"label\":\"Total OS\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"observer.os.platform\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"331d730b-580a-4d92-a2fe-6a84c9d97da7\":{\"label\":\"Host Count\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"host.id\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"3406b6a3-14cc-43af-9f24-ac050dd0a821\":{\"label\":\"TLS Supported Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"d4469a63-4cf7-4e5f-bdcc-b9a494d4a232\":{\"label\":\"TLS Insecure Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.insecure_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"5b34e39e-686f-462c-9121-c0695e10982f\":{\"label\":\"TLS Weak Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2\":{\"label\":\"MAC\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.mac\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"c01e7181-5ff6-4dcf-acab-76dda3f5a746\":{\"label\":\"Proto Version\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.protocol_version\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"a5eeb316-c12c-4532-b3d7-60b8f2f06876\":{\"label\":\"Certificate\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.certificate\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"b5fce59b-3087-426d-aab0-9b9bbecb3ed8\",\"f9d9e11f-6962-422b-b6da-2fd7558dd085\",\"c01e7181-5ff6-4dcf-acab-76dda3f5a746\",\"590cd120-8a6e-4be0-bd3b-0ba0026d28a6\",\"434e93db-3c69-4dae-807b-d0719c662bac\",\"78f4e7ab-8d4a-44c8-a828-9c575851796c\",\"eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2\",\"a5eeb316-c12c-4532-b3d7-60b8f2f06876\",\"f998a85c-6b52-4d94-9644-c76256e90cc5\",\"3406b6a3-14cc-43af-9f24-ac050dd0a821\",\"d4469a63-4cf7-4e5f-bdcc-b9a494d4a232\",\"5b34e39e-686f-462c-9121-c0695e10982f\",\"d80e5fa1-371d-4474-b958-366159cfdd27\",\"331d730b-580a-4d92-a2fe-6a84c9d97da7\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"07f49118-bcf0-44f7-875a-df393ce88c47\",\"gridData\":{\"i\":\"07f49118-bcf0-44f7-875a-df393ce88c47\",\"y\":59,\"x\":0,\"w\":48,\"h\":32}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"tychon.index: inventory\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-76c0d382-132a-4232-b1ba-2928d86d36eb\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"c452013b-c1a4-444a-9861-fd5f8283dbb8\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"64bc500b-17f2-4b63-99de-710ec63da6b9\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"f1c203be-6445-4ac0-8f8f-64797cb120ba\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"72caa386-75a2-404d-996c-609cc9ce8705\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"98a06023-cab2-4907-bc55-dbb722c5294a\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"c38c78d3-f83a-4b39-8766-fd169aa8f1cf\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"496f4a9c-c379-4dfc-8e74-df11f73cfa52\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"d60e63d5-11c7-4413-b41f-139d3870723e\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"}],\"layerId\":\"76c0d382-132a-4232-b1ba-2928d86d36eb\",\"layerType\":\"data\"},\"query\":{\"query\":\"tychon.index: inventory\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"76c0d382-132a-4232-b1ba-2928d86d36eb\":{\"columns\":{\"c452013b-c1a4-444a-9861-fd5f8283dbb8\":{\"label\":\"Subject\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.subject.distinguished_name\",\"isBucketed\":true,\"params\":{\"size\":100,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"66633750-7aab-4f60-82cb-63d6b4fb604e\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"64bc500b-17f2-4b63-99de-710ec63da6b9\":{\"label\":\"Issued\",\"dataType\":\"date\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.validity.not_before\",\"filter\":{\"query\":\"\\\"x509.validity.not_before\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"f1c203be-6445-4ac0-8f8f-64797cb120ba\":{\"label\":\"Expires\",\"dataType\":\"date\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.validity.not_after\",\"filter\":{\"query\":\"\\\"x509.validity.not_after\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"72caa386-75a2-404d-996c-609cc9ce8705\":{\"label\":\"Lifespan\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.certificate_leaf_details.validity.duration_days\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294aX0\":{\"label\":\"Part of Time Left\",\"dataType\":\"date\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.not_after\",\"filter\":{\"query\":\"\\\"x509.not_after\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294aX1\":{\"label\":\"Part of Time Left\",\"dataType\":\"number\",\"operationType\":\"now\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[],\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294aX2\":{\"label\":\"Part of Time Left\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"subtract\",\"args\":[\"98a06023-cab2-4907-bc55-dbb722c5294aX0\",\"98a06023-cab2-4907-bc55-dbb722c5294aX1\"],\"location\":{\"min\":0,\"max\":34},\"text\":\"last_value(x509.not_after) - now()\"}},\"references\":[\"98a06023-cab2-4907-bc55-dbb722c5294aX0\",\"98a06023-cab2-4907-bc55-dbb722c5294aX1\"],\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294a\":{\"label\":\"Time Left\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"last_value(x509.not_after) - now()\",\"isFormulaBroken\":false,\"format\":{\"id\":\"duration\",\"params\":{\"decimals\":0,\"fromUnit\":\"milliseconds\"}}},\"references\":[\"98a06023-cab2-4907-bc55-dbb722c5294aX2\"],\"customLabel\":true},\"c38c78d3-f83a-4b39-8766-fd169aa8f1cf\":{\"label\":\"Curve\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.public_key_curve\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"496f4a9c-c379-4dfc-8e74-df11f73cfa52\":{\"label\":\"Algorithm\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.public_key_algorithm\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"d60e63d5-11c7-4413-b41f-139d3870723e\":{\"label\":\"Key Size\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.public_key_size\",\"filter\":{\"query\":\"\\\"x509.public_key_size\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true}},\"columnOrder\":[\"c452013b-c1a4-444a-9861-fd5f8283dbb8\",\"72caa386-75a2-404d-996c-609cc9ce8705\",\"c38c78d3-f83a-4b39-8766-fd169aa8f1cf\",\"496f4a9c-c379-4dfc-8e74-df11f73cfa52\",\"d60e63d5-11c7-4413-b41f-139d3870723e\",\"64bc500b-17f2-4b63-99de-710ec63da6b9\",\"f1c203be-6445-4ac0-8f8f-64797cb120ba\",\"98a06023-cab2-4907-bc55-dbb722c5294a\",\"66633750-7aab-4f60-82cb-63d6b4fb604e\",\"98a06023-cab2-4907-bc55-dbb722c5294aX0\",\"98a06023-cab2-4907-bc55-dbb722c5294aX1\",\"98a06023-cab2-4907-bc55-dbb722c5294aX2\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"316d40b0-635e-4969-bf7a-b5e03e2834b4\",\"gridData\":{\"i\":\"316d40b0-635e-4969-bf7a-b5e03e2834b4\",\"y\":91,\"x\":0,\"w\":48,\"h\":12}},{\"type\":\"search\",\"title\":\"DoD OMB Report\",\"panelIndex\":\"dab055a8-39ea-4507-a004-7e78a229d7e7\",\"gridData\":{\"i\":\"dab055a8-39ea-4507-a004-7e78a229d7e7\",\"y\":103,\"x\":0,\"w\":48,\"h\":54},\"embeddableConfig\":{\"description\":\"OMB Report for the Department of Defense\",\"enhancements\":{\"dynamicActions\":{\"events\":[]}}},\"panelRefName\":\"panel_dab055a8-39ea-4507-a004-7e78a229d7e7\"}]", + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "timeFrom": "now-1y/d", + "timeRestore": true, + "timeTo": "now", + "title": "[TYCHON Quantum Command] Application Report", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "managed": false, + "originId": "601ec774-d72f-415f-90e8-df3569fa8eab", + "references": [ + { + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "name": "01b3101c-246d-448d-a05d-3a05e7747926:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:dfda3f15-fd80-541a-a930-8a72e988f26d:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "07f49118-bcf0-44f7-875a-df393ce88c47:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d0188d05-be4a-474b-8825-cf250d80d88f:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9c6edb36-c71b-5cf1-8dcd-a37de6214334:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:0ba322cf-440b-5ad3-a615-62aad7cf634c:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "ae78c400-d497-4d7f-9541-3e14fb724097:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b0c9f1de-0afd-5b7d-b3a1-fb28c055a10a:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d46a3ff4-c28b-57a1-a225-f58957519288:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "d2885626-4e44-41c7-b5ba-45c5b524280a:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:e17bab29-a9ff-52fc-911c-0fbbde37ba9b:dashboardId", + "type": "dashboard" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "01b3101c-246d-448d-a05d-3a05e7747926:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "07f49118-bcf0-44f7-875a-df393ce88c47:indexpattern-datasource-layer-e75aaba0-a144-4cc0-a761-f8be87375cb4", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "316d40b0-635e-4969-bf7a-b5e03e2834b4:indexpattern-datasource-layer-76c0d382-132a-4232-b1ba-2928d86d36eb", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091:indexpattern-datasource-layer-8e8a2d62-de50-4140-91d5-4d323f4bfe51", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "ae78c400-d497-4d7f-9541-3e14fb724097:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "d2885626-4e44-41c7-b5ba-45c5b524280a:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", + "type": "tag" + }, + { + "id": "tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report", + "name": "dab055a8-39ea-4507-a004-7e78a229d7e7:panel_dab055a8-39ea-4507-a004-7e78a229d7e7", + "type": "search" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.2.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NjUsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json new file mode 100644 index 00000000000..c00e42c7eb5 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json @@ -0,0 +1,113 @@ +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", + "panelsJSON": "{}", + "showApplySelections": false + }, + "description": "Aligns to schema 2.0.3.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "optionsJSON": "{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", + "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | Application Detail | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"name\":\"indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"341cf49e-257b-48f0-af62-9d0ae3420573\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"341cf49e-257b-48f0-af62-9d0ae3420573\":{\"columns\":{\"babddc5e-7343-42a8-941a-4d81e5d985ae\":{\"label\":\"Process Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"53541012-c568-493f-87d8-0a4800cc6dab\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"53541012-c568-493f-87d8-0a4800cc6dab\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"}},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"0f84ffed-4e62-4c1c-bedc-be51e098a775\",\"gridData\":{\"i\":\"0f84ffed-4e62-4c1c-bedc-be51e098a775\",\"y\":2,\"x\":0,\"w\":11,\"h\":7}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 20}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-KEM / Kyber\\\", \\\"desc\\\": \\\"Post-quantum \\u2014 harvest-proof\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"X25519 / ECDHE\\\", \\\"desc\\\": \\\"Elliptic curve \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"DHE / DH\\\", \\\"desc\\\": \\\"Finite-field DH \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"RSA Key Exchange\\\", \\\"desc\\\": \\\"No forward secrecy \\u2014 deprecated\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"POST-QUANTUM CRYPTOGRAPHY READINESS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"5863cc6f-de20-4892-891f-069d5a9316f9\",\"gridData\":{\"i\":\"5863cc6f-de20-4892-891f-069d5a9316f9\",\"y\":2,\"x\":11,\"w\":11,\"h\":14}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.protocol_tier\\\", \\\"size\\\": 50}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"TLS 1.3\\\", \\\"lbl\\\": \\\"TLS 1.3\\\", \\\"desc\\\": \\\"Required for PQC key exchange \\u2014 carries ML-KEM key_share\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"TLS 1.2\\\", \\\"lbl\\\": \\\"TLS 1.2\\\", \\\"desc\\\": \\\"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\\\", \\\"badge\\\": \\\"NO KEM EXT\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"TLS 1.1 or below\\\", \\\"desc\\\": \\\"Deprecated \\u2014 contains known protocol vulnerabilities, should be disabled\\\", \\\"badge\\\": \\\"DEPRECATED\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"TLS PROTOCOL VERSION\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"PREFERRED PROTOCOL \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"a293b107-7762-4b76-a2f8-6497e1d52dbf\",\"gridData\":{\"i\":\"a293b107-7762-4b76-a2f8-6497e1d52dbf\",\"y\":2,\"x\":22,\"w\":12,\"h\":14}},{\"type\":\"lens\",\"title\":\"Ports Identified\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"b5e53a68-24f0-5385-8498-35d2b3d898cc\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\":{\"columns\":{\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\":{\"label\":\"Ports \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"server.port\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"a506ec6b-bb03-4116-884b-04cea6bcb388\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"a506ec6b-bb03-4116-884b-04cea6bcb388\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"716deebb-7717-49ad-b463-7f8880f050bf\",\"gridData\":{\"i\":\"716deebb-7717-49ad-b463-7f8880f050bf\",\"y\":2,\"x\":34,\"w\":6,\"h\":14}},{\"type\":\"lens\",\"title\":\"Versions Found\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\":{\"columns\":{\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\":{\"label\":\"Version\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.software_package_version\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"a506ec6b-bb03-4116-884b-04cea6bcb388\":{\"label\":\"Count of records \",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"a506ec6b-bb03-4116-884b-04cea6bcb388\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"5b71a4a3-dde9-4d62-9791-475787c052df\",\"gridData\":{\"i\":\"5b71a4a3-dde9-4d62-9791-475787c052df\",\"y\":2,\"x\":40,\"w\":8,\"h\":14}},{\"type\":\"lens\",\"title\":\"\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"name\":\"indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"341cf49e-257b-48f0-af62-9d0ae3420573\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"341cf49e-257b-48f0-af62-9d0ae3420573\":{\"columns\":{\"babddc5e-7343-42a8-941a-4d81e5d985ae\":{\"label\":\"Directory Path\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.executable_directory\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"53541012-c568-493f-87d8-0a4800cc6dab\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"53541012-c568-493f-87d8-0a4800cc6dab\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"}},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"541e6258-f438-4fd0-b039-adcdc944bb8a\",\"gridData\":{\"i\":\"541e6258-f438-4fd0-b039-adcdc944bb8a\",\"y\":9,\"x\":0,\"w\":11,\"h\":7}},{\"type\":\"lens\",\"title\":\"Found On Assets\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"0b95bb86-15cd-5498-b469-92e6120e762b\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-978e2a9e-6e77-4b60-a432-ebb35f2ad6c1\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"bacbe082-96df-43d0-9e2b-1a8a1740c574\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"14f48029-f56d-4db1-8a48-e990270bbb64\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"oneClickFilter\":true},{\"columnId\":\"8902ba19-daec-484d-aea3-8b4ac1cce646\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"dd8a939b-f0f8-4a4b-9b34-56bde897441c\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"340cf762-1dc6-49b8-ade4-a9d707dd978d\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"690b2f8e-0eac-4633-bfa7-47ece118fe33\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"b4b643e9-ab88-4830-89c5-aa80ca3bdb7a\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"e2845484-f680-42cd-9636-e215edfe9f78\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"}],\"layerId\":\"978e2a9e-6e77-4b60-a432-ebb35f2ad6c1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"978e2a9e-6e77-4b60-a432-ebb35f2ad6c1\":{\"columns\":{\"bacbe082-96df-43d0-9e2b-1a8a1740c574\":{\"label\":\"Hostname\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.hostname\",\"isBucketed\":true,\"params\":{\"size\":500,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e4717f8a-c09e-407b-b9ea-673d108cec27\":{\"label\":\"Ports\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"server.port\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"14f48029-f56d-4db1-8a48-e990270bbb64\":{\"label\":\"Domain\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.domain\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"8902ba19-daec-484d-aea3-8b4ac1cce646\":{\"label\":\"IP\",\"dataType\":\"ip\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.ip\",\"isBucketed\":true,\"params\":{\"size\":1,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"dd8a939b-f0f8-4a4b-9b34-56bde897441c\":{\"label\":\"OS Platform\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.os.platform\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"340cf762-1dc6-49b8-ade4-a9d707dd978d\":{\"label\":\"OS Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.os.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"690b2f8e-0eac-4633-bfa7-47ece118fe33\":{\"label\":\"OS Version \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.os.version\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"b4b643e9-ab88-4830-89c5-aa80ca3bdb7a\":{\"label\":\"Weak TLS Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"e2845484-f680-42cd-9636-e215edfe9f78\":{\"label\":\"Unique TLS Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.insecure_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"bacbe082-96df-43d0-9e2b-1a8a1740c574\",\"14f48029-f56d-4db1-8a48-e990270bbb64\",\"8902ba19-daec-484d-aea3-8b4ac1cce646\",\"dd8a939b-f0f8-4a4b-9b34-56bde897441c\",\"340cf762-1dc6-49b8-ade4-a9d707dd978d\",\"690b2f8e-0eac-4633-bfa7-47ece118fe33\",\"e2845484-f680-42cd-9636-e215edfe9f78\",\"b4b643e9-ab88-4830-89c5-aa80ca3bdb7a\",\"e4717f8a-c09e-407b-b9ea-673d108cec27\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"c35ba11c-8005-4653-b5c4-0e658b426ef9\",\"gridData\":{\"i\":\"c35ba11c-8005-4653-b5c4-0e658b426ef9\",\"y\":16,\"x\":0,\"w\":48,\"h\":13}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"name\":\"indexpattern-datasource-layer-efd1c1c6-66da-400d-b474-d14414080249\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"3b1be2af-eeaa-4415-8c4d-007b2881bb77\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\",\"isMetric\":true},{\"columnId\":\"f3b310d9-1571-4d39-8e93-884fd27edcd7\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"5a5b6100-a1f3-4104-a958-fd5e97733081\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":false}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"e9535d81-cde5-48f2-8b39-795b363dc5b3\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"oneClickFilter\":true,\"colorMode\":\"none\"},{\"columnId\":\"5bf22b6b-946b-4fb0-b457-f3f292f546da\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"width\":213.33333333333334},{\"columnId\":\"c5807b1d-23db-4d1a-8498-e89968ea63c7\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.3\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":false},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.2\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":5},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLS1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"e5bdf109-436f-4b84-bd6e-80c86e7c0db4\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"96808911-ee68-4654-9dad-f5ec6c1e4136\",\"isTransposed\":false,\"isMetric\":false,\"oneClickFilter\":true},{\"columnId\":\"2dbbc91f-11c4-4396-8a71-3bd2e20b1b19\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"8904b583-14e3-46d5-a978-46c337227a48\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"3243578e-4af0-438a-879e-94b256f1d9ee\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"}],\"layerId\":\"efd1c1c6-66da-400d-b474-d14414080249\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"efd1c1c6-66da-400d-b474-d14414080249\":{\"columns\":{\"3b1be2af-eeaa-4415-8c4d-007b2881bb77\":{\"label\":\"App Process\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"f3b310d9-1571-4d39-8e93-884fd27edcd7\":{\"label\":\"Listening On\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"server.port\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"5a5b6100-a1f3-4104-a958-fd5e97733081\":{\"label\":\"Resilient\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.kex_primary_quantum_safe\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e9535d81-cde5-48f2-8b39-795b363dc5b3\":{\"label\":\"Key Exchange\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.kex_primary\",\"isBucketed\":true,\"params\":{\"size\":6,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"5bf22b6b-946b-4fb0-b457-f3f292f546da\":{\"label\":\"Cipher Suite\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.preferred_cipher\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"c5807b1d-23db-4d1a-8498-e89968ea63c7\":{\"label\":\"Protocol\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.preferred_protocol\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e5bdf109-436f-4b84-bd6e-80c86e7c0db4\":{\"label\":\"Package Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.software_package_name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"96808911-ee68-4654-9dad-f5ec6c1e4136\":{\"label\":\"Path\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.executable_directory\",\"isBucketed\":true,\"params\":{\"size\":100,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"2dbbc91f-11c4-4396-8a71-3bd2e20b1b19\":{\"label\":\"KX Count\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_key_exchange_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"8904b583-14e3-46d5-a978-46c337227a48\":{\"label\":\"Protocols\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_protocol_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"3243578e-4af0-438a-879e-94b256f1d9ee\":{\"label\":\"Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"3b1be2af-eeaa-4415-8c4d-007b2881bb77\",\"96808911-ee68-4654-9dad-f5ec6c1e4136\",\"f3b310d9-1571-4d39-8e93-884fd27edcd7\",\"e5bdf109-436f-4b84-bd6e-80c86e7c0db4\",\"5a5b6100-a1f3-4104-a958-fd5e97733081\",\"e9535d81-cde5-48f2-8b39-795b363dc5b3\",\"5bf22b6b-946b-4fb0-b457-f3f292f546da\",\"c5807b1d-23db-4d1a-8498-e89968ea63c7\",\"2dbbc91f-11c4-4396-8a71-3bd2e20b1b19\",\"8904b583-14e3-46d5-a978-46c337227a48\",\"3243578e-4af0-438a-879e-94b256f1d9ee\",\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"}},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"fb740713-8d4d-4114-8816-739a35cf7b68\",\"gridData\":{\"i\":\"fb740713-8d4d-4114-8816-739a35cf7b68\",\"y\":29,\"x\":0,\"w\":48,\"h\":15}},{\"type\":\"lens\",\"title\":\"Supported Weak Ciphers\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"a8bb1dca-9e7f-55bc-b777-050d845c3d7a\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"fccc8673-7024-4075-bd07-b717a834dfbf\"},{\"isTransposed\":false,\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"}],\"layerId\":\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\":{\"columns\":{\"fccc8673-7024-4075-bd07-b717a834dfbf\":{\"label\":\"Weak Ciphers \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"76043fbd-8e84-4b5d-83da-3712770265b8\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"fccc8673-7024-4075-bd07-b717a834dfbf\",\"76043fbd-8e84-4b5d-83da-3712770265b8\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"686a9532-a314-4685-b25c-7de7c957f361\",\"gridData\":{\"i\":\"686a9532-a314-4685-b25c-7de7c957f361\",\"y\":44,\"x\":0,\"w\":16,\"h\":18}},{\"type\":\"lens\",\"title\":\"Supported Insecure Ciphers\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"08ff1cd0-f8eb-53f9-9be5-24cff120f036\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"fccc8673-7024-4075-bd07-b717a834dfbf\"},{\"isTransposed\":false,\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"}],\"layerId\":\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\":{\"columns\":{\"fccc8673-7024-4075-bd07-b717a834dfbf\":{\"label\":\"Insecure Ciphers \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.insecure_ciphers\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"76043fbd-8e84-4b5d-83da-3712770265b8\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"fccc8673-7024-4075-bd07-b717a834dfbf\",\"76043fbd-8e84-4b5d-83da-3712770265b8\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"511cf538-0abc-44f0-a54c-3ccc2a58ba7f\",\"gridData\":{\"i\":\"511cf538-0abc-44f0-a54c-3ccc2a58ba7f\",\"y\":44,\"x\":16,\"w\":16,\"h\":18}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"fccc8673-7024-4075-bd07-b717a834dfbf\"},{\"isTransposed\":false,\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"}],\"layerId\":\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\":{\"columns\":{\"fccc8673-7024-4075-bd07-b717a834dfbf\":{\"label\":\"Supported Ciphers\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.supported_ciphers\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"76043fbd-8e84-4b5d-83da-3712770265b8\":{\"label\":\"Count of records \",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"fccc8673-7024-4075-bd07-b717a834dfbf\",\"76043fbd-8e84-4b5d-83da-3712770265b8\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"fe8e72b0-98d0-4252-bec5-c56732ed1f12\",\"gridData\":{\"i\":\"fe8e72b0-98d0-4252-bec5-c56732ed1f12\",\"y\":44,\"x\":32,\"w\":16,\"h\":18}}]", + "timeRestore": false, + "title": "[TYCHON Quantum Command] Application Detail", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "managed": false, + "originId": "d871606c-7231-4508-88b0-2a4228e4ff3d", + "references": [ + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:08ff1cd0-f8eb-53f9-9be5-24cff120f036:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "686a9532-a314-4685-b25c-7de7c957f361:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:a8bb1dca-9e7f-55bc-b777-050d845c3d7a:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "716deebb-7717-49ad-b463-7f8880f050bf:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b5e53a68-24f0-5385-8498-35d2b3d898cc:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "c35ba11c-8005-4653-b5c4-0e658b426ef9:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:0b95bb86-15cd-5498-b469-92e6120e762b:dashboardId", + "type": "dashboard" + }, + { + "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", + "name": "0f84ffed-4e62-4c1c-bedc-be51e098a775:indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + }, + { + "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", + "name": "541e6258-f438-4fd0-b039-adcdc944bb8a:indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "5b71a4a3-dde9-4d62-9791-475787c052df:indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "686a9532-a314-4685-b25c-7de7c957f361:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "716deebb-7717-49ad-b463-7f8880f050bf:indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "c35ba11c-8005-4653-b5c4-0e658b426ef9:indexpattern-datasource-layer-978e2a9e-6e77-4b60-a432-ebb35f2ad6c1", + "type": "index-pattern" + }, + { + "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", + "name": "fb740713-8d4d-4114-8816-739a35cf7b68:indexpattern-datasource-layer-efd1c1c6-66da-400d-b474-d14414080249", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "fe8e72b0-98d0-4252-bec5-c56732ed1f12:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.2.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NjYsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json new file mode 100644 index 00000000000..97572d9665b --- /dev/null +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json @@ -0,0 +1,68 @@ +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", + "panelsJSON": "{}", + "showApplySelections": false + }, + "description": "Aligns to schema 2.0.3", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"}}" + }, + "optionsJSON": "{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", + "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | Application Connections Topology | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"title\":\"QuantumApplicationList\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"754afa08-289f-5a39-bc46-04d2b9e6e76a\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"QuantumApplicationList\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Application filter list panel (multi-select) with dashboard filter integration.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"selectedApps\\\",\\n \\\"value\\\": \\\"|\\\",\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@appRowBg:click\\\",\\n \\\"update\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? replace(selectedApps, '|' + datum.app + '|', '|') : selectedApps + datum.app + '|'\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedAppsArray\\\",\\n \\\"update\\\": \\\"selectedApps == '|' ? [] : split(slice(selectedApps, 1, length(selectedApps)-1), '|')\\\"\\n },\\n {\\n \\\"name\\\": \\\"activeFilter\\\",\\n \\\"update\\\": \\\"length(selectedAppsArray) > 0 ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'terms': {'tychon.application.name': selectedAppsArray}}]}} : {'term': {'event.dataset': 'tychon.application'}}\\\"\\n },\\n {\\n \\\"name\\\": \\\"_applyAppFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@applyBtn:click\\\",\\n \\\"update\\\": \\\"kibanaAddFilter(activeFilter)\\\",\\n \\\"force\\\": true\\n }\\n ]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } },\\n \\\"aggs\\\": {\\n \\\"app_names\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"tychon.application.name\\\",\\n \\\"size\\\": 200,\\n \\\"order\\\": { \\\"_count\\\": \\\"desc\\\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.app_names.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"datum.doc_count\\\" },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"72 + (datum.rn - 1) * 26\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rn <= 15\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLICATION FILTER\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"applyBtn\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 92\\\" },\\n \\\"y\\\": { \\\"value\\\": 16 },\\n \\\"width\\\": { \\\"value\\\": 76 },\\n \\\"height\\\": { \\\"value\\\": 20 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#9fd7ff\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 54\\\" },\\n \\\"y\\\": { \\\"value\\\": 26 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLY\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#dff0ff\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"name\\\": \\\"appRowBg\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 18 },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y - 10\\\" },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 18\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"datum.y + 10\\\" },\\n \\\"cornerRadius\\\": { \\\"value\\\": 6 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#1f4d74' : '#0f1115'\\\" },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#9fd7ff' : '#253241'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 30 },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"app\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#e8f3ff' : '#c9d7e5'\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - 110\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 30\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(datum.count, ',')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#d9eeff' : '#8ea3b8'\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"right\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"5de2ae04-5993-4e9b-9c32-674ec15c23cb\",\"gridData\":{\"i\":\"5de2ae04-5993-4e9b-9c32-674ec15c23cb\",\"y\":2,\"x\":0,\"w\":8,\"h\":19}},{\"type\":\"visualization\",\"title\":\"PQC Connections Topology\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"PQC Connections Topology\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 8,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"zoom\\\",\\n \\\"value\\\": 0.55,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6)\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panX\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panX - (width/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (width/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panX + event.movementX\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panY\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panY - (height/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (height/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panY + event.movementY\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedNode\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:click\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? (selectedNode && selectedNode.id===datum.id ? null : datum) : selectedNode\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"_applyNodeFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:dblclick\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? kibanaAddFilter((datum.nodeType === 'application' ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'tychon.application.name': toString(datum.id)}}]}} : {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'host.hostname': toString(datum.id)}}]}})) : 0\\\",\\n \\\"force\\\": true\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjPeerIds\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency')) ? pluck(data('adjacency'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"adjPeer2Ids\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency2')) ? pluck(data('adjacency2'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"highlightNodeIdsCsv\\\",\\n \\\"update\\\": \\\"selectedNode ? (',' + toString(selectedNode.id) + ',' + join(adjPeerIds, ',') + ',' + join(adjPeer2Ids, ',') + ',') : ''\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanX\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cx) ? (width * 0.5) - (data('layout_center')[0].cx * zoom) : (width * (1 - zoom) * 0.5)\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanY\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cy) ? (height * 0.52) - (data('layout_center')[0].cy * zoom) : (height * (1 - zoom) * 0.5)\\\"\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"pairs\\\": {\\n \\\"filter\\\": {\\n \\\"bool\\\": {\\n \\\"must\\\": [\\n { \\\"exists\\\": { \\\"field\\\": \\\"host.hostname\\\" } },\\n { \\\"exists\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } },\\n { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } }\\n ]\\n }\\n },\\n \\\"aggs\\\": {\\n \\\"links\\\": {\\n \\\"composite\\\": {\\n \\\"size\\\": 500,\\n \\\"sources\\\": [\\n { \\\"src\\\": { \\\"terms\\\": { \\\"field\\\": \\\"host.hostname\\\" } } },\\n { \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } } }\\n ]\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.pairs.links.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"datum.key.src\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"datum.key.dst\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.doc_count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.target) && datum.source!='' && datum.target!=''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"nodes\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"source\\\", \\\"target\\\"], \\\"as\\\": [\\\"side\\\", \\\"id\\\"] },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"id\\\", \\\"side\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"nodeType\\\", \\\"expr\\\": \\\"datum.side==='source' ? 'host' : 'application'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.source != '' && datum.target != ''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout\\\",\\n \\\"source\\\": \\\"nodes\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"force\\\",\\n \\\"iterations\\\": 300,\\n \\\"static\\\": true,\\n \\\"forces\\\": [\\n { \\\"force\\\": \\\"center\\\", \\\"x\\\": { \\\"signal\\\": \\\"width * 0.5\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"height * 0.52\\\" } },\\n { \\\"force\\\": \\\"collide\\\", \\\"radius\\\": 20 },\\n { \\\"force\\\": \\\"nbody\\\", \\\"strength\\\": -180 },\\n { \\\"force\\\": \\\"link\\\", \\\"links\\\": \\\"edges\\\", \\\"id\\\": \\\"id\\\", \\\"distance\\\": 130 }\\n ]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout_center\\\",\\n \\\"source\\\": \\\"layout\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"ops\\\": [\\\"median\\\", \\\"median\\\"],\\n \\\"fields\\\": [\\\"x\\\", \\\"y\\\"],\\n \\\"as\\\": [\\\"cx\\\", \\\"cy\\\"]\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cx\\\", \\\"expr\\\": \\\"isFinite(datum.cx) ? datum.cx : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cy\\\", \\\"expr\\\": \\\"isFinite(datum.cy) ? datum.cy : 0\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges_draw\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sx\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.x) ? datum.source.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sy\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.y) ? datum.source.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tx\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.x) ? datum.target.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"ty\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.y) ? datum.target.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.sx) && isValid(datum.sy) && isValid(datum.tx) && isValid(datum.ty)\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (datum.srcId===toString(selectedNode.id) || datum.dstId===toString(selectedNode.id))\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id)\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency2\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (indexof(adjPeerIds, datum.srcId) >= 0 || indexof(adjPeerIds, datum.dstId) >= 0)\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id) && indexof(adjPeerIds, datum.peer) < 0\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"edges_draw\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"field\\\": \\\"sx\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"sy\\\" },\\n \\\"x2\\\": { \\\"field\\\": \\\"tx\\\" },\\n \\\"y2\\\": { \\\"field\\\": \\\"ty\\\" },\\n \\\"stroke\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? '#4fc3f7' : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? '#7fe8ff' : '#213240')\\\"\\n },\\n \\\"strokeOpacity\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? 0.42 : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? 0.75 : 0.08)\\\"\\n },\\n \\\"strokeWidth\\\": { \\\"value\\\": 0.9 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#3b2b1a' : '#1a2c3b'\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.9 },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#ffd7a2' : '#a9dbff'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"opacity\\\": { \\\"signal\\\": \\\"!selectedNode ? 1 : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? 1 : 0.2)\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"name\\\": \\\"nodeMark\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"strokeOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n },\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY - 14\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"id\\\" },\\n \\\"fill\\\": { \\\"signal\\\": \\\"!selectedNode ? '#e0e0e0' : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? '#f2f7ff' : '#4f5f6f')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"bottom\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"b07160f8-34a0-4c9c-b8e0-40c7841c9f86\",\"gridData\":{\"i\":\"b07160f8-34a0-4c9c-b8e0-40c7841c9f86\",\"y\":2,\"x\":8,\"w\":30,\"h\":36}},{\"type\":\"visualization\",\"title\":\"Connections Selection Details\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"28bdb45d-bec5-5991-b0c4-e7c31df068c4\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Connections Selection Details\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection details panel for host/application context using dashboard filters.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"panelW\\\", \\\"update\\\": \\\"width - 20\\\" },\\n { \\\"name\\\": \\\"labelX\\\", \\\"value\\\": 26 },\\n { \\\"name\\\": \\\"valueX\\\", \\\"update\\\": \\\"width * 0.42\\\" },\\n { \\\"name\\\": \\\"row0\\\", \\\"value\\\": 74 },\\n { \\\"name\\\": \\\"rowH\\\", \\\"value\\\": 24 }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"context\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"host\\\": { \\\"terms\\\": { \\\"field\\\": \\\"observer.hostname\\\", \\\"size\\\": 1 } },\\n \\\"app\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name.keyword\\\", \\\"size\\\": 1 } },\\n \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"server.address\\\", \\\"size\\\": 1 } },\\n \\\"proto\\\": { \\\"terms\\\": { \\\"field\\\": \\\"network.protocol\\\", \\\"size\\\": 1 } },\\n \\\"tls_ver\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_protocol\\\", \\\"size\\\": 1 } },\\n \\\"cipher\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_cipher\\\", \\\"size\\\": 1 } },\\n \\\"events\\\": { \\\"value_count\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"first_seen\\\": { \\\"min\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"last_seen\\\": { \\\"max\\\": { \\\"field\\\": \\\"@timestamp\\\" } }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"host\\\",\\n \\\"expr\\\": \\\"datum.host && datum.host.buckets && length(datum.host.buckets)>0 ? datum.host.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app\\\",\\n \\\"expr\\\": \\\"datum.app && datum.app.buckets && length(datum.app.buckets)>0 ? datum.app.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"dst\\\",\\n \\\"expr\\\": \\\"datum.dst && datum.dst.buckets && length(datum.dst.buckets)>0 ? datum.dst.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"proto\\\",\\n \\\"expr\\\": \\\"datum.proto && datum.proto.buckets && length(datum.proto.buckets)>0 ? datum.proto.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tlsVer\\\",\\n \\\"expr\\\": \\\"datum.tls_ver && datum.tls_ver.buckets && length(datum.tls_ver.buckets)>0 ? datum.tls_ver.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"cipher\\\",\\n \\\"expr\\\": \\\"datum.cipher && datum.cipher.buckets && length(datum.cipher.buckets)>0 ? datum.cipher.buckets[0].key : ''\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"events\\\", \\\"expr\\\": \\\"datum.events ? datum.events.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"firstSeen\\\",\\n \\\"expr\\\": \\\"datum.first_seen && isValid(datum.first_seen.value_as_string) ? datum.first_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"lastSeen\\\",\\n \\\"expr\\\": \\\"datum.last_seen && isValid(datum.last_seen.value_as_string) ? datum.last_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionType\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? 'APPLICATION CONTEXT' : (datum.host != '' ? 'HOST CONTEXT' : 'NO SELECTION')\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionId\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? datum.app : (datum.host != '' ? datum.host : 'Select a host/app in the graph')\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"context\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"project\\\",\\n \\\"fields\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ],\\n \\\"as\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ]\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"kv\\\",\\n \\\"expr\\\": \\\"[{k:'Context',v:datum.selectionType},{k:'Selection',v:datum.selectionId},{k:'Source Host',v:datum.host},{k:'Application',v:datum.app},{k:'Destination',v:datum.dst},{k:'Protocol',v:datum.proto},{k:'TLS Version',v:datum.tlsVer},{k:'Cipher',v:datum.cipher},{k:'Event Count',v:format(datum.events, ',')},{k:'First Seen',v:datum.firstSeen},{k:'Last Seen',v:datum.lastSeen}]\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"kv\\\"], \\\"as\\\": [\\\"row\\\"] },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"row0 + (datum.rn - 1) * rowH\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"SELECTION DETAILS\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX - 10\\\" },\\n \\\"y\\\": { \\\"value\\\": 54 },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 20\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#1f2a36\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"labelX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.k\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#9fc4e0\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.v == '' ? '\\u2014' : datum.row.v\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8eef5\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - valueX - 18\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"903af92d-f9ab-4b97-8f31-4f46b66f7b49\",\"gridData\":{\"i\":\"903af92d-f9ab-4b97-8f31-4f46b66f7b49\",\"y\":2,\"x\":38,\"w\":10,\"h\":15}},{\"type\":\"visualization\",\"title\":\"Application PQC Dashboard Risk\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9ee0be55-05bd-533b-b46b-ac541ed779ff\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Application PQC Dashboard Risk\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"totalApps\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"protoReady\\\", \\\"update\\\": \\\"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"protoPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"protoClr\\\", \\\"update\\\": \\\"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"barW\\\", \\\"update\\\": \\\"width * 0.62 - 18\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"proto_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"proto_pqc\\\", \\\"source\\\": \\\"proto_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"APPLICATION PQC DASHBOARD\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"signal\\\": \\\"'PQC COMPLIANCE PROGRESS \\u2014 ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"KEX COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY key exchange'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"PROTOCOL COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 TLS 1.3 capable'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * protoPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"protoPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 218},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 238},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 253},\\n \\\"text\\\": {\\\"signal\\\": \\\"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY signature'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * sigPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 282},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"6f785f49-4d43-42cb-92f3-c80b2c06f45d\",\"gridData\":{\"i\":\"6f785f49-4d43-42cb-92f3-c80b2c06f45d\",\"y\":17,\"x\":38,\"w\":10,\"h\":12}},{\"type\":\"visualization\",\"title\":\"Aggregate Risk Determination\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"6e39195a-0cb6-50af-9f4c-94de184a31c3\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"QuantumRiskRadial\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection risk dial aligned to inventory OMB readiness tiers.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"cx\\\", \\\"update\\\": \\\"width/2\\\" },\\n { \\\"name\\\": \\\"cy\\\", \\\"update\\\": \\\"height*0.56\\\" },\\n { \\\"name\\\": \\\"r\\\", \\\"update\\\": \\\"min(width, height) * 0.34\\\" }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"risk\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"apps_total\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } },\\n \\\"kex_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.kex_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"proto_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"sig_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.sig_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"isValid(datum.apps_total) && isValid(datum.apps_total.value) ? max(1, datum.apps_total.value) : 1\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"kex_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.kex_ready) && isValid(datum.kex_ready.u) && isValid(datum.kex_ready.u.value) ? datum.kex_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"proto_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.proto_ready) && isValid(datum.proto_ready.u) && isValid(datum.proto_ready.u.value) ? datum.proto_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sig_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.sig_ready) && isValid(datum.sig_ready.u) && isValid(datum.sig_ready.u.value) ? datum.sig_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_kex_ready\\\", \\\"expr\\\": \\\"100 * datum.kex_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_proto_ready\\\", \\\"expr\\\": \\\"100 * datum.proto_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_sig_ready\\\", \\\"expr\\\": \\\"100 * datum.sig_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"readiness\\\", \\\"expr\\\": \\\"clamp(round((datum.p_kex_ready + datum.p_proto_ready + datum.p_sig_ready) / 3), 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"score\\\", \\\"expr\\\": \\\"clamp(100 - datum.readiness, 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? 'LOW' : datum.readiness >= 60 ? 'MEDIUM' : 'HIGH'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"color\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? '#22c55e' : datum.readiness >= 60 ? '#f59e0b' : '#ef4444'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"angle\\\", \\\"expr\\\": \\\"-3.1415926 + (datum.score/100) * 3.1415926 * 2\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"value\\\": 3.1415926},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1f2937\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"field\\\": \\\"angle\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy - 6\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.score, 'd') + '/100'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 28}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + 24\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.tier + ' RISK'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cfe3f7\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"7bb23bb3-53f1-48c8-914c-4108cf26dc05\",\"gridData\":{\"i\":\"7bb23bb3-53f1-48c8-914c-4108cf26dc05\",\"y\":21,\"x\":0,\"w\":8,\"h\":11}}]", + "timeRestore": false, + "title": "[TYCHON Quantum Command] Application Connections Topology", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "managed": false, + "originId": "67c35d70-7848-45c9-80e1-93a359eccf5b", + "references": [ + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "5de2ae04-5993-4e9b-9c32-674ec15c23cb:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:754afa08-289f-5a39-bc46-04d2b9e6e76a:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "6f785f49-4d43-42cb-92f3-c80b2c06f45d:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9ee0be55-05bd-533b-b46b-ac541ed779ff:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "7bb23bb3-53f1-48c8-914c-4108cf26dc05:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:6e39195a-0cb6-50af-9f4c-94de184a31c3:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "903af92d-f9ab-4b97-8f31-4f46b66f7b49:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:28bdb45d-bec5-5991-b0c4-e7c31df068c4:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.2.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NzIsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json new file mode 100644 index 00000000000..e76c1b2f4e2 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json @@ -0,0 +1,92 @@ +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", + "panelsJSON": "{}", + "showApplySelections": false + }, + "description": "Operational view of all discovered certificates — quantum readiness, hygiene, key algorithms, and issuer coverage", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"}}" + }, + "optionsJSON": "{\"useMargins\":false,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":true,\"hidePanelTitles\":true}", + "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | Certificate Report | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"title\":\"CERT OPS — Inventory Header\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Inventory Header\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"total\\\", \\\"update\\\": \\\"length(data('d_total'))>0 ? data('d_total')[0].n : 0\\\"}, {\\\"name\\\": \\\"expired\\\", \\\"update\\\": \\\"length(data('d_expired'))>0 ? data('d_expired')[0].n : 0\\\"}, {\\\"name\\\": \\\"exp30\\\", \\\"update\\\": \\\"length(data('d_exp30'))>0 ? data('d_exp30')[0].n : 0\\\"}, {\\\"name\\\": \\\"self\\\", \\\"update\\\": \\\"length(data('d_self'))>0 ? data('d_self')[0].n : 0\\\"}, {\\\"name\\\": \\\"legacy\\\", \\\"update\\\": \\\"length(data('d_legacy'))>0 ? data('d_legacy')[0].n : 0\\\"}, {\\\"name\\\": \\\"pqcvuln\\\", \\\"update\\\": \\\"length(data('d_pqcvuln'))>0 ? data('d_pqcvuln')[0].n : 0\\\"}, {\\\"name\\\": \\\"bw\\\", \\\"update\\\": \\\"floor((width - 10) / 6) - 4\\\"}, {\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? null : datum.k) : sel\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_total\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"d_expired\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_exp30\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_self\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_legacy\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_pqcvuln\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tiles\\\", \\\"values\\\": [{\\\"k\\\": \\\"TOTAL\\\", \\\"ord\\\": 0, \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"sig\\\": \\\"total\\\", \\\"filt\\\": null}, {\\\"k\\\": \\\"EXPIRED\\\", \\\"ord\\\": 1, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"ord\\\": 2, \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"sig\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"ord\\\": 3, \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"sig\\\": \\\"self\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"LEGACY\\\", \\\"ord\\\": 4, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"legacy\\\", \\\"filt\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}, {\\\"k\\\": \\\"PQC VULN\\\", \\\"ord\\\": 5, \\\"clr\\\": \\\"#ab47bc\\\", \\\"bg\\\": \\\"#ab47bc18\\\", \\\"sig\\\": \\\"pqcvuln\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"x\\\", \\\"expr\\\": \\\"datum.ord * (bw + 4) + 8\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"val\\\", \\\"expr\\\": \\\"datum.sig === 'total' ? total : datum.sig === 'expired' ? expired : datum.sig === 'exp30' ? exp30 : datum.sig === 'self' ? self : datum.sig === 'legacy' ? legacy : pqcvuln\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE INVENTORY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL OVERVIEW \\\\u2014 click a tile to filter the dashboard\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"tile\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"field\\\": \\\"x\\\"}, \\\"y\\\": {\\\"value\\\": 52}, \\\"width\\\": {\\\"signal\\\": \\\"bw\\\"}, \\\"height\\\": {\\\"value\\\": 72}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.bg : '#161616'\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 && datum.filt ? '#2a2a3a' : '#222222')\\\"}, \\\"strokeWidth\\\": {\\\"signal\\\": \\\"datum.k === sel ? 2 : 1\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 88}, \\\"text\\\": {\\\"signal\\\": \\\"datum.val >= 1000 ? format(datum.val,'.3~s') : format(datum.val,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 ? datum.clr : '#3a3a3a')\\\"}, \\\"fontSize\\\": {\\\"value\\\": 22}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 108}, \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : '#666666'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"74b385d6-da5a-438e-a0af-f1a77dab28db\",\"gridData\":{\"i\":\"74b385d6-da5a-438e-a0af-f1a77dab28db\",\"y\":2,\"x\":0,\"w\":48,\"h\":8}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Quantum Tier\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"f676853f-014e-5857-89ba-97b22fb271af\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Quantum Tier\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 10}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tc\\\", \\\"source\\\": \\\"raw\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"]}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"tc\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature \\\\u2014 quantum-resistant, CNSA 2.0 approved\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0}, {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve \\\\u2014 quantum-vulnerable via Shor's algorithm, must be replaced pre-2035\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1}, {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA \\\\u2014 quantum-vulnerable via Shor's algorithm, harvest-now-decrypt-later risk today\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}, {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"SHA-1/MD5 hash \\\\u2014 classically broken and quantum-vulnerable, replace immediately\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#b71c1c\\\", \\\"bg\\\": \\\"#b71c1c22\\\", \\\"ord\\\": 3}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM \\\\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 55}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.5\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"}, \\\"height\\\": {\\\"value\\\": 6}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"187d7c49-96d6-43fe-a3d7-ee51f605e0f5\",\"gridData\":{\"i\":\"187d7c49-96d6-43fe-a3d7-ee51f605e0f5\",\"y\":10,\"x\":0,\"w\":16,\"h\":29}},{\"type\":\"visualization\",\"title\":\"Certificate Hygiene\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"c9ef7c09-bbcf-57c7-bcbc-d3fae0140da2\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Certificate Hygiene\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"expired\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, \\\"exp30\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, \\\"exp90\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, \\\"selfsign\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, \\\"weakkey\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}, \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"expired\\\", \\\"expr\\\": \\\"datum.expired ? datum.expired.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp30\\\", \\\"expr\\\": \\\"datum.exp30 ? datum.exp30.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp90\\\", \\\"expr\\\": \\\"datum.exp90 ? datum.exp90.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"selfsign\\\", \\\"expr\\\": \\\"datum.selfsign ? datum.selfsign.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"weakkey\\\", \\\"expr\\\": \\\"datum.weakkey ? datum.weakkey.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total\\\", \\\"expr\\\": \\\"datum.total ? datum.total.value : 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"EXPIRED\\\", \\\"lbl\\\": \\\"Expired\\\", \\\"desc\\\": \\\"certificate.not_after < now \\\\u2014 no longer trusted by any client\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"lbl\\\": \\\"Expiring in 30 days\\\", \\\"desc\\\": \\\"certificate.not_after within 30 days \\\\u2014 immediate renewal required\\\", \\\"sev\\\": \\\"high\\\", \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"EXP 90D\\\", \\\"lbl\\\": \\\"Expiring in 90 days\\\", \\\"desc\\\": \\\"certificate.not_after within 90 days \\\\u2014 plan renewal now\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"exp90\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"lbl\\\": \\\"Self-Signed\\\", \\\"desc\\\": \\\"certificate.is_self_signed = true \\\\u2014 no CA trust chain, browser errors\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"selfsign\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"WEAK KEY\\\", \\\"lbl\\\": \\\"Weak Key \\\\u22641024-bit\\\", \\\"desc\\\": \\\"RSA/DSA key \\\\u22641024 bits \\\\u2014 computationally breakable, must be replaced\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"weakkey\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"raw\\\", \\\"key\\\": \\\"total\\\", \\\"fields\\\": [\\\"ord\\\"], \\\"values\\\": [\\\"expired\\\", \\\"exp30\\\", \\\"exp90\\\", \\\"selfsign\\\", \\\"weakkey\\\", \\\"total\\\"], \\\"as\\\": [\\\"v_expired\\\", \\\"v_exp30\\\", \\\"v_exp90\\\", \\\"v_selfsign\\\", \\\"v_weakkey\\\", \\\"v_total\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.field==='expired' ? (length(data('raw'))>0?data('raw')[0].expired:0) : datum.field==='exp30' ? (length(data('raw'))>0?data('raw')[0].exp30:0) : datum.field==='exp90' ? (length(data('raw'))>0?data('raw')[0].exp90:0) : datum.field==='selfsign' ? (length(data('raw'))>0?data('raw')[0].selfsign:0) : (length(data('raw'))>0?data('raw')[0].weakkey:0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? data('raw')[0].total : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 68 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE HYGIENE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL ISSUES \\\\u2014 expiry \\\\u00b7 trust \\\\u00b7 key strength\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? datum.bg : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 61\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sev\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 29\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 14}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#333333' : '#222222'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 ? format(datum.pct * 100, '.1f') + '%' : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"48d7d98f-27df-4c04-a736-8e772da0b028\",\"gridData\":{\"i\":\"48d7d98f-27df-4c04-a736-8e772da0b028\",\"y\":10,\"x\":16,\"w\":16,\"h\":29}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Top Issuing CAs\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"5a19f6d5-01ea-5a0d-9469-870400433156\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Top Issuing CAs\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.issuer_organization': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.issuer_organization': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_issuer\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.issuer_organization\\\", \\\"size\\\": 10, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_issuer.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 52 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.rnk === 1 ? '#448aff' : datum.rnk === 2 ? '#4db6ac' : datum.rnk <= 5 ? '#546e7a' : '#37474f'\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"TOP ISSUING CAs\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE AUTHORITY — who issued your certificates · click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 30}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.rnk, 'd') + '.'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.62\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.62) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 5}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '66'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 45\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#888888'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"df2ef032-250b-40c9-93de-3f6211bddac5\",\"gridData\":{\"i\":\"df2ef032-250b-40c9-93de-3f6211bddac5\",\"y\":10,\"x\":32,\"w\":16,\"h\":29}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Key Algorithm\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"195b2262-1d5d-50e1-86d2-f404cd493030\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Key Algorithm\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_algo\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.algorithm\\\", \\\"size\\\": 10}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_algo.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"palette\\\",\\n \\\"values\\\": [\\n {\\\"k\\\": \\\"RSA\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"lbl\\\": \\\"RSA\\\", \\\"desc\\\": \\\"Rivest–Shamir–Adleman — quantum-vulnerable via Shor's algorithm\\\"},\\n {\\\"k\\\": \\\"ECDSA\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"lbl\\\": \\\"ECDSA\\\", \\\"desc\\\": \\\"Elliptic curve — quantum-vulnerable, efficient on classical hardware\\\"},\\n {\\\"k\\\": \\\"DSA\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"lbl\\\": \\\"DSA\\\", \\\"desc\\\": \\\"Digital Signature Algorithm — deprecated, should not be in new certs\\\"},\\n {\\\"k\\\": \\\"unknown_der\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown DER\\\", \\\"desc\\\": \\\"DER-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"unknown_pem\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown PEM\\\", \\\"desc\\\": \\\"PEM-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"ML-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"ML-DSA\\\", \\\"desc\\\": \\\"Lattice-based PQC signature — CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"SLH-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"SLH-DSA\\\", \\\"desc\\\": \\\"Hash-based PQC signature — CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"FN-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"FN-DSA\\\", \\\"desc\\\": \\\"Falcon lattice signature — CNSA 2.0 quantum-resistant\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"palette\\\", \\\"key\\\": \\\"k\\\", \\\"fields\\\": [\\\"k\\\"],\\n \\\"values\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"], \\\"as\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"],\\n \\\"default\\\": \\\"#78909c\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.clr || '#78909c'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.bg || '#78909c18'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"lbl\\\", \\\"expr\\\": \\\"datum.lbl || datum.k\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\", \\\"expr\\\": \\\"datum.desc || 'Unrecognized key algorithm'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bw\\\", \\\"expr\\\": \\\"width * 0.58 - 110\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"rows\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"PUBLIC KEY TYPE — click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161622' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.4\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 10}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '88'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"65669cd8-396b-410c-bc9b-ee3389ef8017\",\"gridData\":{\"i\":\"65669cd8-396b-410c-bc9b-ee3389ef8017\",\"y\":39,\"x\":0,\"w\":16,\"h\":30}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Key Size Distribution\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"4cb43ecb-be8e-5b80-8c8e-32e171de9e03\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Key Size Distribution\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_size\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.bit_size\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_size.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sz\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"toString(datum.key) + '-bit'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef5350' : datum.key <= 2048 ? '#ffa726' : datum.key <= 3072 ? '#448aff' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef535018' : datum.key <= 2048 ? '#ffa72618' : datum.key <= 3072 ? '#448aff18' : '#00c85318'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'CRITICAL' : datum.key <= 1024 ? 'WEAK' : datum.key <= 2048 ? 'CLASSICAL' : datum.key <= 3072 ? 'STRONG' : 'CNSA 2.0'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'Trivially breakable — remove immediately' : datum.key <= 1024 ? 'Below NIST minimum — must be replaced' : datum.key === 2048 ? 'RSA-2048 / ECDSA-P256 — classical standard, quantum-vulnerable' : datum.key === 3072 ? 'RSA-3072 — transitional strength, quantum-vulnerable' : datum.key === 4096 ? 'RSA-4096 — strong classical, quantum-vulnerable' : datum.key === 256 ? 'ECDSA-P256 — modern elliptic curve' : datum.key === 384 ? 'ECDSA-P384 — strong elliptic curve (CNSA 1.0)' : 'Key size ' + datum.key\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY SIZE DISTRIBUTION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"BIT STRENGTH — click to filter · CNSA 2.0 requires RSA ≥3072 or ECDSA P-384\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"},\\n \\\"width\\\": {\\\"value\\\": 64}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58 + 32\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 27\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 64 : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 12}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3a8c4d30-8553-4034-91da-f7010ef7b182\",\"gridData\":{\"i\":\"3a8c4d30-8553-4034-91da-f7010ef7b182\",\"y\":39,\"x\":16,\"w\":16,\"h\":30}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Signature Algorithm\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"5e8c06e1-fcf5-5aab-b7bc-c3cdc891baee\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Signature Algorithm\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_sig\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.signature_algorithm\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_sig.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef5350' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef5350' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa726' : datum.key === 'N/A' || datum.key === '0' ? '#555555' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef535018' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef535018' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff18' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa72618' : '#55555518'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'BROKEN' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? 'LEGACY' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? 'MODERN' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? 'CLASSICAL' : datum.key === 'N/A' || datum.key === '0' ? 'UNKNOWN' : 'PQC READY'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'MD5 collision attacks are trivial — critically broken' : datum.key === 'SHA1-RSA' ? 'SHA-1 deprecated — browsers reject, fails compliance' : datum.key === 'DSA-SHA1' ? 'DSA with SHA-1 — both deprecated, remove immediately' : datum.key === 'SHA256-RSA' ? 'RSA with SHA-256 — dominant classical standard' : datum.key === 'SHA384-RSA' ? 'RSA with SHA-384 — stronger hash, still quantum-vulnerable' : datum.key === 'SHA512-RSA' ? 'RSA with SHA-512 — strongest classical RSA variant' : datum.key === 'ECDSA-SHA256' ? 'ECDSA with SHA-256 — modern, efficient, quantum-vulnerable' : datum.key === 'ECDSA-SHA384' ? 'ECDSA with SHA-384 — CNSA 1.0 approved, quantum-vulnerable' : 'Signature algorithm'\\\"},\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.k !== 'N/A' && datum.k !== '0'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 66 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES ARE SIGNED — click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 59\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.42\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 6\\\"},\\n \\\"width\\\": {\\\"value\\\": 68}, \\\"height\\\": {\\\"value\\\": 15}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60 + 34\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 18\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 32\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 47\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3fa6122b-517f-47d6-b194-2fcea3de3332\",\"gridData\":{\"i\":\"3fa6122b-517f-47d6-b194-2fcea3de3332\",\"y\":39,\"x\":32,\"w\":16,\"h\":30}},{\"type\":\"visualization\",\"title\":\"Certificate Longevity\",\"embeddableConfig\":{\"description\":\"Certificate lifetime buckets: automated (≤90d) through legacy (>5yr) with key management system insight\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"8de715c9-8769-51a8-8672-32a3af72a8c7\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Certificate Longevity\",\"description\":\"Certificate lifetime buckets: automated (≤90d) through legacy (>5yr) with key management system insight\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"le90d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();if(na<=System.currentTimeMillis())return false;long d=(na-nb)/86400000L;return d>=0&&d<=90;\\\"}}}}, \\\"le1yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>90&&d<=365;\\\"}}}}, \\\"le825d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>365&&d<=825;\\\"}}}}, \\\"le5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>825&&d<=1825;\\\"}}}}, \\\"gt5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>1825;\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le90d\\\", \\\"expr\\\": \\\"datum.le90d ? datum.le90d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le1yr\\\", \\\"expr\\\": \\\"datum.le1yr ? datum.le1yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le825d\\\", \\\"expr\\\": \\\"datum.le825d ? datum.le825d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le5yr\\\", \\\"expr\\\": \\\"datum.le5yr ? datum.le5yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"gt5yr\\\", \\\"expr\\\": \\\"datum.gt5yr ? datum.gt5yr.doc_count : 0\\\"}]}, {\\\"name\\\": \\\"tot\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"le90d\\\", \\\"lbl\\\": \\\"Automated \\\\u226490 days\\\", \\\"mgmt\\\": \\\"KEY MGT SYSTEM\\\", \\\"desc\\\": \\\"Almost certainly managed by ACME / Let's Encrypt / cert-manager \\\\u2014 short lifetime is a signature of automated issuance\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"le90d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gte\\\": 0, \\\"lte\\\": 90}}}}, {\\\"k\\\": \\\"le1yr\\\", \\\"lbl\\\": \\\"Short-lived \\\\u22641 year\\\", \\\"mgmt\\\": \\\"LIKELY MANAGED\\\", \\\"desc\\\": \\\"Annual lifetime pattern \\\\u2014 may be automated renewal or disciplined manual rotation by an ops team\\\", \\\"clr\\\": \\\"#4db6ac\\\", \\\"bg\\\": \\\"#4db6ac18\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"le1yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 90, \\\"lte\\\": 365}}}}, {\\\"k\\\": \\\"le825d\\\", \\\"lbl\\\": \\\"Modern \\\\u2264825 days\\\", \\\"mgmt\\\": \\\"CA ISSUED\\\", \\\"desc\\\": \\\"Within Apple / browser maximum trust limit (825 days) \\\\u2014 actively issued by a real CA, rotation expected\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"le825d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 365, \\\"lte\\\": 825}}}}, {\\\"k\\\": \\\"le5yr\\\", \\\"lbl\\\": \\\"Long-lived \\\\u22645 years\\\", \\\"mgmt\\\": \\\"MANUAL\\\", \\\"desc\\\": \\\"826\\\\u20131825 day lifetime \\\\u2014 manually managed, no automated rotation, quantum risk grows over the certificate's life\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"le5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 825, \\\"lte\\\": 1825}}}}, {\\\"k\\\": \\\"gt5yr\\\", \\\"lbl\\\": \\\"Legacy > 5 years\\\", \\\"mgmt\\\": \\\"LEGACY / MANUAL\\\", \\\"desc\\\": \\\"5+ year validity \\\\u2014 definitely manually issued; each year of remaining life increases the window for harvest-now-decrypt-later attacks\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"gt5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 1825}}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? (datum.field==='le90d' ? data('raw')[0].le90d : datum.field==='le1yr' ? data('raw')[0].le1yr : datum.field==='le825d' ? data('raw')[0].le825d : datum.field==='le5yr' ? data('raw')[0].le5yr : data('raw')[0].gt5yr) : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 52\\\"}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"rows\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LONGEVITY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LIFETIME \\\\u2014 short = automated key management \\\\u00b7 long = manual / legacy\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161616' : '#121212'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.52\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 42\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.74\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76 + 41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"mgmt\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 28\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 82 : 0\\\"}, \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '44'\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 52\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 && datum.n > 0 ? format(datum.pct * 100, '.1f') + '%' : ''\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2\",\"gridData\":{\"i\":\"d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2\",\"y\":69,\"x\":0,\"w\":24,\"h\":22}},{\"type\":\"visualization\",\"title\":\"Certificate Source Type\",\"embeddableConfig\":{\"description\":\"File system disk scan vs live TLS port capture — how each certificate was discovered\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"d14a762a-33a5-545d-9c69-b36b1279da31\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Certificate Source Type\",\"description\":\"File system disk scan vs live TLS port capture — how each certificate was discovered\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_fs\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"term\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"d_port\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-inventory*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"bool\\\": {\\\"must\\\": [{\\\"exists\\\": {\\\"field\\\": \\\"x509.subject.common_name\\\"}}, {\\\"term\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}]}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"fs\\\", \\\"ord\\\": 0, \\\"lbl\\\": \\\"File System\\\", \\\"badge\\\": \\\"DISK\\\", \\\"sub\\\": \\\"Certificates read from disk \\\\u2014 PEM/DER files, keystores, application bundles\\\", \\\"desc\\\": \\\"Found by crawling the local filesystem. Source path is known. These certs may not be actively serving traffic \\\\u2014 they could be backups, bundled CA roots, or application trust stores.\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"icon\\\": \\\"\\\\u2399\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}}, {\\\"k\\\": \\\"port\\\", \\\"ord\\\": 1, \\\"lbl\\\": \\\"Port / Network\\\", \\\"badge\\\": \\\"NETWORK\\\", \\\"sub\\\": \\\"Certificates captured live from TLS handshakes on open network ports\\\", \\\"desc\\\": \\\"Captured during an active TLS scan. These certs are definitely in use serving live traffic. Quantum readiness score and cipher suite are also available for these entries.\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"icon\\\": \\\"\\\\u26a1\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.k === 'fs' ? (length(data('d_fs'))>0 ? data('d_fs')[0].n : 0) : (length(data('d_port'))>0 ? data('d_port')[0].n : 0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 134 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SOURCE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES WERE DISCOVERED \\\\u2014 file scan vs live TLS capture\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"row_bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? '#1c1c2e' : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 127\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 10\\\"}, \\\"width\\\": {\\\"value\\\": 56}, \\\"height\\\": {\\\"value\\\": 18}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 42}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 23\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 78}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sub\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.82\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 64\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.64\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 70\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n, '.3~s') : format(datum.n, ',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 32}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 88\\\"}, \\\"text\\\": {\\\"value\\\": \\\"certificates\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"ce89de35-28cf-4f8c-82a1-215539f77bad\",\"gridData\":{\"i\":\"ce89de35-28cf-4f8c-82a1-215539f77bad\",\"y\":69,\"x\":24,\"w\":24,\"h\":22}},{\"type\":\"search\",\"title\":\"Certificate Inventory Detail\",\"panelIndex\":\"3a5ae8e6-acd0-40f9-a6fb-488f44a55e32\",\"gridData\":{\"i\":\"3a5ae8e6-acd0-40f9-a6fb-488f44a55e32\",\"y\":91,\"x\":0,\"w\":48,\"h\":38},\"embeddableConfig\":{\"description\":\"Per-cert records sorted by earliest expiry. FILE=disk scan, PORT=live TLS. Paginated server-side — scales to any size.\",\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"grid\":{}},\"panelRefName\":\"panel_3a5ae8e6-acd0-40f9-a6fb-488f44a55e32\"}]", + "timeRestore": false, + "title": "[TYCHON Quantum Command] Certificate Operations Dashboard", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T17:19:39.902Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "managed": false, + "references": [ + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "187d7c49-96d6-43fe-a3d7-ee51f605e0f5:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:f676853f-014e-5857-89ba-97b22fb271af:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "3a8c4d30-8553-4034-91da-f7010ef7b182:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:4cb43ecb-be8e-5b80-8c8e-32e171de9e03:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "3fa6122b-517f-47d6-b194-2fcea3de3332:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:5e8c06e1-fcf5-5aab-b7bc-c3cdc891baee:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "48d7d98f-27df-4c04-a736-8e772da0b028:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:c9ef7c09-bbcf-57c7-bcbc-d3fae0140da2:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "65669cd8-396b-410c-bc9b-ee3389ef8017:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:195b2262-1d5d-50e1-86d2-f404cd493030:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "ce89de35-28cf-4f8c-82a1-215539f77bad:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d14a762a-33a5-545d-9c69-b36b1279da31:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:8de715c9-8769-51a8-8672-32a3af72a8c7:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "df2ef032-250b-40c9-93de-3f6211bddac5:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:5a19f6d5-01ea-5a0d-9469-870400433156:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + }, + { + "id": "tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail", + "name": "3a5ae8e6-acd0-40f9-a6fb-488f44a55e32:panel_3a5ae8e6-acd0-40f9-a6fb-488f44a55e32", + "type": "search" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.2.0", + "updated_at": "2026-06-11T17:19:39.902Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY2MTcsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/index_pattern/05179988-8b3d-4f26-9832-d83a1e769b2d.json b/packages/tychon_quantum_command/kibana/index_pattern/05179988-8b3d-4f26-9832-d83a1e769b2d.json new file mode 100644 index 00000000000..20a41e3ce71 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/index_pattern/05179988-8b3d-4f26-9832-d83a1e769b2d.json @@ -0,0 +1,25 @@ +{ + "attributes": { + "allowHidden": false, + "fieldAttrs": "{\"observer.hostname\":{\"count\":2},\"omb.vulnerability_status\":{\"count\":1},\"process.name\":{\"count\":1},\"tychon.crypto.protocol\":{\"count\":3},\"tychon.index\":{\"count\":18},\"host.hostname\":{\"count\":0},\"omb.crqc_vulnerable_algos\":{\"count\":0},\"omb.module_name\":{\"count\":0},\"omb.pqc_algos\":{\"count\":0},\"omb.software_package_name\":{\"count\":0},\"omb.symmetric_algos\":{\"count\":0},\"certificate.subject\":{\"count\":2},\"tychon.application.connected_to_count\":{\"count\":2},\"destination.ip\":{\"count\":1}}", + "fieldFormatMap": "{}", + "fields": "[]", + "name": "Quantum Resistant Inventory", + "runtimeFieldMap": "{}", + "sourceFilters": "[]", + "timeFieldName": "@timestamp", + "title": "tychon-pqc*" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "managed": false, + "originId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "references": [], + "type": "index-pattern", + "typeMigrationVersion": "8.0.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NjEsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/index_pattern/1dc9d581-4b38-4108-84e1-59a9fbcfbca5.json b/packages/tychon_quantum_command/kibana/index_pattern/1dc9d581-4b38-4108-84e1-59a9fbcfbca5.json new file mode 100644 index 00000000000..fdaeb7f7412 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/index_pattern/1dc9d581-4b38-4108-84e1-59a9fbcfbca5.json @@ -0,0 +1,25 @@ +{ + "attributes": { + "allowHidden": false, + "fieldAttrs": "{\"host.hostname\":{\"count\":1},\"omb.crqc_vulnerable_algos\":{\"count\":1},\"omb.module_name\":{\"count\":1},\"omb.pqc_algos\":{\"count\":2},\"omb.symmetric_algos\":{\"count\":1},\"omb.vulnerability_status\":{\"count\":2},\"omb.software_package_name\":{\"count\":1},\"omb.software_package_version\":{\"count\":1},\"omb.vendor\":{\"count\":1},\"omb.operating_system\":{\"count\":1},\"omb.additional_notes\":{\"count\":1},\"omb.kex_protocols\":{\"count\":1},\"tls.supported_ciphers\":{\"count\":1},\"tls.preferred_key_exchange\":{\"count\":1},\"omb.kex_secondary\":{\"count\":1},\"omb.kem_algorithms\":{\"count\":1},\"omb.kem_parameters\":{\"count\":1},\"omb.dsa_algorithms\":{\"count\":1},\"omb.dsa_parameters\":{\"count\":1},\"omb.dsa_hash_algorithms\":{\"count\":2},\"omb.block_cipher_key_lengths\":{\"count\":1},\"omb.block_cipher_modes\":{\"count\":1},\"crypto.hash_algorithms\":{\"count\":1},\"omb.hash_algorithm_parameters\":{\"count\":1},\"crypto.mac_algorithms\":{\"count\":1},\"omb.mac_algorithm_parameters\":{\"count\":1},\"omb.other_crypto_details\":{\"count\":1},\"omb.certifications\":{\"count\":1},\"cert_total_days\":{\"customLabel\":\"Total Validity\"},\"cert_days_remaining\":{\"customLabel\":\"Days Remaining\"}}", + "fieldFormatMap": "{\"cert_days_remaining\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"days\",\"outputFormat\":\"humanizePrecise\",\"outputPrecision\":1,\"includeSpaceWithSuffix\":true}},\"cert_total_days\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"days\",\"outputFormat\":\"humanizePrecise\",\"outputPrecision\":1,\"includeSpaceWithSuffix\":true}}}", + "fields": "[]", + "name": "Quantum Inventory Stats [TYCHON ACDI Direct]", + "runtimeFieldMap": "{\"cert_days_remaining\":{\"type\":\"long\",\"script\":{\"source\":\"long na=0L;if(doc[\\\"certificate.not_after\\\"].size()>0)na=doc[\\\"certificate.not_after\\\"].value.toInstant().toEpochMilli();else if(doc[\\\"x509.not_after\\\"].size()>0)na=doc[\\\"x509.not_after\\\"].value.toInstant().toEpochMilli();if(na==0L)return;emit((na-System.currentTimeMillis())/86400000L);\"}},\"cert_total_days\":{\"type\":\"long\",\"script\":{\"source\":\"long na=0L,nb=0L;if(doc[\\\"certificate.not_after\\\"].size()>0)na=doc[\\\"certificate.not_after\\\"].value.toInstant().toEpochMilli();else if(doc[\\\"x509.not_after\\\"].size()>0)na=doc[\\\"x509.not_after\\\"].value.toInstant().toEpochMilli();if(doc[\\\"certificate.not_before\\\"].size()>0)nb=doc[\\\"certificate.not_before\\\"].value.toInstant().toEpochMilli();else if(doc[\\\"x509.not_before\\\"].size()>0)nb=doc[\\\"x509.not_before\\\"].value.toInstant().toEpochMilli();if(na==0L||nb==0L)return;emit((na-nb)/86400000L);\"}}}", + "sourceFilters": "[]", + "timeFieldName": "@timestamp", + "title": "tychon-pqc-*" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "1dc9d581-4b38-4108-84e1-59a9fbcfbca5", + "managed": false, + "originId": "ca728b62-2968-45a5-b90b-32e2747056c0", + "references": [], + "type": "index-pattern", + "typeMigrationVersion": "8.0.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTgsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/index_pattern/852a2806-9a09-4c17-bcea-b54e7b69f3bc.json b/packages/tychon_quantum_command/kibana/index_pattern/852a2806-9a09-4c17-bcea-b54e7b69f3bc.json new file mode 100644 index 00000000000..0a52209f98b --- /dev/null +++ b/packages/tychon_quantum_command/kibana/index_pattern/852a2806-9a09-4c17-bcea-b54e7b69f3bc.json @@ -0,0 +1,25 @@ +{ + "attributes": { + "allowHidden": false, + "fieldAttrs": "{}", + "fieldFormatMap": "{}", + "fields": "[]", + "name": "Quantum Inventory", + "runtimeFieldMap": "{}", + "sourceFilters": "[]", + "timeFieldName": "@timestamp", + "title": "tychon-pqc-inventory*" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", + "managed": false, + "originId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "references": [], + "type": "index-pattern", + "typeMigrationVersion": "8.0.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NjMsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json new file mode 100644 index 00000000000..066caa03961 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json @@ -0,0 +1,81 @@ +{ + "attributes": { + "columns": [ + "observer.hostname", + "omb.vulnerability_status", + "omb.module_name", + "omb.crqc_vulnerable_algos", + "omb.pqc_algos", + "omb.symmetric_algos", + "omb.software_package_name", + "omb.software_package_version", + "omb.vendor", + "omb.operating_system", + "omb.additional_notes", + "omb.kex_protocols", + "tls.supported_ciphers", + "tls.preferred_key_exchange", + "omb.kex_secondary", + "omb.kem_algorithms", + "omb.kem_parameters", + "omb.dsa_algorithms", + "omb.dsa_parameters", + "omb.block_cipher_key_lengths", + "omb.block_cipher_modes", + "crypto.hash_algorithms", + "omb.hash_algorithm_parameters", + "crypto.mac_algorithms", + "omb.mac_algorithm_parameters", + "omb.other_crypto_details", + "omb.certifications", + "@timestamp" + ], + "description": "OMB Report for the Department of Defense", + "grid": { + "columns": { + "omb.additional_notes": { + "width": 241 + } + } + }, + "hideChart": false, + "isTextBasedQuery": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"exists\",\"key\":\"omb.vulnerability_status\",\"value\":\"exists\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"exists\":{\"field\":\"omb.vulnerability_status\"}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "timeRange": { + "from": "now-24h/h", + "to": "now" + }, + "timeRestore": true, + "title": "DoD OMB Report" + }, + "coreMigrationVersion": "8.8.0", + "id": "tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report", + "managed": false, + "originId": "662602a4-f820-4e80-9fe2-115c951fe43c", + "references": [ + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + } + ], + "type": "search", + "typeMigrationVersion": "10.5.0" +} diff --git a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json new file mode 100644 index 00000000000..66a8dbaa739 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json @@ -0,0 +1,46 @@ +{ + "attributes": { + "columns": [ + "observer.hostname", + "tychon.type", + "x509.subject.common_name", + "certificate.issuer_common_name", + "x509.issuer.common_name", + "omb.sig_tier", + "tychon.crypto.grade", + "cert_days_remaining", + "cert_total_days", + "certificate.not_after", + "x509.not_after", + "certificate.is_self_signed", + "file.path", + "server.ip", + "server.port" + ], + "description": "All certs — FILE (disk scan) and PORT (live TLS). Sorted by earliest expiry. Scales via server-side pagination.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\": true, \"version\": true, \"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": [], \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "cert_days_remaining", + "asc" + ] + ], + "title": "Certificate Inventory Detail", + "version": 1 + }, + "coreMigrationVersion": "8.8.0", + "id": "tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail", + "managed": false, + "originId": "d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001", + "references": [ + { + "id": "1dc9d581-4b38-4108-84e1-59a9fbcfbca5", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "search", + "typeMigrationVersion": "10.5.0" +} diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json new file mode 100644 index 00000000000..b14849564a5 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json @@ -0,0 +1,19 @@ +{ + "attributes": { + "color": "#E7664C", + "description": "PQC Scan Results", + "name": "ACDI" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "managed": false, + "originId": "6a127011-8fb1-4f28-afae-70d465f3f246", + "references": [], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY4NzMzOSwzMF0=" +} diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json new file mode 100644 index 00000000000..7abe599f47f --- /dev/null +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json @@ -0,0 +1,19 @@ +{ + "attributes": { + "color": "#B9A888", + "description": "Updated for the Quantum 2.0.3 schema", + "name": "2.0.3" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "managed": false, + "originId": "fbb71a48-1a00-4182-8614-cacc09fd24f4", + "references": [], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY4NzMzOCwzMF0=" +} diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json new file mode 100644 index 00000000000..0d9780245ba --- /dev/null +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json @@ -0,0 +1,19 @@ +{ + "attributes": { + "color": "#1140c2", + "description": "", + "name": "Quantum Resilient" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "managed": false, + "originId": "2a2cc491-f59c-4504-b146-049aa17a25f2", + "references": [], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY4NzM0MCwzMF0=" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json new file mode 100644 index 00000000000..5b180964592 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json @@ -0,0 +1,24 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "Application PQC Dashboard Risk", + "uiStateJSON": "{}", + "version": "1", + "visState": "{\"title\":\"Application PQC Dashboard Risk\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"totalApps\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"protoReady\\\", \\\"update\\\": \\\"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"protoPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"protoClr\\\", \\\"update\\\": \\\"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"barW\\\", \\\"update\\\": \\\"width * 0.62 - 18\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"proto_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"proto_pqc\\\", \\\"source\\\": \\\"proto_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"APPLICATION PQC DASHBOARD\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"signal\\\": \\\"'PQC COMPLIANCE PROGRESS \u2014 ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"KEX COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \u2014 PQC READY key exchange'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"PROTOCOL COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \u2014 TLS 1.3 capable'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * protoPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"protoPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 218},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 238},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 253},\\n \\\"text\\\": {\\\"signal\\\": \\\"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \u2014 PQC READY signature'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * sigPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 282},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d", + "managed": false, + "originId": "a80b900a-ad14-4973-ba14-6135a7657b22", + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NzEsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json new file mode 100644 index 00000000000..d138939bfae --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json @@ -0,0 +1,35 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "QuantumApplicationList", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"QuantumApplicationList\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Application filter list panel (multi-select) with dashboard filter integration.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"selectedApps\\\",\\n \\\"value\\\": \\\"|\\\",\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@appRowBg:click\\\",\\n \\\"update\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? replace(selectedApps, '|' + datum.app + '|', '|') : selectedApps + datum.app + '|'\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedAppsArray\\\",\\n \\\"update\\\": \\\"selectedApps == '|' ? [] : split(slice(selectedApps, 1, length(selectedApps)-1), '|')\\\"\\n },\\n {\\n \\\"name\\\": \\\"activeFilter\\\",\\n \\\"update\\\": \\\"length(selectedAppsArray) > 0 ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'terms': {'tychon.application.name': selectedAppsArray}}]}} : {'term': {'event.dataset': 'tychon.application'}}\\\"\\n },\\n {\\n \\\"name\\\": \\\"_applyAppFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@applyBtn:click\\\",\\n \\\"update\\\": \\\"kibanaAddFilter(activeFilter)\\\",\\n \\\"force\\\": true\\n }\\n ]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } },\\n \\\"aggs\\\": {\\n \\\"app_names\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"tychon.application.name\\\",\\n \\\"size\\\": 200,\\n \\\"order\\\": { \\\"_count\\\": \\\"desc\\\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.app_names.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"datum.doc_count\\\" },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"72 + (datum.rn - 1) * 26\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rn <= 15\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLICATION FILTER\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"applyBtn\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 92\\\" },\\n \\\"y\\\": { \\\"value\\\": 16 },\\n \\\"width\\\": { \\\"value\\\": 76 },\\n \\\"height\\\": { \\\"value\\\": 20 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#9fd7ff\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 54\\\" },\\n \\\"y\\\": { \\\"value\\\": 26 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLY\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#dff0ff\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"name\\\": \\\"appRowBg\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 18 },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y - 10\\\" },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 18\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"datum.y + 10\\\" },\\n \\\"cornerRadius\\\": { \\\"value\\\": 6 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#1f4d74' : '#0f1115'\\\" },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#9fd7ff' : '#253241'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 30 },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"app\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#e8f3ff' : '#c9d7e5'\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - 110\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 30\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(datum.count, ',')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#d9eeff' : '#8ea3b8'\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"right\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n }\\n ]\\n}\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e", + "managed": false, + "originId": "4caff337-23d1-4e48-b924-e2fe546c1b8c", + "references": [ + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", + "type": "tag" + } + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NjksMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json new file mode 100644 index 00000000000..a544b64d5b1 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json @@ -0,0 +1,23 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "CERT OPS \u2014 Key Algorithm", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\": \"CERT OPS \\u2014 Key Algorithm\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_algo\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.algorithm\\\", \\\"size\\\": 10}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_algo.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"palette\\\",\\n \\\"values\\\": [\\n {\\\"k\\\": \\\"RSA\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"lbl\\\": \\\"RSA\\\", \\\"desc\\\": \\\"Rivest\\u2013Shamir\\u2013Adleman \\u2014 quantum-vulnerable via Shor's algorithm\\\"},\\n {\\\"k\\\": \\\"ECDSA\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"lbl\\\": \\\"ECDSA\\\", \\\"desc\\\": \\\"Elliptic curve \\u2014 quantum-vulnerable, efficient on classical hardware\\\"},\\n {\\\"k\\\": \\\"DSA\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"lbl\\\": \\\"DSA\\\", \\\"desc\\\": \\\"Digital Signature Algorithm \\u2014 deprecated, should not be in new certs\\\"},\\n {\\\"k\\\": \\\"unknown_der\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown DER\\\", \\\"desc\\\": \\\"DER-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"unknown_pem\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown PEM\\\", \\\"desc\\\": \\\"PEM-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"ML-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"ML-DSA\\\", \\\"desc\\\": \\\"Lattice-based PQC signature \\u2014 CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"SLH-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"SLH-DSA\\\", \\\"desc\\\": \\\"Hash-based PQC signature \\u2014 CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"FN-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"FN-DSA\\\", \\\"desc\\\": \\\"Falcon lattice signature \\u2014 CNSA 2.0 quantum-resistant\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"palette\\\", \\\"key\\\": \\\"k\\\", \\\"fields\\\": [\\\"k\\\"],\\n \\\"values\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"], \\\"as\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"],\\n \\\"default\\\": \\\"#78909c\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.clr || '#78909c'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.bg || '#78909c18'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"lbl\\\", \\\"expr\\\": \\\"datum.lbl || datum.k\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\", \\\"expr\\\": \\\"datum.desc || 'Unrecognized key algorithm'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bw\\\", \\\"expr\\\": \\\"width * 0.58 - 110\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"rows\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"PUBLIC KEY TYPE \\u2014 click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161622' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.4\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 10}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '88'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTMsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json new file mode 100644 index 00000000000..b04bd3bbd95 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json @@ -0,0 +1,23 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "CERT OPS \u2014 Inventory Header", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\": \"CERT OPS \\u2014 Inventory Header\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"total\\\", \\\"update\\\": \\\"length(data('d_total'))>0 ? data('d_total')[0].n : 0\\\"}, {\\\"name\\\": \\\"expired\\\", \\\"update\\\": \\\"length(data('d_expired'))>0 ? data('d_expired')[0].n : 0\\\"}, {\\\"name\\\": \\\"exp30\\\", \\\"update\\\": \\\"length(data('d_exp30'))>0 ? data('d_exp30')[0].n : 0\\\"}, {\\\"name\\\": \\\"self\\\", \\\"update\\\": \\\"length(data('d_self'))>0 ? data('d_self')[0].n : 0\\\"}, {\\\"name\\\": \\\"legacy\\\", \\\"update\\\": \\\"length(data('d_legacy'))>0 ? data('d_legacy')[0].n : 0\\\"}, {\\\"name\\\": \\\"pqcvuln\\\", \\\"update\\\": \\\"length(data('d_pqcvuln'))>0 ? data('d_pqcvuln')[0].n : 0\\\"}, {\\\"name\\\": \\\"bw\\\", \\\"update\\\": \\\"floor((width - 10) / 6) - 4\\\"}, {\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? null : datum.k) : sel\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_total\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"d_expired\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_exp30\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_self\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_legacy\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_pqcvuln\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tiles\\\", \\\"values\\\": [{\\\"k\\\": \\\"TOTAL\\\", \\\"ord\\\": 0, \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"sig\\\": \\\"total\\\", \\\"filt\\\": null}, {\\\"k\\\": \\\"EXPIRED\\\", \\\"ord\\\": 1, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"ord\\\": 2, \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"sig\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"ord\\\": 3, \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"sig\\\": \\\"self\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"LEGACY\\\", \\\"ord\\\": 4, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"legacy\\\", \\\"filt\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}, {\\\"k\\\": \\\"PQC VULN\\\", \\\"ord\\\": 5, \\\"clr\\\": \\\"#ab47bc\\\", \\\"bg\\\": \\\"#ab47bc18\\\", \\\"sig\\\": \\\"pqcvuln\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"x\\\", \\\"expr\\\": \\\"datum.ord * (bw + 4) + 8\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"val\\\", \\\"expr\\\": \\\"datum.sig === 'total' ? total : datum.sig === 'expired' ? expired : datum.sig === 'exp30' ? exp30 : datum.sig === 'self' ? self : datum.sig === 'legacy' ? legacy : pqcvuln\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE INVENTORY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL OVERVIEW \\\\u2014 click a tile to filter the dashboard\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"tile\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"field\\\": \\\"x\\\"}, \\\"y\\\": {\\\"value\\\": 52}, \\\"width\\\": {\\\"signal\\\": \\\"bw\\\"}, \\\"height\\\": {\\\"value\\\": 72}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.bg : '#161616'\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 && datum.filt ? '#2a2a3a' : '#222222')\\\"}, \\\"strokeWidth\\\": {\\\"signal\\\": \\\"datum.k === sel ? 2 : 1\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 88}, \\\"text\\\": {\\\"signal\\\": \\\"datum.val >= 1000 ? format(datum.val,'.3~s') : format(datum.val,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 ? datum.clr : '#3a3a3a')\\\"}, \\\"fontSize\\\": {\\\"value\\\": 22}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 108}, \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : '#666666'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}]}\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NDksMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json new file mode 100644 index 00000000000..611fa6084a9 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json @@ -0,0 +1,23 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "CERT OPS \u2014 Top Issuing CAs", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\": \"CERT OPS \\u2014 Top Issuing CAs\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.issuer_organization': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.issuer_organization': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_issuer\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.issuer_organization\\\", \\\"size\\\": 10, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_issuer.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 52 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.rnk === 1 ? '#448aff' : datum.rnk === 2 ? '#4db6ac' : datum.rnk <= 5 ? '#546e7a' : '#37474f'\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"TOP ISSUING CAs\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE AUTHORITY \\u2014 who issued your certificates \\u00b7 click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 30}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.rnk, 'd') + '.'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.62\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.62) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 5}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '66'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 45\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#888888'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTIsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json new file mode 100644 index 00000000000..3c19412ac59 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json @@ -0,0 +1,35 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "Connections Selection Details", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Connections Selection Details\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection details panel for host/application context using dashboard filters.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"panelW\\\", \\\"update\\\": \\\"width - 20\\\" },\\n { \\\"name\\\": \\\"labelX\\\", \\\"value\\\": 26 },\\n { \\\"name\\\": \\\"valueX\\\", \\\"update\\\": \\\"width * 0.42\\\" },\\n { \\\"name\\\": \\\"row0\\\", \\\"value\\\": 74 },\\n { \\\"name\\\": \\\"rowH\\\", \\\"value\\\": 24 }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"context\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"host\\\": { \\\"terms\\\": { \\\"field\\\": \\\"observer.hostname\\\", \\\"size\\\": 1 } },\\n \\\"app\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name.keyword\\\", \\\"size\\\": 1 } },\\n \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"server.address\\\", \\\"size\\\": 1 } },\\n \\\"proto\\\": { \\\"terms\\\": { \\\"field\\\": \\\"network.protocol\\\", \\\"size\\\": 1 } },\\n \\\"tls_ver\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_protocol\\\", \\\"size\\\": 1 } },\\n \\\"cipher\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_cipher\\\", \\\"size\\\": 1 } },\\n \\\"events\\\": { \\\"value_count\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"first_seen\\\": { \\\"min\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"last_seen\\\": { \\\"max\\\": { \\\"field\\\": \\\"@timestamp\\\" } }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"host\\\",\\n \\\"expr\\\": \\\"datum.host && datum.host.buckets && length(datum.host.buckets)>0 ? datum.host.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app\\\",\\n \\\"expr\\\": \\\"datum.app && datum.app.buckets && length(datum.app.buckets)>0 ? datum.app.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"dst\\\",\\n \\\"expr\\\": \\\"datum.dst && datum.dst.buckets && length(datum.dst.buckets)>0 ? datum.dst.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"proto\\\",\\n \\\"expr\\\": \\\"datum.proto && datum.proto.buckets && length(datum.proto.buckets)>0 ? datum.proto.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tlsVer\\\",\\n \\\"expr\\\": \\\"datum.tls_ver && datum.tls_ver.buckets && length(datum.tls_ver.buckets)>0 ? datum.tls_ver.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"cipher\\\",\\n \\\"expr\\\": \\\"datum.cipher && datum.cipher.buckets && length(datum.cipher.buckets)>0 ? datum.cipher.buckets[0].key : ''\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"events\\\", \\\"expr\\\": \\\"datum.events ? datum.events.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"firstSeen\\\",\\n \\\"expr\\\": \\\"datum.first_seen && isValid(datum.first_seen.value_as_string) ? datum.first_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"lastSeen\\\",\\n \\\"expr\\\": \\\"datum.last_seen && isValid(datum.last_seen.value_as_string) ? datum.last_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionType\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? 'APPLICATION CONTEXT' : (datum.host != '' ? 'HOST CONTEXT' : 'NO SELECTION')\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionId\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? datum.app : (datum.host != '' ? datum.host : 'Select a host/app in the graph')\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"context\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"project\\\",\\n \\\"fields\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ],\\n \\\"as\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ]\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"kv\\\",\\n \\\"expr\\\": \\\"[{k:'Context',v:datum.selectionType},{k:'Selection',v:datum.selectionId},{k:'Source Host',v:datum.host},{k:'Application',v:datum.app},{k:'Destination',v:datum.dst},{k:'Protocol',v:datum.proto},{k:'TLS Version',v:datum.tlsVer},{k:'Cipher',v:datum.cipher},{k:'Event Count',v:format(datum.events, ',')},{k:'First Seen',v:datum.firstSeen},{k:'Last Seen',v:datum.lastSeen}]\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"kv\\\"], \\\"as\\\": [\\\"row\\\"] },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"row0 + (datum.rn - 1) * rowH\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"SELECTION DETAILS\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX - 10\\\" },\\n \\\"y\\\": { \\\"value\\\": 54 },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 20\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#1f2a36\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"labelX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.k\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#9fc4e0\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.v == '' ? '\u2014' : datum.row.v\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8eef5\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - valueX - 18\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975", + "managed": false, + "originId": "d5510112-05fd-47b6-8930-fe26306b50ce", + "references": [ + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", + "type": "tag" + } + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NjcsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json new file mode 100644 index 00000000000..b3c8e88a724 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json @@ -0,0 +1,23 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "CERT OPS \u2014 Quantum Tier", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\": \"CERT OPS \\u2014 Quantum Tier\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 10}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tc\\\", \\\"source\\\": \\\"raw\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"]}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"tc\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature \\\\u2014 quantum-resistant, CNSA 2.0 approved\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0}, {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve \\\\u2014 quantum-vulnerable via Shor's algorithm, must be replaced pre-2035\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1}, {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA \\\\u2014 quantum-vulnerable via Shor's algorithm, harvest-now-decrypt-later risk today\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}, {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"SHA-1/MD5 hash \\\\u2014 classically broken and quantum-vulnerable, replace immediately\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#b71c1c\\\", \\\"bg\\\": \\\"#b71c1c22\\\", \\\"ord\\\": 3}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM \\\\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 55}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.5\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"}, \\\"height\\\": {\\\"value\\\": 6}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}}}}]}\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTAsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json new file mode 100644 index 00000000000..8a07af7eecd --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json @@ -0,0 +1,35 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "QuantumRiskRadial", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"QuantumRiskRadial\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection risk dial aligned to inventory OMB readiness tiers.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"cx\\\", \\\"update\\\": \\\"width/2\\\" },\\n { \\\"name\\\": \\\"cy\\\", \\\"update\\\": \\\"height*0.56\\\" },\\n { \\\"name\\\": \\\"r\\\", \\\"update\\\": \\\"min(width, height) * 0.34\\\" }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"risk\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"apps_total\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } },\\n \\\"kex_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.kex_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"proto_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"sig_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.sig_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"isValid(datum.apps_total) && isValid(datum.apps_total.value) ? max(1, datum.apps_total.value) : 1\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"kex_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.kex_ready) && isValid(datum.kex_ready.u) && isValid(datum.kex_ready.u.value) ? datum.kex_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"proto_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.proto_ready) && isValid(datum.proto_ready.u) && isValid(datum.proto_ready.u.value) ? datum.proto_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sig_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.sig_ready) && isValid(datum.sig_ready.u) && isValid(datum.sig_ready.u.value) ? datum.sig_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_kex_ready\\\", \\\"expr\\\": \\\"100 * datum.kex_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_proto_ready\\\", \\\"expr\\\": \\\"100 * datum.proto_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_sig_ready\\\", \\\"expr\\\": \\\"100 * datum.sig_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"readiness\\\", \\\"expr\\\": \\\"clamp(round((datum.p_kex_ready + datum.p_proto_ready + datum.p_sig_ready) / 3), 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"score\\\", \\\"expr\\\": \\\"clamp(100 - datum.readiness, 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? 'LOW' : datum.readiness >= 60 ? 'MEDIUM' : 'HIGH'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"color\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? '#22c55e' : datum.readiness >= 60 ? '#f59e0b' : '#ef4444'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"angle\\\", \\\"expr\\\": \\\"-3.1415926 + (datum.score/100) * 3.1415926 * 2\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"value\\\": 3.1415926},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1f2937\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"field\\\": \\\"angle\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy - 6\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.score, 'd') + '/100'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 28}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + 24\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.tier + ' RISK'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cfe3f7\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4", + "managed": false, + "originId": "dfb8a02d-f29b-48d9-8ed9-c997d0f0bfe2", + "references": [ + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", + "type": "tag" + } + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NzAsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json new file mode 100644 index 00000000000..ca67b0a5386 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json @@ -0,0 +1,22 @@ +{ + "attributes": { + "description": "Certificate lifetime buckets: automated (\u226490d) through legacy (>5yr) with key management system insight", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": []}" + }, + "title": "Certificate Longevity", + "uiStateJSON": "{}", + "visState": "{\"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"le90d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();if(na<=System.currentTimeMillis())return false;long d=(na-nb)/86400000L;return d>=0&&d<=90;\\\"}}}}, \\\"le1yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>90&&d<=365;\\\"}}}}, \\\"le825d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>365&&d<=825;\\\"}}}}, \\\"le5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>825&&d<=1825;\\\"}}}}, \\\"gt5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>1825;\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le90d\\\", \\\"expr\\\": \\\"datum.le90d ? datum.le90d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le1yr\\\", \\\"expr\\\": \\\"datum.le1yr ? datum.le1yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le825d\\\", \\\"expr\\\": \\\"datum.le825d ? datum.le825d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le5yr\\\", \\\"expr\\\": \\\"datum.le5yr ? datum.le5yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"gt5yr\\\", \\\"expr\\\": \\\"datum.gt5yr ? datum.gt5yr.doc_count : 0\\\"}]}, {\\\"name\\\": \\\"tot\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"le90d\\\", \\\"lbl\\\": \\\"Automated \\\\u226490 days\\\", \\\"mgmt\\\": \\\"KEY MGT SYSTEM\\\", \\\"desc\\\": \\\"Almost certainly managed by ACME / Let's Encrypt / cert-manager \\\\u2014 short lifetime is a signature of automated issuance\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"le90d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gte\\\": 0, \\\"lte\\\": 90}}}}, {\\\"k\\\": \\\"le1yr\\\", \\\"lbl\\\": \\\"Short-lived \\\\u22641 year\\\", \\\"mgmt\\\": \\\"LIKELY MANAGED\\\", \\\"desc\\\": \\\"Annual lifetime pattern \\\\u2014 may be automated renewal or disciplined manual rotation by an ops team\\\", \\\"clr\\\": \\\"#4db6ac\\\", \\\"bg\\\": \\\"#4db6ac18\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"le1yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 90, \\\"lte\\\": 365}}}}, {\\\"k\\\": \\\"le825d\\\", \\\"lbl\\\": \\\"Modern \\\\u2264825 days\\\", \\\"mgmt\\\": \\\"CA ISSUED\\\", \\\"desc\\\": \\\"Within Apple / browser maximum trust limit (825 days) \\\\u2014 actively issued by a real CA, rotation expected\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"le825d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 365, \\\"lte\\\": 825}}}}, {\\\"k\\\": \\\"le5yr\\\", \\\"lbl\\\": \\\"Long-lived \\\\u22645 years\\\", \\\"mgmt\\\": \\\"MANUAL\\\", \\\"desc\\\": \\\"826\\\\u20131825 day lifetime \\\\u2014 manually managed, no automated rotation, quantum risk grows over the certificate's life\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"le5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 825, \\\"lte\\\": 1825}}}}, {\\\"k\\\": \\\"gt5yr\\\", \\\"lbl\\\": \\\"Legacy > 5 years\\\", \\\"mgmt\\\": \\\"LEGACY / MANUAL\\\", \\\"desc\\\": \\\"5+ year validity \\\\u2014 definitely manually issued; each year of remaining life increases the window for harvest-now-decrypt-later attacks\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"gt5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 1825}}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? (datum.field==='le90d' ? data('raw')[0].le90d : datum.field==='le1yr' ? data('raw')[0].le1yr : datum.field==='le825d' ? data('raw')[0].le825d : datum.field==='le5yr' ? data('raw')[0].le5yr : data('raw')[0].gt5yr) : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 52\\\"}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"rows\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LONGEVITY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LIFETIME \\\\u2014 short = automated key management \\\\u00b7 long = manual / legacy\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161616' : '#121212'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.52\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 42\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.74\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76 + 41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"mgmt\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 28\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 82 : 0\\\"}, \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '44'\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 52\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 && datum.n > 0 ? format(datum.pct * 100, '.1f') + '%' : ''\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTYsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json new file mode 100644 index 00000000000..d325a41f23f --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json @@ -0,0 +1,23 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": []}" + }, + "title": "Certificate Hygiene", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"expired\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, \\\"exp30\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, \\\"exp90\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, \\\"selfsign\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, \\\"weakkey\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}, \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"expired\\\", \\\"expr\\\": \\\"datum.expired ? datum.expired.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp30\\\", \\\"expr\\\": \\\"datum.exp30 ? datum.exp30.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp90\\\", \\\"expr\\\": \\\"datum.exp90 ? datum.exp90.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"selfsign\\\", \\\"expr\\\": \\\"datum.selfsign ? datum.selfsign.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"weakkey\\\", \\\"expr\\\": \\\"datum.weakkey ? datum.weakkey.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total\\\", \\\"expr\\\": \\\"datum.total ? datum.total.value : 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"EXPIRED\\\", \\\"lbl\\\": \\\"Expired\\\", \\\"desc\\\": \\\"certificate.not_after < now \\\\u2014 no longer trusted by any client\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"lbl\\\": \\\"Expiring in 30 days\\\", \\\"desc\\\": \\\"certificate.not_after within 30 days \\\\u2014 immediate renewal required\\\", \\\"sev\\\": \\\"high\\\", \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"EXP 90D\\\", \\\"lbl\\\": \\\"Expiring in 90 days\\\", \\\"desc\\\": \\\"certificate.not_after within 90 days \\\\u2014 plan renewal now\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"exp90\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"lbl\\\": \\\"Self-Signed\\\", \\\"desc\\\": \\\"certificate.is_self_signed = true \\\\u2014 no CA trust chain, browser errors\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"selfsign\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"WEAK KEY\\\", \\\"lbl\\\": \\\"Weak Key \\\\u22641024-bit\\\", \\\"desc\\\": \\\"RSA/DSA key \\\\u22641024 bits \\\\u2014 computationally breakable, must be replaced\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"weakkey\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"raw\\\", \\\"key\\\": \\\"total\\\", \\\"fields\\\": [\\\"ord\\\"], \\\"values\\\": [\\\"expired\\\", \\\"exp30\\\", \\\"exp90\\\", \\\"selfsign\\\", \\\"weakkey\\\", \\\"total\\\"], \\\"as\\\": [\\\"v_expired\\\", \\\"v_exp30\\\", \\\"v_exp90\\\", \\\"v_selfsign\\\", \\\"v_weakkey\\\", \\\"v_total\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.field==='expired' ? (length(data('raw'))>0?data('raw')[0].expired:0) : datum.field==='exp30' ? (length(data('raw'))>0?data('raw')[0].exp30:0) : datum.field==='exp90' ? (length(data('raw'))>0?data('raw')[0].exp90:0) : datum.field==='selfsign' ? (length(data('raw'))>0?data('raw')[0].selfsign:0) : (length(data('raw'))>0?data('raw')[0].weakkey:0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? data('raw')[0].total : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 68 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE HYGIENE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL ISSUES \\\\u2014 expiry \\\\u00b7 trust \\\\u00b7 key strength\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? datum.bg : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 61\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sev\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 29\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 14}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#333333' : '#222222'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 ? format(datum.pct * 100, '.1f') + '%' : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTEsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json new file mode 100644 index 00000000000..420b10fe0d0 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json @@ -0,0 +1,22 @@ +{ + "attributes": { + "description": "File system disk scan vs live TLS port capture \u2014 how each certificate was discovered", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": []}" + }, + "title": "Certificate Source Type", + "uiStateJSON": "{}", + "visState": "{\"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_fs\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"term\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"d_port\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-inventory*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"bool\\\": {\\\"must\\\": [{\\\"exists\\\": {\\\"field\\\": \\\"x509.subject.common_name\\\"}}, {\\\"term\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}]}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"fs\\\", \\\"ord\\\": 0, \\\"lbl\\\": \\\"File System\\\", \\\"badge\\\": \\\"DISK\\\", \\\"sub\\\": \\\"Certificates read from disk \\\\u2014 PEM/DER files, keystores, application bundles\\\", \\\"desc\\\": \\\"Found by crawling the local filesystem. Source path is known. These certs may not be actively serving traffic \\\\u2014 they could be backups, bundled CA roots, or application trust stores.\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"icon\\\": \\\"\\\\u2399\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}}, {\\\"k\\\": \\\"port\\\", \\\"ord\\\": 1, \\\"lbl\\\": \\\"Port / Network\\\", \\\"badge\\\": \\\"NETWORK\\\", \\\"sub\\\": \\\"Certificates captured live from TLS handshakes on open network ports\\\", \\\"desc\\\": \\\"Captured during an active TLS scan. These certs are definitely in use serving live traffic. Quantum readiness score and cipher suite are also available for these entries.\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"icon\\\": \\\"\\\\u26a1\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.k === 'fs' ? (length(data('d_fs'))>0 ? data('d_fs')[0].n : 0) : (length(data('d_port'))>0 ? data('d_port')[0].n : 0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 134 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SOURCE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES WERE DISCOVERED \\\\u2014 file scan vs live TLS capture\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"row_bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? '#1c1c2e' : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 127\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 10\\\"}, \\\"width\\\": {\\\"value\\\": 56}, \\\"height\\\": {\\\"value\\\": 18}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 42}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 23\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 78}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sub\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.82\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 64\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.64\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 70\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n, '.3~s') : format(datum.n, ',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 32}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 88\\\"}, \\\"text\\\": {\\\"value\\\": \\\"certificates\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTcsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json new file mode 100644 index 00000000000..699c263f9c2 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json @@ -0,0 +1,24 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" + }, + "title": "PQC Connections Topology", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"PQC Connections Topology\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 8,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"zoom\\\",\\n \\\"value\\\": 0.55,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6)\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panX\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panX - (width/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (width/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panX + event.movementX\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panY\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panY - (height/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (height/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panY + event.movementY\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedNode\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:click\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? (selectedNode && selectedNode.id===datum.id ? null : datum) : selectedNode\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"_applyNodeFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:dblclick\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? kibanaAddFilter((datum.nodeType === 'application' ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'tychon.application.name': toString(datum.id)}}]}} : {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'host.hostname': toString(datum.id)}}]}})) : 0\\\",\\n \\\"force\\\": true\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjPeerIds\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency')) ? pluck(data('adjacency'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"adjPeer2Ids\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency2')) ? pluck(data('adjacency2'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"highlightNodeIdsCsv\\\",\\n \\\"update\\\": \\\"selectedNode ? (',' + toString(selectedNode.id) + ',' + join(adjPeerIds, ',') + ',' + join(adjPeer2Ids, ',') + ',') : ''\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanX\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cx) ? (width * 0.5) - (data('layout_center')[0].cx * zoom) : (width * (1 - zoom) * 0.5)\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanY\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cy) ? (height * 0.52) - (data('layout_center')[0].cy * zoom) : (height * (1 - zoom) * 0.5)\\\"\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"pairs\\\": {\\n \\\"filter\\\": {\\n \\\"bool\\\": {\\n \\\"must\\\": [\\n { \\\"exists\\\": { \\\"field\\\": \\\"host.hostname\\\" } },\\n { \\\"exists\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } },\\n { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } }\\n ]\\n }\\n },\\n \\\"aggs\\\": {\\n \\\"links\\\": {\\n \\\"composite\\\": {\\n \\\"size\\\": 500,\\n \\\"sources\\\": [\\n { \\\"src\\\": { \\\"terms\\\": { \\\"field\\\": \\\"host.hostname\\\" } } },\\n { \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } } }\\n ]\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.pairs.links.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"datum.key.src\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"datum.key.dst\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.doc_count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.target) && datum.source!='' && datum.target!=''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"nodes\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"source\\\", \\\"target\\\"], \\\"as\\\": [\\\"side\\\", \\\"id\\\"] },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"id\\\", \\\"side\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"nodeType\\\", \\\"expr\\\": \\\"datum.side==='source' ? 'host' : 'application'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.source != '' && datum.target != ''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout\\\",\\n \\\"source\\\": \\\"nodes\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"force\\\",\\n \\\"iterations\\\": 300,\\n \\\"static\\\": true,\\n \\\"forces\\\": [\\n { \\\"force\\\": \\\"center\\\", \\\"x\\\": { \\\"signal\\\": \\\"width * 0.5\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"height * 0.52\\\" } },\\n { \\\"force\\\": \\\"collide\\\", \\\"radius\\\": 20 },\\n { \\\"force\\\": \\\"nbody\\\", \\\"strength\\\": -180 },\\n { \\\"force\\\": \\\"link\\\", \\\"links\\\": \\\"edges\\\", \\\"id\\\": \\\"id\\\", \\\"distance\\\": 130 }\\n ]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout_center\\\",\\n \\\"source\\\": \\\"layout\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"ops\\\": [\\\"median\\\", \\\"median\\\"],\\n \\\"fields\\\": [\\\"x\\\", \\\"y\\\"],\\n \\\"as\\\": [\\\"cx\\\", \\\"cy\\\"]\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cx\\\", \\\"expr\\\": \\\"isFinite(datum.cx) ? datum.cx : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cy\\\", \\\"expr\\\": \\\"isFinite(datum.cy) ? datum.cy : 0\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges_draw\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sx\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.x) ? datum.source.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sy\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.y) ? datum.source.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tx\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.x) ? datum.target.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"ty\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.y) ? datum.target.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.sx) && isValid(datum.sy) && isValid(datum.tx) && isValid(datum.ty)\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (datum.srcId===toString(selectedNode.id) || datum.dstId===toString(selectedNode.id))\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id)\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency2\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (indexof(adjPeerIds, datum.srcId) >= 0 || indexof(adjPeerIds, datum.dstId) >= 0)\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id) && indexof(adjPeerIds, datum.peer) < 0\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"edges_draw\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"field\\\": \\\"sx\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"sy\\\" },\\n \\\"x2\\\": { \\\"field\\\": \\\"tx\\\" },\\n \\\"y2\\\": { \\\"field\\\": \\\"ty\\\" },\\n \\\"stroke\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? '#4fc3f7' : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? '#7fe8ff' : '#213240')\\\"\\n },\\n \\\"strokeOpacity\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? 0.42 : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? 0.75 : 0.08)\\\"\\n },\\n \\\"strokeWidth\\\": { \\\"value\\\": 0.9 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#3b2b1a' : '#1a2c3b'\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.9 },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#ffd7a2' : '#a9dbff'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"opacity\\\": { \\\"signal\\\": \\\"!selectedNode ? 1 : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? 1 : 0.2)\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"name\\\": \\\"nodeMark\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"strokeOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n },\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY - 14\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"id\\\" },\\n \\\"fill\\\": { \\\"signal\\\": \\\"!selectedNode ? '#e0e0e0' : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? '#f2f7ff' : '#4f5f6f')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"bottom\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c", + "managed": false, + "originId": "d12466b5-c1c4-4c03-bd17-295d26285885", + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NjgsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json new file mode 100644 index 00000000000..183fb0f6364 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json @@ -0,0 +1,23 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "CERT OPS \u2014 Signature Algorithm", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\": \"CERT OPS \\u2014 Signature Algorithm\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_sig\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.signature_algorithm\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_sig.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef5350' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef5350' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa726' : datum.key === 'N/A' || datum.key === '0' ? '#555555' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef535018' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef535018' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff18' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa72618' : '#55555518'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'BROKEN' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? 'LEGACY' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? 'MODERN' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? 'CLASSICAL' : datum.key === 'N/A' || datum.key === '0' ? 'UNKNOWN' : 'PQC READY'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'MD5 collision attacks are trivial \\u2014 critically broken' : datum.key === 'SHA1-RSA' ? 'SHA-1 deprecated \\u2014 browsers reject, fails compliance' : datum.key === 'DSA-SHA1' ? 'DSA with SHA-1 \\u2014 both deprecated, remove immediately' : datum.key === 'SHA256-RSA' ? 'RSA with SHA-256 \\u2014 dominant classical standard' : datum.key === 'SHA384-RSA' ? 'RSA with SHA-384 \\u2014 stronger hash, still quantum-vulnerable' : datum.key === 'SHA512-RSA' ? 'RSA with SHA-512 \\u2014 strongest classical RSA variant' : datum.key === 'ECDSA-SHA256' ? 'ECDSA with SHA-256 \\u2014 modern, efficient, quantum-vulnerable' : datum.key === 'ECDSA-SHA384' ? 'ECDSA with SHA-384 \\u2014 CNSA 1.0 approved, quantum-vulnerable' : 'Signature algorithm'\\\"},\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.k !== 'N/A' && datum.k !== '0'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 66 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES ARE SIGNED \\u2014 click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 59\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.42\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 6\\\"},\\n \\\"width\\\": {\\\"value\\\": 68}, \\\"height\\\": {\\\"value\\\": 15}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60 + 34\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 18\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 32\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 47\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTUsMzBd" +} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json new file mode 100644 index 00000000000..5cc4134b682 --- /dev/null +++ b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json @@ -0,0 +1,23 @@ +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "CERT OPS \u2014 Key Size Distribution", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\": \"CERT OPS \\u2014 Key Size Distribution\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_size\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.bit_size\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_size.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sz\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"toString(datum.key) + '-bit'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef5350' : datum.key <= 2048 ? '#ffa726' : datum.key <= 3072 ? '#448aff' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef535018' : datum.key <= 2048 ? '#ffa72618' : datum.key <= 3072 ? '#448aff18' : '#00c85318'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'CRITICAL' : datum.key <= 1024 ? 'WEAK' : datum.key <= 2048 ? 'CLASSICAL' : datum.key <= 3072 ? 'STRONG' : 'CNSA 2.0'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'Trivially breakable \\u2014 remove immediately' : datum.key <= 1024 ? 'Below NIST minimum \\u2014 must be replaced' : datum.key === 2048 ? 'RSA-2048 / ECDSA-P256 \\u2014 classical standard, quantum-vulnerable' : datum.key === 3072 ? 'RSA-3072 \\u2014 transitional strength, quantum-vulnerable' : datum.key === 4096 ? 'RSA-4096 \\u2014 strong classical, quantum-vulnerable' : datum.key === 256 ? 'ECDSA-P256 \\u2014 modern elliptic curve' : datum.key === 384 ? 'ECDSA-P384 \\u2014 strong elliptic curve (CNSA 1.0)' : 'Key size ' + datum.key\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY SIZE DISTRIBUTION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"BIT STRENGTH \\u2014 click to filter \\u00b7 CNSA 2.0 requires RSA \\u22653072 or ECDSA P-384\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"},\\n \\\"width\\\": {\\\"value\\\": 64}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58 + 32\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 27\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 64 : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 12}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-06-11T16:06:12.868Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130", + "managed": false, + "references": [], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2026-06-11T16:06:12.868Z", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "version": "WzY1NTQsMzBd" +} diff --git a/packages/tychon_quantum_command/manifest.yml b/packages/tychon_quantum_command/manifest.yml new file mode 100644 index 00000000000..f156ef41006 --- /dev/null +++ b/packages/tychon_quantum_command/manifest.yml @@ -0,0 +1,55 @@ +format_version: 2.0.0 +name: tychon_quantum_command +title: "TYCHON Quantum Command" +version: 2.0.4 +source: + license: "Elastic-2.0" +description: "Fleet integration for Tychon Quantum Command output." +type: integration +categories: + - security + - os_system +conditions: + kibana.version: "^8.11.0" + elastic.subscription: "basic" +screenshots: + - src: /img/TQC_Inventory.png + title: TYCHON Quantum Command - Inventory + size: 3434x1086 + type: image/png + - src: /img/TQC_Application_Report.png + title: TYCHON Quantum Command - Application Report + size: 3437x1072 + type: image/png + - src: /img/TQC_Application_Detail.png + title: TYCHON Quantum Command - Application Detail + size: 3435x1086 + type: image/png + - src: /img/TQC_Certificate_Report.png + title: TYCHON Quantum Command - Certificate Report + size: 3437x1083 + type: image/png + - src: /img/TQC_Application_Connections_Topology.png + title: TYCHON Quantum Command - Application Connections Topology + size: 3435x1082 + type: image/png + - src: /img/TQC_Cost_Analysis.png + title: TYCHON Quantum Command - Cost Analysis + size: 3438x1082 + type: image/png +icons: + - src: /img/TychonLogo.svg + title: TYCHON + size: 32x32 + type: image/svg+xml +policy_templates: + - name: tychon_quantum_command + title: Tychon Quantum Command + description: Collect TQC output files. + inputs: + - type: filestream + title: Collect TQC output + description: Collect NDJSON or JSON files generated by TQC. +owner: + github: tychonllc + type: partner diff --git a/packages/tychon_quantum_command/sample_event.json b/packages/tychon_quantum_command/sample_event.json new file mode 100644 index 00000000000..477c749dbeb --- /dev/null +++ b/packages/tychon_quantum_command/sample_event.json @@ -0,0 +1,37 @@ +{ + "@timestamp": "2026-06-11T12:00:00Z", + "event": { + "kind": "event", + "category": ["configuration"], + "dataset": "tychon_quantum_command.tychon_pqc" + }, + "data_stream": { + "type": "logs", + "dataset": "tychon_quantum_command.tychon_pqc", + "namespace": "default" + }, + "ecs": { + "version": "8.17.0" + }, + "host": { + "hostname": "server01" + }, + "tychon": { + "index": "applications", + "asset_type": "application", + "scan_mode": "quantum_command", + "pqc_readiness": "partial", + "quantum_risk": "medium", + "application": { + "name": "Example Service", + "port": 443, + "preferred_protocol": "TLSv1.3", + "preferred_cipher": "TLS_AES_256_GCM_SHA384", + "preferred_key_exchange": "ECDHE", + "port_quantum_grade": { + "grade": "B", + "score": 82.5 + } + } + } +} diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_changelog.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_changelog.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca6586deba5a3248a28f7e19b15a614309fc1ea6 GIT binary patch literal 2226 zcmb_dO-vg{6rTNqHQ10JNE$-05s>0ioQfbhf~KY+2}ErS*@BZ+4%5wgus5uC-Pv(e zP!3TK4eF(-Dz&8-dgviYkZQE0N=`Aftse0<0wHGH5QhMmD_s!ck z@4b2R=6lb5O_2r!qa%6z@`QxYBmNN#rOIsH0OlH+L7H#|jSEbOa$Y zWPete(uz8fChbR>d{LPU2M%lVAne5ltG}pf%CQRwMKJanOS&MK*Ix`A{W+!ZNlA2dYtUt!)je=uamXST_808|d znVX%Y&Shc%GxhH1_(U3?E9*8Z7xAc5Eb4X+pRpOqQ=Q{1Td~Iv&keLRlq0TqhhDBK<^kaC$P}aK5Q_TG+jv+ygiIk`=LvK{DYM!BV}MAN*oKoc z?RHf@3cJ(&_c=ZO>wY1XuJx@CELbQfxYjll{d^b|nW@+6Dc zUSnlJBYE;+T%kOBULBNZ&H`)00kqpJs5A^bHHqsfoSAod=QzyILw9kr7>7J2R|uW2 zLf$u+#|7QRJa8}ZEa+dP&x3KV0)cvnG=F;jlk+#G)?0g5TYGPI-Kk%XjQkuK`Qh}& zzVP_utR29Vjd|ZK&aOHM*)szm>j8uf>jj zckY3jeAL>tcxofOYdze)8gBn;`hNGRhvCzk657}OB*Hzx7XP@75Wub7Ct8#rTN+Pv zhvK52WXk{3c>97D#d{XCs0NISPOj{?t1#wm!K$t_^EO6Z21y{cgE8g6qg_C}R*YQ+ z?Zm)3gXCT+LsG!kZj22Jt|n(1%pjJ9F@P!Zln~5#pBwR0Px(#wBm|5LphbUQhphc2 zN=jOI(hyR{gvW?ex;N0|ffset2G0#V^w}~iQ#c0Y1x>jN%8Qq_0rAwbZ8Cmco;n3| zR0lBmd-m{EnfqBm72iG-)YmJSc!Lgr0uR(30rFT91mQQ-^9Y50ss5U`>Y9Zy;l}uS mOV4Uc&lciekGqi^UR-z}9oUe=*Ux@*_Tz~^B_y}`JNyeYX6!ov literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_kibana_assets.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_kibana_assets.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..218b4b3f8de9411ed6bc28c5f1d8241e4d3862c8 GIT binary patch literal 13456 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 H5(obatt}ue literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_manifest_assets.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_manifest_assets.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59dc1b01b529e2437e891b57239d775cef6c6dee GIT binary patch literal 3061 zcmb_eO>7fK6rT02?M-46{sJK+br4OdLrEY%IQ*!F8VV7_F&pC)YPwq1n`FV>-Oh}G zR6VpvmEcfSJ@i17K+u$)=%Kw)s6^FM-)y{gNK$cV$M(#d zH*em&nfJZ-ymdvm8bKS{wf9WckI*AN@fytC_Vi;IE~0mkBJ`re0u>^h_VxOx&mBc7 zx}!v;Hlzgl1?sOun~)-|M~ZYxN`*>#77ShD{DcNi$%?<{ErfDw5o$yry?TLIiQI&` zN>l{S-R%CN!QVMADzFs}HZ7_S6)l~bww2UNvhE<1CQn}jLW5hJLR3%?SiYKy>yQn1 zT92rt_@MVIA`N5^4Jy)R6!o*!eVSzs8HDa9#GoV%l2Dd&o~;1@1+Z&O9Q{HPUT}x7r>in%P|8J6g~KTYb(P)#w3n?? z1bA29Sg25X*S66@J{gsn&n8TAG&;h9ITKr2!C*n{G;ukyst%cXLseOgqv>b0VM7HO zCY`ZOi-kQ+DwhQ;NW{nw5q{BE*cXZ2+2h2(B%2 zs*l)KKCfpF*m|*GSd?T_*gj+EK%`G34)-V3V@1uP#e$l!3vgOa?X{>ej5Q9m?EHT9 z-I9ntFS4zpZF^g1mI7Xg+pA?WH5W;3&M5N(q>ekRzHbS}+T4{ja0ilv?jrhiW7A}8 zA~qSHh+prx5xW+<5x*AyuH$y>R_u2CR{W=)nLX*5t;c6JX2zvix&C2OWO8s~a56iQ zoqBn$b@z1Z?r)PbO-IJ1`*Oom(1@NxF~^6C;?KcjFGBGq1pbz|j^~>KaisWSrKsK` zs6x?K6xDLvIzmQBm2ptn>&3O>Q$+sp@JDuKb*Z`soVlB%VfsX#-%$le$Ot& zpAlaRR3yB!BHS-c6~0F)f#>Dl^1X0JFe5EIA+un|kslDMLND>NBHjs=QIQvEUrwfK zp*}_2jGEC_w56nE7<}A_OkV^wp@{oAC>-_g5u1=HM5~#A$NWV)w5@V z)2PM z9ZUX5X49Fu^vUV;$(h*OGxgc=-Up$TAN61E|Kg3wLlcK4lM~6QT{Df{cVh#0GbirF zPRxc*a*4jneOIDa^)K6}VzZ%6kJEaU-fP%8HF!VN{YMp8@i>I4!gF%{v|N9s@#^_m zx&470D$QS-T7O^O@vM%U40pL3j{i++;Ih|O9oXgnepk)G>Z+*E1(6F8Ugw~e@!|%x ztXfqIcCP5wwUEjSNWQdE%j+E`G;dmlWveP)1v+snbgWKQ2?d<$szw2Ar;Feq(6vfc z^*mrHXX;cp@_AK-_y{jx!ZuzJ_qkZXyw~ifxEAvoh#Ppv69totmPvUe zVV<6uoCY$XL0WMA!2gvpiNEeOH2>mmJj;9M(eXNtg8+9Pc>}t~q96#rpq59d>Sz9~ zeG&-P`YzV|xpuYCaixB4L+kX0);|$U9=9SXG(I*fZg?PtF7>_N_d)+3B9a>1GyVZN CDz^6k literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_readme.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_readme.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..248f019163df7585c4ea2006b247eda800a03e10 GIT binary patch literal 2816 zcmd5;O>7fK6rT02opoZ91T{a9A3Gq@m?#z`0Y@YujS_yMmL#=;Lo3tKvb&C#tar`K zxQHMm)I&*ofr>-R364ZUf@6^?0rwt=LP@l3PxR7Tnjob@J@n0borE-{RO+E)`_0Uo zH*emX_q{i6-w`fH(3%hRoj>SD=mnpY8qD3cIt$%Z^a)A|Bj}{Sga{w|MtscY_97GA zUSd)WYC%b{4ke|t(zvVH)8Td9VsXF%XUmfQo-+t(?;zBOK)UL6Nj_^q-5xUn=k0ZW zvB0mK7ZaQvd16=$X9||e4BHx2Jz2LCyvb@O3>2{bEMh_ufyFWtYmp7U)FCD%eL(%( zVirhBtSp6?ob>NSv4B&a)DPxozB68g2CBr90eU z{r5Y#MO#{0E-|`2+qd>9WUbrw4?cuTx;FY0+Ag|DxYbgGLI1j4Ja#eBku+PSGr{Ds z!QoTK;yGZyT0V zLEP|QE(u_esBUH`_qElzIdmj_n(Bn6C$e@2YG8*Hsuyd^B`&Y!rW3P%Ku+;UPPhQ!EXSSWKTH3ddTyxF28eMAV{4 zM`!#%yerKBGSsEGXkouAoFJG?$AMf$zce)6PTWe|9=J7duk(Il zE^&WgZs5DlM~R1tM*|NBzVBJ+omgl;z0i=Fm7dAwR_w&KQUa<)oLd@?7Wao8@RKk@w z5{IBup-@N&HfpmGE9NJ>);fVKpxT6dQ*F>=F=wY{P{lOui@Jt$3Ymrsasu9f*NWCC zG*Zp?wsDMm=*C%vV#~%%&*e>p=@_W0XKhpC3c5A{{%tqyfFtO~Kp-c=mDeY~oV+oy zShH`wX5St9U~)0s|3kR{aqUuV&vnj-xAqU~~CXdG~59s*BAYUkX(% zh8pKXjo+m1Og;~Ftct*1YXU(~@QPM|`g_%bt^Oyi6@!O^+b7B&t_}Z}MA<$qlCPx& z$Z*fLw4^_^DRtf=We$5O6Ckyqia@R*QV(QwrrNZpXopw-@)y*O{WEo2S(=_v3MPvM z$Zo!|ffEi!(g?(ni&z}7NE1wBqKih-%-178C@(DlwIa|CY{m@0ACLyg3GaidW2$6y z%!p#qj7@U5n3+!R-vI7yHn;He;ZMoG1Kx4~1;f|FUxc65#_lGb$z4lwXi=`8m+PPI z>U?nGx!kuF+yc9H|C9EL!QNoZNBHaN-p*(&=)jZ5{evg39OIm=72M}9g!xNjdMlOu zStOJ}b`umKC4q9}`x}tNrn{)_}i%837^iAFe3O9mpw$1X2b`W(4n8H|V4ktcu-DNvo<6WjQz#8u3pqFT4!$bH4jI7$wI05_BN z0a+FWLHHT%dx3&K@^9tKKt$-jQNLKdXTEyRO9YeUVF5{@*_mhJt|cjS?bK(dJ|Fu{ JMAB|o`=3#ifdl{m literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_stream_configuration.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_stream_configuration.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..affca5fb5c40081c102160a7af168023e4b11889 GIT binary patch literal 5802 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 literal 0 HcmV?d00001 diff --git a/packages/tychon_quantum_command/tests/test_changelog.py b/packages/tychon_quantum_command/tests/test_changelog.py new file mode 100644 index 00000000000..073382c558f --- /dev/null +++ b/packages/tychon_quantum_command/tests/test_changelog.py @@ -0,0 +1,28 @@ +from __future__ import print_function + +import io +import os +import re +import unittest + + +class ChangelogTest(unittest.TestCase): + def setUp(self): + # type: () -> None + self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + self.changelog_path = os.path.join(self.package_dir, 'changelog.yml') + + def test_every_change_entry_has_link(self): + # type: () -> None + with io.open(self.changelog_path, 'r', encoding='utf-8') as handle: + content = handle.read() + + change_entries = re.findall(r'(?ms)^ - description: .*?(?=^ - description: |\Z)', content) + self.assertGreaterEqual(len(change_entries), 1) + + for entry in change_entries: + self.assertRegex(entry, r'(?m)^ link: https?://\S+$') + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/packages/tychon_quantum_command/tests/test_kibana_assets.py b/packages/tychon_quantum_command/tests/test_kibana_assets.py new file mode 100644 index 00000000000..a2945ed3b19 --- /dev/null +++ b/packages/tychon_quantum_command/tests/test_kibana_assets.py @@ -0,0 +1,534 @@ +from __future__ import print_function + +import json +import os +import re +import unittest +import zipfile + + +EXPECTED_COUNTS = { + "dashboard": 6, + "index-pattern": 3, + "search": 2, + "tag": 3, + "visualization": 14, +} + +TOPOLOGY_VISUALIZATION_ID = 'tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c' +TOPOLOGY_DASHBOARD_ID = 'tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology' +APPLICATION_REPORT_DASHBOARD_ID = 'tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report' +CERTIFICATE_OPERATIONS_DASHBOARD_ID = 'tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard' +APPLICATION_LIST_VISUALIZATION_ID = 'tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e' + + +class KibanaAssetsTest(unittest.TestCase): + def setUp(self): + # type: () -> None + self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + self.kibana_dir = os.path.join(self.package_dir, "kibana") + self.kibana_zip = os.path.join(self.package_dir, "kibana.zip") + + def _get_source(self): + # type: () -> str + for root, _, files in os.walk(self.kibana_dir): + for file_name in files: + if file_name.endswith('.json'): + return 'dir' + if os.path.isfile(self.kibana_zip): + return 'zip' + self.fail('No Kibana saved objects found in kibana/ or kibana.zip') + + def _load_objects(self): + # type: () -> tuple + counts = {} + objects_by_type = {} + + if self._get_source() == 'dir': + for root, _, files in os.walk(self.kibana_dir): + folder_name = os.path.basename(root) + if folder_name == 'kibana': + continue + + normalized_type = folder_name.replace('_', '-') + for file_name in files: + if not file_name.endswith('.json'): + continue + + path = os.path.join(root, file_name) + with open(path, 'r', encoding='utf-8') as handle: + obj = json.load(handle) + + counts[normalized_type] = counts.get(normalized_type, 0) + 1 + type_objects = objects_by_type.setdefault(normalized_type, {}) + type_objects[obj['id']] = obj + + self.assertEqual(normalized_type, obj['type'], 'Object type mismatch for %s' % path) + self.assertEqual(obj['id'], os.path.splitext(file_name)[0], 'Object filename must exactly match the saved object id for %s' % path) + else: + with zipfile.ZipFile(self.kibana_zip, 'r') as archive: + for name in archive.namelist(): + if not name.endswith('.json'): + continue + + normalized_name = name.replace('\\', '/') + parts = normalized_name.split('/') + self.assertGreaterEqual(len(parts), 2, 'Unexpected archive entry %s' % normalized_name) + folder_name = parts[0] + file_name = parts[-1] + normalized_type = folder_name.replace('_', '-') + obj = json.loads(archive.read(name).decode('utf-8')) + + counts[normalized_type] = counts.get(normalized_type, 0) + 1 + type_objects = objects_by_type.setdefault(normalized_type, {}) + type_objects[obj['id']] = obj + + self.assertEqual(normalized_type, obj['type'], 'Object type mismatch for %s' % normalized_name) + self.assertEqual(obj['id'], os.path.splitext(file_name)[0], 'Object filename must exactly match the saved object id for %s' % normalized_name) + + return counts, objects_by_type + + def _load_reference_objects(self): + # type: () -> dict + reference_path = os.path.join( + os.path.dirname(self.package_dir), + "Dashboards", + "TYCHON QC Enterprise Dashboards 2.0.1.2.ndjson", + ) + objects_by_type = {} + with open(reference_path, 'r', encoding='utf-8') as handle: + for line in handle: + if not line.strip(): + continue + obj = json.loads(line) + if 'type' not in obj: + continue + type_objects = objects_by_type.setdefault(obj['type'], {}) + type_objects[obj['id']] = obj + + return objects_by_type + + def _reference_dashboard_id(self, dashboard_id): + # type: (str) -> str + normalized = dashboard_id + prefix = 'tychon_quantum_command-' + if normalized.startswith(prefix): + normalized = normalized[len(prefix):] + + for suffix in [ + '-inventory', + '-application-report', + '-application-detail', + '-application-connections-topology', + '-cost-analysis', + '-certificate-operations-dashboard', + ]: + if normalized.endswith(suffix): + return normalized[:-len(suffix)] + + return normalized + + def _panel_title(self, panel): + # type: (dict) -> str + return ( + panel.get('title') or + panel.get('embeddableConfig', {}).get('savedVis', {}).get('title') or + panel.get('embeddableConfig', {}).get('attributes', {}).get('title') or + '' + ) + + def _panel_type(self, panel): + # type: (dict) -> str + if panel.get('type') == 'search': + return 'search' + return panel.get('embeddableConfig', {}).get('savedVis', {}).get('type') or panel.get('type') + + def _resolve_reference_panel(self, dashboard, panel, reference_objects): + # type: (dict, dict, dict) -> dict + panel_ref_name = panel.get('panelRefName') + if not panel_ref_name: + return panel + + reference = None + for candidate in dashboard.get('references', []): + ref_name = candidate.get('name', '') + if ref_name == panel_ref_name or ref_name.endswith(':' + panel_ref_name): + reference = candidate + break + + if reference is None: + return panel + + saved_object = reference_objects.get(reference['type'], {}).get(reference['id']) + if saved_object is None: + return panel + + resolved = json.loads(json.dumps(panel)) + resolved.pop('panelRefName', None) + if reference['type'] == 'visualization': + vis_state = json.loads(saved_object['attributes']['visState']) + resolved.setdefault('embeddableConfig', {})['savedVis'] = { + 'title': vis_state.get('title'), + 'type': vis_state.get('type'), + 'aggs': vis_state.get('aggs', []), + 'params': vis_state.get('params', {}), + } + elif reference['type'] == 'search': + resolved['type'] = 'search' + resolved.setdefault('embeddableConfig', {})['attributes'] = saved_object['attributes'] + + return resolved + + def _collect_query_fields(self, value, fields): + # type: (object, set) -> None + if isinstance(value, dict): + for key, item in value.items(): + if key in ('field', '%timefield%', 'sourceField') and isinstance(item, str): + fields.add(item) + elif key in ('term', 'terms', 'match_phrase', 'exists', 'range') and isinstance(item, dict): + for field_name, field_value in item.items(): + if field_name == 'field' and isinstance(field_value, str): + fields.add(field_value) + elif isinstance(field_name, str): + fields.add(field_name) + self._collect_query_fields(field_value, fields) + elif key == 'query' and isinstance(item, str): + for match in re.findall(r'"?([A-Za-z_@][A-Za-z0-9_@.-]+)"?\s*:', item): + fields.add(match) + else: + self._collect_query_fields(item, fields) + elif isinstance(value, list): + for item in value: + self._collect_query_fields(item, fields) + + def _panel_query_signature(self, panel): + # type: (dict) -> tuple + indexes = set() + fields = set() + + def collect_vega_data(data): + # type: (object) -> None + if isinstance(data, dict): + url = data.get('url') + if isinstance(url, dict): + if isinstance(url.get('index'), str): + indexes.add(url['index']) + self._collect_query_fields(url, fields) + for item in data.values(): + collect_vega_data(item) + elif isinstance(data, list): + for item in data: + collect_vega_data(item) + + spec = panel.get('embeddableConfig', {}).get('savedVis', {}).get('params', {}).get('spec') + if spec: + spec_obj = json.loads(spec) + collect_vega_data(spec_obj.get('data', [])) + spec_text = json.dumps(spec_obj) + for match in re.findall(r"'([A-Za-z0-9_@.-]+)'\s*:", spec_text): + if '.' in match or match.startswith('@'): + fields.add(match) + + if panel.get('type') == 'search': + attributes = panel.get('embeddableConfig', {}).get('attributes', {}) + for column in attributes.get('columns', []): + fields.add(column) + for sort_item in attributes.get('sort', []): + if sort_item: + fields.add(sort_item[0]) + search_source = attributes.get('kibanaSavedObjectMeta', {}).get('searchSourceJSON') + if search_source: + self._collect_query_fields(json.loads(search_source), fields) + + self._collect_query_fields(panel.get('embeddableConfig', {}).get('attributes', {}).get('state', {}), fields) + + ignored_fields = set(['order', 'size']) + return sorted(indexes), sorted(fields - ignored_fields) + + def _assert_search_panel_uses_saved_object_reference(self, dashboard, panel, objects_by_type): + # type: (dict, dict, dict) -> dict + self.assertEqual('search', panel.get('type')) + self.assertIn('panelRefName', panel, 'Search panel %s must be embedded by reference' % panel.get('title')) + self.assertNotIn('attributes', panel.get('embeddableConfig', {}), 'Search panel %s should not carry by-value saved search state' % panel.get('title')) + + panel_ref_name = panel.get('panelRefName') + search_ref = None + for ref in dashboard.get('references', []): + ref_name = ref.get('name', '') + if ref.get('type') == 'search' and (ref_name == panel_ref_name or ref_name.endswith(':' + panel_ref_name)): + search_ref = ref + break + self.assertIsNotNone(search_ref, 'Search panel %s must reference a package search saved object' % panel.get('title')) + self.assertIn(search_ref['id'], objects_by_type.get('search', {})) + return objects_by_type['search'][search_ref['id']]['attributes'] + + def test_expected_object_counts(self): + counts, _ = self._load_objects() + self.assertEqual(EXPECTED_COUNTS, counts) + + def test_all_saved_object_references_resolve(self): + _, objects_by_type = self._load_objects() + + for object_type in sorted(objects_by_type): + objects = objects_by_type[object_type] + for object_id in sorted(objects): + obj = objects[object_id] + for reference in obj.get('references', []): + ref_type = reference['type'] + ref_id = reference['id'] + self.assertIn(ref_type, objects_by_type, 'Missing reference type %s from %s/%s' % (ref_type, object_type, object_id)) + self.assertIn(ref_id, objects_by_type[ref_type], 'Missing reference id %s (%s) from %s/%s' % (ref_id, ref_type, object_type, object_id)) + + def test_dashboards_do_not_use_legacy_saved_object_dependencies(self): + _, objects_by_type = self._load_objects() + + for dashboard in objects_by_type.get('dashboard', {}).values(): + disallowed_refs = {'links', 'visualization'} + for reference in dashboard.get('references', []): + self.assertNotIn(reference['type'], disallowed_refs, 'Dashboard %s still references %s' % (dashboard['id'], reference['type'])) + + panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) + for panel in panels: + if panel.get('type') == 'visualization': + self.assertNotIn('panelRefName', panel, 'Dashboard %s still uses by-reference visualization panel %s' % (dashboard['id'], panel.get('panelIndex'))) + + def test_dashboards_have_package_safe_navigation(self): + _, objects_by_type = self._load_objects() + + total_drilldown_refs = 0 + for dashboard in objects_by_type.get('dashboard', {}).values(): + search_source = json.loads(dashboard['attributes']['kibanaSavedObjectMeta']['searchSourceJSON']) + for filt in search_source.get('filter', []): + self.assertNotEqual(filt.get('query', {}).get('exists', {}).get('field'), '@timestamp', 'Dashboard %s still has a dashboard-level @timestamp exists filter' % dashboard['id']) + + drilldown_refs = [ + ref for ref in dashboard.get('references', []) + if ref['type'] == 'dashboard' and 'DASHBOARD_TO_DASHBOARD_DRILLDOWN' in ref['name'] + ] + self.assertGreaterEqual(len(drilldown_refs), 1, 'Dashboard %s is missing package-safe navigation drilldowns' % dashboard['id']) + total_drilldown_refs += len(drilldown_refs) + + panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) + panel_event_count = 0 + for panel in panels: + events = panel.get('embeddableConfig', {}).get('enhancements', {}).get('dynamicActions', {}).get('events', []) + for event in events: + if event.get('action', {}).get('factoryId') == 'DASHBOARD_TO_DASHBOARD_DRILLDOWN': + panel_event_count += 1 + self.assertGreaterEqual(panel_event_count, 1, 'Dashboard %s has no embedded drilldown events' % dashboard['id']) + + self.assertGreaterEqual(total_drilldown_refs, 20) + + def test_dashboards_have_visible_navigation_panel_in_screenshot_order(self): + _, objects_by_type = self._load_objects() + expected_labels = [ + 'Inventory', + 'Application Report', + 'Application Detail', + 'Certificate Report', + 'Application Connections Topology', + 'Cost Analysis', + ] + + for dashboard in objects_by_type.get('dashboard', {}).values(): + panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) + nav_panels = [panel for panel in panels if panel.get('panelIndex') == 'tychon-quantum-command-nav'] + self.assertEqual(1, len(nav_panels), 'Dashboard %s must include one visible nav panel' % dashboard['id']) + nav_panel = nav_panels[0] + self.assertEqual(0, nav_panel.get('gridData', {}).get('y'), 'Dashboard %s nav panel must be at the top row' % dashboard['id']) + self.assertEqual(3, nav_panel.get('gridData', {}).get('h'), 'Dashboard %s nav panel should match reference panel height' % dashboard['id']) + params = nav_panel.get('embeddableConfig', {}).get('savedVis', {}).get('params', {}) + self.assertEqual(12, params.get('fontSize'), 'Dashboard %s nav panel should match reference markdown font size' % dashboard['id']) + markdown = params.get('markdown', '') + self.assertNotIn('TYCHON Quantum Command Navigation', markdown, 'Dashboard %s nav panel should not include an extra heading' % dashboard['id']) + positions = [] + for label in expected_labels: + pos = markdown.find(label) + self.assertNotEqual(-1, pos, 'Dashboard %s nav panel is missing label %s' % (dashboard['id'], label)) + positions.append(pos) + self.assertEqual(sorted(positions), positions, 'Dashboard %s nav labels are out of order' % dashboard['id']) + + def test_package_dashboards_match_reference_saved_object_queries(self): + # type: () -> None + _, package_objects = self._load_objects() + reference_objects = self._load_reference_objects() + + reference_dashboards = reference_objects.get('dashboard', {}) + package_dashboards_by_reference_id = {} + for dashboard in package_objects.get('dashboard', {}).values(): + package_dashboards_by_reference_id[self._reference_dashboard_id(dashboard['id'])] = dashboard + + self.assertEqual(set(reference_dashboards), set(package_dashboards_by_reference_id)) + + for reference_id in sorted(reference_dashboards): + reference_dashboard = reference_dashboards[reference_id] + package_dashboard = package_dashboards_by_reference_id[reference_id] + reference_panels = {} + for panel in json.loads(reference_dashboard['attributes'].get('panelsJSON', '[]')): + reference_panels[panel.get('panelIndex')] = self._resolve_reference_panel(reference_dashboard, panel, reference_objects) + package_panels = {} + for panel in json.loads(package_dashboard['attributes'].get('panelsJSON', '[]')): + package_panels[panel.get('panelIndex')] = self._resolve_reference_panel(package_dashboard, panel, package_objects) + + missing_panel_ids = set(reference_panels) - set(package_panels) + extra_panel_ids = set(package_panels) - set(reference_panels) + self.assertEqual( + ['links'], + sorted(set(self._panel_type(reference_panels[panel_id]) for panel_id in missing_panel_ids)), + 'Dashboard %s has non-navigation panels missing from the package' % package_dashboard['id'], + ) + self.assertEqual( + set(['tychon-quantum-command-nav']), + extra_panel_ids, + 'Dashboard %s has unexpected package-only panels' % package_dashboard['id'], + ) + + for panel_id in sorted(set(reference_panels) & set(package_panels)): + reference_panel = reference_panels[panel_id] + package_panel = package_panels[panel_id] + self.assertEqual( + self._panel_title(reference_panel), + self._panel_title(package_panel), + 'Dashboard %s panel %s title drifted from the reference saved object' % (package_dashboard['id'], panel_id), + ) + self.assertEqual( + self._panel_query_signature(reference_panel), + self._panel_query_signature(package_panel), + 'Dashboard %s panel %s query fields drifted from the reference saved object' % (package_dashboard['id'], panel_id), + ) + + def test_package_dashboards_do_not_contain_mojibake(self): + # type: () -> None + _, objects_by_type = self._load_objects() + blocked_markers = ['\\u00e2', '\\u20ac', u'ā', u'â', u'Ã', u'�'] + + for dashboard in objects_by_type.get('dashboard', {}).values(): + dashboard_text = json.dumps(dashboard, ensure_ascii=False) + for marker in blocked_markers: + self.assertNotIn(marker, dashboard_text, 'Dashboard %s contains mojibake marker %s' % (dashboard['id'], marker)) + + def test_application_connections_topology_panel_matches_standalone_visualization(self): + # type: () -> None + _, objects_by_type = self._load_objects() + + dashboard = objects_by_type['dashboard'][TOPOLOGY_DASHBOARD_ID] + visualization = objects_by_type['visualization'][TOPOLOGY_VISUALIZATION_ID] + visualization_state = json.loads(visualization['attributes']['visState']) + + panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) + topology_panels = [panel for panel in panels if panel.get('title') == 'PQC Connections Topology'] + self.assertEqual(1, len(topology_panels), 'Topology dashboard must embed exactly one PQC Connections Topology panel') + + topology_panel = topology_panels[0] + saved_vis = topology_panel.get('embeddableConfig', {}).get('savedVis', {}) + inline_state = { + 'title': saved_vis.get('title'), + 'type': saved_vis.get('type'), + 'aggs': saved_vis.get('data', {}).get('aggs', []), + 'params': saved_vis.get('params', {}), + } + self.assertEqual(visualization_state, inline_state, 'Topology dashboard panel must stay in sync with the standalone Vega visualization') + + spec = json.loads(visualization_state['params']['spec']) + raw_sources = [source for source in spec.get('data', []) if source.get('name') == 'raw'] + self.assertEqual(1, len(raw_sources), 'Topology Vega spec must define exactly one raw source') + self.assertEqual('tychon-pqc-applications', raw_sources[0].get('url', {}).get('index')) + raw_must = raw_sources[0].get('url', {}).get('body', {}).get('aggs', {}).get('pairs', {}).get('filter', {}).get('bool', {}).get('must', []) + self.assertIn({'exists': {'field': 'host.hostname'}}, raw_must) + self.assertIn({'exists': {'field': 'tychon.application.name'}}, raw_must) + self.assertIn({'term': {'event.dataset': 'tychon.application'}}, raw_must) + + def test_application_visualizations_do_not_filter_on_unreachable_event_dataset(self): + # type: () -> None + _, objects_by_type = self._load_objects() + + application_list = objects_by_type['visualization'][APPLICATION_LIST_VISUALIZATION_ID] + topology = objects_by_type['visualization'][TOPOLOGY_VISUALIZATION_ID] + + app_list_spec = json.loads(json.loads(application_list['attributes']['visState'])['params']['spec']) + topology_spec = json.loads(json.loads(topology['attributes']['visState'])['params']['spec']) + + app_sources = [source for source in app_list_spec.get('data', []) if source.get('name') == 'apps'] + self.assertEqual(1, len(app_sources), 'Application list visualization must define one apps source') + self.assertEqual('tychon-pqc-applications', app_sources[0].get('url', {}).get('index')) + app_filter = app_sources[0].get('url', {}).get('body', {}).get('aggs', {}).get('app_only', {}).get('filter', {}) + self.assertEqual({'term': {'event.dataset': 'tychon.application'}}, app_filter) + + active_signals = [signal for signal in app_list_spec.get('signals', []) if signal.get('name') == 'activeFilter'] + self.assertEqual(1, len(active_signals), 'Application list visualization must define one activeFilter signal') + active_update = active_signals[0].get('update', '') + self.assertIn("'event.dataset': 'tychon.application'", active_update) + + self.assertIn("event.dataset", repr(topology_spec)) + + + def test_application_report_embeds_dod_omb_report_search_panel(self): + # type: () -> None + _, objects_by_type = self._load_objects() + + dashboard = objects_by_type['dashboard'][APPLICATION_REPORT_DASHBOARD_ID] + panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) + omb_panels = [panel for panel in panels if panel.get('title') == 'DoD OMB Report'] + self.assertEqual(1, len(omb_panels), 'Application Report dashboard must embed exactly one DoD OMB Report panel') + + omb_panel = omb_panels[0] + attributes = self._assert_search_panel_uses_saved_object_reference(dashboard, omb_panel, objects_by_type) + self.assertEqual('DoD OMB Report', attributes.get('title')) + self.assertEqual('OMB Report for the Department of Defense', attributes.get('description')) + self.assertIn('observer.hostname', attributes.get('columns', [])) + self.assertIn('omb.vulnerability_status', attributes.get('columns', [])) + + search_source = json.loads(attributes['kibanaSavedObjectMeta']['searchSourceJSON']) + self.assertEqual('kibanaSavedObjectMeta.searchSourceJSON.index', search_source.get('indexRefName')) + filters = search_source.get('filter', []) + self.assertEqual(1, len(filters)) + self.assertEqual('omb.vulnerability_status', filters[0].get('query', {}).get('exists', {}).get('field')) + self.assertEqual('kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index', filters[0].get('meta', {}).get('indexRefName')) + + + def test_certificate_operations_dashboard_embeds_inventory_detail_search_panel(self): + # type: () -> None + _, objects_by_type = self._load_objects() + + dashboard = objects_by_type['dashboard'][CERTIFICATE_OPERATIONS_DASHBOARD_ID] + panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) + inventory_panels = [panel for panel in panels if panel.get('title') == 'Certificate Inventory Detail'] + self.assertEqual(1, len(inventory_panels), 'Certificate Operations dashboard must embed exactly one Certificate Inventory Detail panel') + + inventory_panel = inventory_panels[0] + attributes = self._assert_search_panel_uses_saved_object_reference(dashboard, inventory_panel, objects_by_type) + self.assertEqual('Certificate Inventory Detail', attributes.get('title')) + self.assertIn('observer.hostname', attributes.get('columns', [])) + self.assertIn('x509.subject.common_name', attributes.get('columns', [])) + self.assertEqual([[u'cert_days_remaining', u'asc']], attributes.get('sort')) + + search_source = json.loads(attributes['kibanaSavedObjectMeta']['searchSourceJSON']) + self.assertEqual('kibanaSavedObjectMeta.searchSourceJSON.index', search_source.get('indexRefName')) + self.assertEqual([], search_source.get('filter', [])) + + + def test_application_list_panel_matches_standalone_visualization(self): + # type: () -> None + _, objects_by_type = self._load_objects() + + dashboard = objects_by_type['dashboard'][TOPOLOGY_DASHBOARD_ID] + visualization = objects_by_type['visualization'][APPLICATION_LIST_VISUALIZATION_ID] + visualization_state = json.loads(visualization['attributes']['visState']) + + panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) + app_panels = [panel for panel in panels if panel.get('title') == 'QuantumApplicationList'] + self.assertEqual(1, len(app_panels), 'Topology dashboard must embed exactly one QuantumApplicationList panel') + + app_panel = app_panels[0] + saved_vis = app_panel.get('embeddableConfig', {}).get('savedVis', {}) + inline_state = { + 'title': saved_vis.get('title'), + 'type': saved_vis.get('type'), + 'aggs': saved_vis.get('data', {}).get('aggs', []), + 'params': saved_vis.get('params', {}), + } + self.assertEqual(visualization_state, inline_state, 'Topology dashboard app list panel must stay in sync with the standalone Vega visualization') + + +if __name__ == '__main__': + unittest.main() diff --git a/packages/tychon_quantum_command/tests/test_manifest_assets.py b/packages/tychon_quantum_command/tests/test_manifest_assets.py new file mode 100644 index 00000000000..49abc0304b5 --- /dev/null +++ b/packages/tychon_quantum_command/tests/test_manifest_assets.py @@ -0,0 +1,40 @@ +from __future__ import print_function + +import io +import os +import unittest + + +SCREENSHOTS = [ + ('/img/TQC_Inventory.png', '3434x1086'), + ('/img/TQC_Application_Report.png', '3437x1072'), + ('/img/TQC_Application_Detail.png', '3435x1086'), + ('/img/TQC_Certificate_Report.png', '3437x1083'), + ('/img/TQC_Application_Connections_Topology.png', '3435x1082'), + ('/img/TQC_Cost_Analysis.png', '3438x1082'), +] + + +class ManifestAssetsTest(unittest.TestCase): + def setUp(self): + # type: () -> None + self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + self.manifest_path = os.path.join(self.package_dir, 'manifest.yml') + + def test_manifest_screenshot_files_exist_with_expected_size_metadata(self): + # type: () -> None + with io.open(self.manifest_path, 'r', encoding='utf-8') as handle: + content = handle.read() + + for src, size in SCREENSHOTS: + disk_path = os.path.join(self.package_dir, src.lstrip('/').replace('/', os.sep)) + self.assertTrue(os.path.isfile(disk_path), 'Missing screenshot file %s' % src) + self.assertIn('src: %s' % src, content) + self.assertIn('size: %s' % size, content) + + self.assertNotIn('Topography', content) + self.assertNotIn('Appplication', content) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/packages/tychon_quantum_command/tests/test_publish_readiness.py b/packages/tychon_quantum_command/tests/test_publish_readiness.py new file mode 100644 index 00000000000..75d59285ecd --- /dev/null +++ b/packages/tychon_quantum_command/tests/test_publish_readiness.py @@ -0,0 +1,65 @@ +from __future__ import print_function + +import io +import json +import os +import unittest + + +class PublishReadinessTest(unittest.TestCase): + def setUp(self): + # type: () -> None + self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + self.docs_dir = os.path.join(self.package_dir, 'docs') + self.dev_dir = os.path.join(self.package_dir, '_dev') + self.sample_event_path = os.path.join(self.package_dir, 'sample_event.json') + self.validation_path = os.path.join(self.package_dir, 'validation.yml') + + def test_package_sample_event_is_real_data(self): + # type: () -> None + with io.open(self.sample_event_path, 'r', encoding='utf-8') as handle: + sample_event = json.load(handle) + + self.assertNotIn('description', sample_event) + self.assertEqual('logs', sample_event['data_stream']['type']) + self.assertEqual('tychon_quantum_command.tychon_pqc', sample_event['data_stream']['dataset']) + self.assertEqual('tychon_quantum_command.tychon_pqc', sample_event['event']['dataset']) + self.assertIn('@timestamp', sample_event) + self.assertIn('tychon', sample_event) + + def test_validation_enforces_docs_structure(self): + # type: () -> None + with io.open(self.validation_path, 'r', encoding='utf-8') as handle: + content = handle.read() + + self.assertIn('docs_structure_enforced:', content) + self.assertIn('enabled: true', content) + self.assertIn('version: 1', content) + self.assertIn('exclude_checks: [ "SVR00002" ]', content) + + def test_docs_directory_contains_only_generated_readme(self): + # type: () -> None + markdown_files = [] + for file_name in os.listdir(self.docs_dir): + if file_name.lower().endswith('.md'): + markdown_files.append(file_name) + + self.assertEqual(['README.md'], sorted(markdown_files)) + + def test_dev_directory_contains_only_build_readme_template(self): + # type: () -> None + allowed_files = set([ + '_dev/build/docs/README.md', + ]) + found_files = set() + + for root, _, files in os.walk(self.dev_dir): + for file_name in files: + relative_path = os.path.relpath(os.path.join(root, file_name), self.package_dir) + found_files.add(relative_path.replace('\\', '/')) + + self.assertEqual(allowed_files, found_files) + + +if __name__ == '__main__': + unittest.main() diff --git a/packages/tychon_quantum_command/tests/test_readme.py b/packages/tychon_quantum_command/tests/test_readme.py new file mode 100644 index 00000000000..b852e2ee04e --- /dev/null +++ b/packages/tychon_quantum_command/tests/test_readme.py @@ -0,0 +1,65 @@ +from __future__ import print_function + +import io +import os +import unittest + + +class ReadmeTest(unittest.TestCase): + def setUp(self): + # type: () -> None + self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + self.readme_path = os.path.join(self.package_dir, 'docs', 'README.md') + self.readme_template_path = os.path.join( + self.package_dir, + '_dev', + 'build', + 'docs', + 'README.md', + ) + + def test_readme_has_no_template_placeholders(self): + # type: () -> None + with io.open(self.readme_path, 'r', encoding='utf-8') as handle: + content = handle.read() + + disallowed_markers = [ + '{Data stream name}', + '{data stream name}', + '{source}', + '{list types}', + 'Vendor documentation link 1', + 'Vendor documentation link 2', + 'Vendor documentation link 3', + 'These APIs are used with this integration:\n* ...', + 'replace the placeholder package `sample_event.json`', + ] + + for marker in disallowed_markers: + self.assertNotIn(marker, content) + + def test_readme_uses_namespace_safe_transform_source(self): + # type: () -> None + with io.open(self.readme_path, 'r', encoding='utf-8') as handle: + content = handle.read() + + self.assertIn('logs-tychon_quantum_command.tychon_pqc-*', content) + self.assertIn('logs-tychon_quantum_command.tychon_pqc-', content) + self.assertIn('`logs-tychon_quantum_command.tychon_pqc`', content) + self.assertIn('.ds-logs-tychon_quantum_command.tychon_pqc--YYYY.MM.DD-000001', content) + self.assertNotIn('logs-tychon_pqc-*', content) + + def test_readme_template_exists_and_uses_generated_header(self): + # type: () -> None + self.assertTrue(os.path.isfile(self.readme_template_path)) + + with io.open(self.readme_template_path, 'r', encoding='utf-8') as handle: + content = handle.read() + + self.assertTrue(content.startswith('{{ generatedHeader }}\n\n')) + self.assertNotIn('\n', content) + self.assertNotIn('replace the placeholder package `sample_event.json`', content) + + +if __name__ == '__main__': + unittest.main() diff --git a/packages/tychon_quantum_command/tests/test_stream_configuration.py b/packages/tychon_quantum_command/tests/test_stream_configuration.py new file mode 100644 index 00000000000..8d968981993 --- /dev/null +++ b/packages/tychon_quantum_command/tests/test_stream_configuration.py @@ -0,0 +1,230 @@ +from __future__ import print_function + +import io +import os +import re +import unittest + + +class StreamConfigurationTest(unittest.TestCase): + def setUp(self): + # type: () -> None + self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + self.manifest_path = os.path.join( + self.package_dir, + "data_stream", + "tychon_pqc", + "manifest.yml", + ) + self.stream_template_path = os.path.join( + self.package_dir, + "data_stream", + "tychon_pqc", + "agent", + "stream", + "stream.yml.hbs", + ) + self.pipeline_path = os.path.join( + self.package_dir, + "data_stream", + "tychon_pqc", + "elasticsearch", + "ingest_pipeline", + "default.yml", + ) + self.ecs_fields_path = os.path.join( + self.package_dir, + "data_stream", + "tychon_pqc", + "fields", + "ecs.yml", + ) + self.custom_fields_path = os.path.join( + self.package_dir, + "data_stream", + "tychon_pqc", + "fields", + "fields.yml", + ) + self.transform_dir = os.path.join( + self.package_dir, + "elasticsearch", + "transform", + ) + + def _read_text(self, path): + # type: (str) -> str + with io.open(path, "r", encoding="utf-8") as handle: + return handle.read() + + def test_manifest_exposes_windows_and_linux_path_vars(self): + # type: () -> None + content = self._read_text(self.manifest_path) + + self.assertIn("- name: windows_paths", content) + self.assertIn("title: Windows paths", content) + self.assertIn(r"C:\Program Files\Tychon\*.ndjson", content) + + self.assertIn("- name: linux_paths", content) + self.assertIn("title: Linux paths", content) + self.assertIn("/var/log/tychon/*.ndjson", content) + + additional_paths_match = re.search( + r"- name: paths\s+type: text\s+title: Additional paths\s+multi: true\s+required: false", + content, + re.MULTILINE, + ) + self.assertIsNotNone(additional_paths_match) + + def test_stream_template_renders_all_path_groups(self): + # type: () -> None + content = self._read_text(self.stream_template_path) + + self.assertNotIn("type: filestream", content) + self.assertNotIn("id:", content) + self.assertNotIn("data_stream:", content) + self.assertNotIn("{{uuid}}", content) + self.assertNotIn("{{data_stream.type}}-{{data_stream.dataset}}", content) + self.assertIn("parsers:", content) + self.assertIn("ndjson:", content) + self.assertIn("overwrite_keys: true", content) + self.assertIn("expand_keys: true", content) + + expected_order = [ + "{{#each windows_paths}}", + "{{#each linux_paths}}", + "{{#each paths}}", + ] + + start = 0 + for marker in expected_order: + index = content.find(marker, start) + self.assertNotEqual(-1, index, "Missing marker %s" % marker) + start = index + 1 + + def test_ingest_pipeline_preserves_or_derives_event_dataset(self): + # type: () -> None + content = self._read_text(self.pipeline_path) + + self.assertNotIn("field: event.dataset\n value: tychon_pqc", content) + self.assertIn("currentDataset == null", content) + self.assertIn("currentDataset == 'tychon_quantum_command.tychon_pqc'", content) + self.assertIn("currentDataset == 'tychon_pqc'", content) + self.assertIn("dataset = 'tychon.application';", content) + self.assertIn("dataset = 'tychon.installed_app';", content) + self.assertIn("dataset = 'tychon.browser_extension';", content) + self.assertIn("dataset = 'tychon.cipher';", content) + self.assertIn("tychonIndex == 'system-readiness'", content) + self.assertIn("def eventAction = ctx.event.action != null ? ctx.event.action.toString() : null;", content) + self.assertIn("if (eventAction == 'quantum_assessment_app_group') {", content) + self.assertIn("dataset = 'quantum_assessment.app_group';", content) + self.assertIn("dataset = 'quantum_assessment';", content) + self.assertIn("currentDataset == genericDataset", content) + self.assertIn("currentDataset instanceof List && currentDataset.contains(genericDataset)", content) + self.assertIn("genericDataset = tychonIndex != null ? 'tychon_quantum_command.' + tychonIndex : null;", content) + + def test_ingest_pipeline_includes_reference_rehydration_and_flat_field_logic(self): + # type: () -> None + content = self._read_text(self.pipeline_path) + + self.assertIn("field: event.ingested", content) + self.assertIn("Preserve flat event.* fields before event defaults are applied.", content) + self.assertIn("ctx.event.dataset = ctx['event.dataset'];", content) + self.assertIn("ctx.remove('event.dataset');", content) + self.assertLess(content.find("ctx.event.dataset = ctx['event.dataset'];"), content.find("def shouldDeriveDataset")) + self.assertIn("- dot_expander:", content) + self.assertIn("field: tychon.pipeline.processed", content) + self.assertIn("field: tychon.pipeline.failed", content) + self.assertIn("field: tychon.routing.original.host_ip", content) + self.assertIn("field: tychon.routing.target.ip", content) + self.assertIn("ctx.tychon.certificate_leaf_details = leafDetails;", content) + self.assertNotIn("certificate.leaf", content) + self.assertIn("ctx.tychon.cipher_negotiation = cipherNeg;", content) + self.assertIn("field: x509.issuer.organization", content) + self.assertIn("{{certificate.subject_public_key_info.curve}}", content) + self.assertIn("field: certificate.not_before", content) + self.assertIn("field: certificate.not_after", content) + self.assertIn("field: x509.subject.organization", content) + self.assertIn("field: x509.public_key_curve", content) + self.assertIn("field: destination.address", content) + self.assertIn("field: source.user.id", content) + self.assertIn("field: host.domain", content) + self.assertIn("field: network.protocol", content) + self.assertIn("{{port.protocol_detected}}", content) + self.assertIn("{{tychon.application.protocol_detected}}", content) + self.assertIn("field: error.processor_type", content) + self.assertIn("field: error.processor_tag", content) + self.assertIn("field: error.pipeline", content) + self.assertIn("ctx?.event?.dataset == 'quantum_assessment.app_group'", content) + self.assertIn("costAnalysis.instance_count = 1;", content) + self.assertNotIn("costAnalysis.app_family = costAnalysis.os_upgrade_target;", content) + self.assertNotIn("costAnalysis.tier = costAnalysis.os_tier;", content) + self.assertNotIn("costAnalysis.labor_cost_usd = costAnalysis.os_labor_cost_usd;", content) + self.assertNotIn("costAnalysis.license_cost_usd = costAnalysis.os_license_cost_usd;", content) + self.assertNotIn("costAnalysis.hardware_cost_usd = costAnalysis.os_hardware_cost_usd;", content) + + def test_field_definitions_cover_rehydrated_pipeline_outputs(self): + # type: () -> None + ecs_content = self._read_text(self.ecs_fields_path) + custom_content = self._read_text(self.custom_fields_path) + + self.assertIn("- name: ingested", ecs_content) + self.assertIn("- name: address", ecs_content) + self.assertIn("- name: pipeline", ecs_content) + self.assertIn("- name: processor_tag", ecs_content) + self.assertIn("- name: processor_type", ecs_content) + self.assertIn("- name: ipv4", ecs_content) + self.assertIn("- name: ipv6", ecs_content) + self.assertIn("- name: domain", ecs_content) + self.assertIn("- name: network", ecs_content) + self.assertIn("- name: protocol", ecs_content) + self.assertIn("- name: source", ecs_content) + self.assertIn("- name: id", ecs_content) + + self.assertIn("- name: pipeline", custom_content) + self.assertIn("- name: processed", custom_content) + self.assertIn("- name: failed", custom_content) + self.assertIn("- name: routing", custom_content) + self.assertIn("- name: cipher_negotiation", custom_content) + self.assertIn("- name: crypto_libraries", custom_content) + self.assertIn("- name: public_key_curve", custom_content) + self.assertIn("- name: organization", custom_content) + self.assertIn("- name: not_before", custom_content) + self.assertIn("- name: not_after", custom_content) + self.assertIn("- name: app_family", custom_content) + self.assertIn("- name: tier", custom_content) + self.assertIn("- name: instance_count", custom_content) + self.assertIn("- name: labor_cost_usd", custom_content) + self.assertIn("- name: license_cost_usd", custom_content) + self.assertIn("- name: hardware_cost_usd", custom_content) + + def test_transforms_use_namespace_safe_source_index(self): + # type: () -> None + expected_source_index = "index: logs-tychon_quantum_command.tychon_pqc-*" + + for transform_name in os.listdir(self.transform_dir): + transform_path = os.path.join( + self.transform_dir, + transform_name, + "transform.yml", + ) + + if not os.path.isfile(transform_path): + continue + + content = self._read_text(transform_path) + + self.assertIn( + expected_source_index, + content, + "Transform %s must read from every namespace." % transform_name, + ) + self.assertNotIn( + "index: logs-tychon_quantum_command.tychon_pqc-default", + content, + "Transform %s still hardcodes the default namespace." % transform_name, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/tychon_quantum_command/validation.yml b/packages/tychon_quantum_command/validation.yml new file mode 100644 index 00000000000..b48d0821f75 --- /dev/null +++ b/packages/tychon_quantum_command/validation.yml @@ -0,0 +1,6 @@ +# validation.yml +docs_structure_enforced: + enabled: true + version: 1 +errors: + exclude_checks: [ "SVR00002" ] From a8e43742f066487082ed8bbe414511ead9f5c0e7 Mon Sep 17 00:00:00 2001 From: Thomas Hatcher Date: Wed, 15 Jul 2026 17:29:28 +0000 Subject: [PATCH 2/6] changelog.yml now points to https://github.com/elastic/integrations/pull/20142. --- packages/tychon_quantum_command/changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tychon_quantum_command/changelog.yml b/packages/tychon_quantum_command/changelog.yml index deeb8714e22..effe880656e 100644 --- a/packages/tychon_quantum_command/changelog.yml +++ b/packages/tychon_quantum_command/changelog.yml @@ -2,4 +2,4 @@ changes: - description: Initial release of the TYCHON Quantum Command integration package. type: enhancement - link: https://github.com/tychonllc/tychon_quantum_command/issues/1 + link: https://github.com/elastic/integrations/pull/20142 From 420e25c09e494cf19b4f4bd457e599ccc7327fcf Mon Sep 17 00:00:00 2001 From: Thomas Hatcher Date: Fri, 17 Jul 2026 18:30:11 +0000 Subject: [PATCH 3/6] removed 'test' directory for integration publishing requirement --- .buildkite/pipeline.schedule-daily.yml | 8 +- .buildkite/pipeline.schedule-weekly.yml | 6 +- .buildkite/pipeline.yml | 19 + .buildkite/scripts/backport_branch.sh | 43 +- .buildkite/scripts/non_package_patterns.txt | 5 + .../scripts/run_buildkite_scripts_tests.sh | 4 + .../scripts/test_non_package_patterns.sh | 5 + .github/workflows/pr-buildkite-detective.yml | 22 +- dev/backports/apply/apply.go | 207 +- dev/backports/apply/apply_integration_test.go | 372 +- dev/backports/apply/apply_test.go | 119 + dev/backports/changelog/collect.go | 2 +- dev/backports/changelog/sync.go | 2 +- dev/backports/gitutil/git.go | 39 - dev/citools/packagemanifest.go | 59 +- dev/citools/packages.go | 15 +- dev/codeowners/codeowners.go | 115 +- dev/codeowners/codeowners_test.go | 212 + magefile.go | 85 +- packages/aws/changelog.yml | 20 + .../guardduty/agent/stream/httpjson.yml.hbs | 49 +- packages/aws/manifest.yml | 107 +- packages/aws_rds_otel/changelog.yml | 5 + ...-c92e1216-83f6-4de7-9d7f-1bcb42d5988a.json | 5525 ++++++++--------- packages/aws_rds_otel/manifest.yml | 12 +- .../azure_frontdoor/_dev/build/docs/README.md | 10 +- packages/azure_frontdoor/changelog.yml | 5 + packages/azure_frontdoor/docs/README.md | 33 +- packages/azure_frontdoor/manifest.yml | 2 +- packages/checkpoint/changelog.yml | 5 + .../_dev/test/pipeline/test-checkpoint.log | 11 + .../test-checkpoint.log-expected.json | 1272 ++++ .../elasticsearch/ingest_pipeline/default.yml | 91 +- .../data_stream/firewall/fields/ecs.yml | 6 + packages/checkpoint/docs/README.md | 6 + packages/checkpoint/manifest.yml | 2 +- .../_dev/deploy/docker/files/config.yml | 2 +- packages/cyberark_epm/changelog.yml | 5 + .../_dev/test/system/test-default-config.yml | 4 +- .../admin_audit/agent/stream/cel.yml.hbs | 4 +- .../data_stream/admin_audit/sample_event.json | 16 +- .../_dev/test/system/test-default-config.yml | 4 +- .../aggregated_event/agent/stream/cel.yml.hbs | 4 +- .../aggregated_event/sample_event.json | 16 +- .../_dev/test/system/test-default-config.yml | 4 +- .../agent/stream/cel.yml.hbs | 4 +- .../sample_event.json | 16 +- .../_dev/test/system/test-default-config.yml | 4 +- .../agent/stream/cel.yml.hbs | 4 +- .../policyaudit_raw_event/sample_event.json | 16 +- .../_dev/test/system/test-default-config.yml | 4 +- .../raw_event/agent/stream/cel.yml.hbs | 4 +- .../data_stream/raw_event/sample_event.json | 16 +- packages/cyberark_epm/docs/README.md | 80 +- packages/cyberark_epm/manifest.yml | 2 +- packages/cyera/_dev/build/docs/README.md | 17 +- .../cyera/_dev/deploy/docker/files/config.yml | 137 +- packages/cyera/changelog.yml | 5 + packages/cyera/docs/README.md | 130 +- packages/cyera/manifest.yml | 2 +- packages/kolide/_dev/build/docs/README.md | 339 +- packages/kolide/changelog.yml | 8 + .../_dev/deploy/docker/docker-compose.yml | 12 + .../audit/agent/stream/aws-s3.yml.hbs | 3 + .../elasticsearch/ingest_pipeline/default.yml | 16 +- .../kolide/data_stream/audit/fields/agent.yml | 19 + .../data_stream/audit/fields/base-fields.yml | 16 +- .../kolide/data_stream/audit/manifest.yml | 106 + .../data_stream/audit/sample_event.json | 22 +- .../_dev/deploy/docker/docker-compose.yml | 12 + .../auth/agent/stream/aws-s3.yml.hbs | 3 + .../elasticsearch/ingest_pipeline/default.yml | 10 +- .../kolide/data_stream/auth/fields/agent.yml | 19 + .../data_stream/auth/fields/base-fields.yml | 16 +- packages/kolide/data_stream/auth/manifest.yml | 106 + .../kolide/data_stream/auth/sample_event.json | 107 +- ...-kolide-device-pipeline.json-expected.json | 14 +- .../data_stream/device/fields/base-fields.yml | 16 +- .../kolide/data_stream/device/manifest.yml | 4 +- .../data_stream/device/sample_event.json | 19 +- .../device_check/agent/stream/aws-s3.yml.hbs | 3 + .../elasticsearch/ingest_pipeline/default.yml | 11 +- .../data_stream/device_check/fields/agent.yml | 19 + .../device_check/fields/base-fields.yml | 16 +- .../data_stream/device_check/manifest.yml | 106 + .../device_check/sample_event.json | 58 +- .../deploy/docker/files/config-issues.yml | 21 +- .../pipeline/test-kolide-issues-pipeline.json | 8 +- ...-kolide-issues-pipeline.json-expected.json | 114 +- ...t-kolide-issues-webhook.json-expected.json | 2 + .../issues/agent/stream/cel.yml.hbs | 18 +- .../ingest_pipeline/categorize.yml | 39 +- .../elasticsearch/ingest_pipeline/default.yml | 53 +- .../elasticsearch/ingest_pipeline/webhook.yml | 14 + .../data_stream/issues/fields/base-fields.yml | 16 +- .../data_stream/issues/fields/fields.yml | 4 +- .../data_stream/issues/sample_event.json | 25 +- .../test-kolide-webhook-pipeline.json | 35 + ...kolide-webhook-pipeline.json-expected.json | 55 + .../webhook/fields/base-fields.yml | 16 +- .../kolide/data_stream/webhook/manifest.yml | 2 +- .../data_stream/webhook/routing_rules.yml | 6 + packages/kolide/docs/README.md | 1343 +++- ...-56facae3-56fb-4637-aac5-961c69b0b4af.json | 1057 +++- packages/kolide/manifest.yml | 36 +- packages/osquery_manager/changelog.yml | 11 + packages/osquery_manager/manifest.yml | 7 +- packages/qualys_vmdr/changelog.yml | 5 + .../test-asset-host-detection-events.json | 6 + ...t-host-detection-events.json-expected.json | 105 + .../pipeline/test-asset-host-detection.log | 1 + ...est-asset-host-detection.log-expected.json | 111 + .../elasticsearch/ingest_pipeline/default.yml | 18 +- .../asset_host_detection/fields/fields.yml | 3 + packages/qualys_vmdr/docs/README.md | 1 + .../fields/fields.yml | 3 + packages/qualys_vmdr/manifest.yml | 2 +- .../stormshield/_dev/build/docs/README.md | 34 + packages/stormshield/changelog.yml | 17 + .../pipeline/test-firewall.log-expected.json | 429 +- .../elasticsearch/ingest_pipeline/count.yml | 50 +- .../elasticsearch/ingest_pipeline/default.yml | 215 +- .../data_stream/log/fields/ecs.yml | 34 + .../data_stream/log/sample_event.json | 29 +- packages/stormshield/docs/README.md | 79 +- packages/stormshield/manifest.yml | 2 +- .../docker/files/intelligence-api-config.yml | 56 + packages/ti_anomali/changelog.yml | 5 + .../_dev/test/policy/test-all.expected | 91 +- .../_dev/test/policy/test-default.expected | 91 +- .../intelligence/agent/stream/cel.yml.hbs | 91 +- packages/ti_anomali/manifest.yml | 2 +- .../_dev/test/policy/test-multi-values.yml | 8 +- .../test_changelog.cpython-314.pyc | Bin 2226 -> 0 bytes .../test_kibana_assets.cpython-314.pyc | Bin 13456 -> 0 bytes .../test_manifest_assets.cpython-314.pyc | Bin 3061 -> 0 bytes .../__pycache__/test_readme.cpython-314.pyc | Bin 2816 -> 0 bytes .../test_stream_configuration.cpython-314.pyc | Bin 5802 -> 0 bytes .../tests/test_changelog.py | 28 - .../tests/test_kibana_assets.py | 534 -- .../tests/test_manifest_assets.py | 40 - .../tests/test_publish_readiness.py | 65 - .../tests/test_readme.py | 65 - .../tests/test_stream_configuration.py | 230 - 144 files changed, 10594 insertions(+), 4818 deletions(-) delete mode 100644 dev/backports/gitutil/git.go delete mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_changelog.cpython-314.pyc delete mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_kibana_assets.cpython-314.pyc delete mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_manifest_assets.cpython-314.pyc delete mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_readme.cpython-314.pyc delete mode 100644 packages/tychon_quantum_command/tests/__pycache__/test_stream_configuration.cpython-314.pyc delete mode 100644 packages/tychon_quantum_command/tests/test_changelog.py delete mode 100644 packages/tychon_quantum_command/tests/test_kibana_assets.py delete mode 100644 packages/tychon_quantum_command/tests/test_manifest_assets.py delete mode 100644 packages/tychon_quantum_command/tests/test_publish_readiness.py delete mode 100644 packages/tychon_quantum_command/tests/test_readme.py delete mode 100644 packages/tychon_quantum_command/tests/test_stream_configuration.py diff --git a/.buildkite/pipeline.schedule-daily.yml b/.buildkite/pipeline.schedule-daily.yml index 287f46c5d60..122b73abc70 100644 --- a/.buildkite/pipeline.schedule-daily.yml +++ b/.buildkite/pipeline.schedule-daily.yml @@ -34,7 +34,7 @@ steps: env: SERVERLESS: "false" FORCE_CHECK_ALL: "true" - STACK_VERSION: 8.19.18-SNAPSHOT + STACK_VERSION: 8.19.19-SNAPSHOT PUBLISH_COVERAGE_REPORTS: "true" depends_on: - step: "check" @@ -48,7 +48,7 @@ steps: env: SERVERLESS: "false" FORCE_CHECK_ALL: "true" - STACK_VERSION: 8.19.18-SNAPSHOT + STACK_VERSION: 8.19.19-SNAPSHOT STACK_LOGSDB_ENABLED: "true" PUBLISH_COVERAGE_REPORTS: "false" depends_on: @@ -86,13 +86,13 @@ steps: if: | build.env('TEST_PACKAGES_BASIC_SUBSCRIPTION') == "true" - - label: "Check integrations local stacks - Stack Version v9.5" + - label: "Check integrations local stacks - Stack Version v9.6" trigger: "integrations" build: env: SERVERLESS: "false" FORCE_CHECK_ALL: "true" - STACK_VERSION: 9.5.0-SNAPSHOT + STACK_VERSION: 9.6.0-SNAPSHOT PUBLISH_COVERAGE_REPORTS: "false" depends_on: - step: "check" diff --git a/.buildkite/pipeline.schedule-weekly.yml b/.buildkite/pipeline.schedule-weekly.yml index 1833da51544..02bea3105f8 100644 --- a/.buildkite/pipeline.schedule-weekly.yml +++ b/.buildkite/pipeline.schedule-weekly.yml @@ -21,20 +21,20 @@ steps: env: SERVERLESS: "false" FORCE_CHECK_ALL: "true" - STACK_VERSION: 8.19.18-SNAPSHOT + STACK_VERSION: 8.19.19-SNAPSHOT PUBLISH_COVERAGE_REPORTS: "false" ELASTIC_PACKAGE_DISABLE_ELASTIC_AGENT_WOLFI: "true" depends_on: - step: "check" allow_failure: false - - label: "Check integrations local stacks and non-wolfi images for Elastic Agent - Stack Version v9.5" + - label: "Check integrations local stacks and non-wolfi images for Elastic Agent - Stack Version v9.6" trigger: "integrations" build: env: SERVERLESS: "false" FORCE_CHECK_ALL: "true" - STACK_VERSION: 9.5.0-SNAPSHOT + STACK_VERSION: 9.6.0-SNAPSHOT PUBLISH_COVERAGE_REPORTS: "false" ELASTIC_PACKAGE_DISABLE_ELASTIC_AGENT_WOLFI: "true" depends_on: diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 1573b5ad8f2..6e39ddd03bc 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -154,6 +154,25 @@ steps: if_changed: - "**/changelog.yml" + - label: ":busts_in_silhouette: Check backport package owners" + key: "check-backport-owners" + command: ".buildkite/scripts/check_backport_owners.sh" + soft_fail: true + agents: + image: "${LINUX_AGENT_IMAGE}" + cpu: "2" + memory: "1G" + plugins: + - elastic/vault-github-token#v0.1.0: + depends_on: + - step: "check-buildkite-scripts" + allow_failure: false + if: | + build.env('BUILDKITE_PULL_REQUEST') != "false" && + build.env('BUILDKITE_PULL_REQUEST_BASE_BRANCH') =~ /^backport-/ + if_changed: + - "packages/**" + - ".github/CODEOWNERS" - label: "Trigger integrations" key: "test-integrations" diff --git a/.buildkite/scripts/backport_branch.sh b/.buildkite/scripts/backport_branch.sh index 86a41cfe922..38073c3cef7 100755 --- a/.buildkite/scripts/backport_branch.sh +++ b/.buildkite/scripts/backport_branch.sh @@ -161,43 +161,12 @@ updateBackportBranchContents() { fi # Update scripts used by mage - local MAGEFILE_SCRIPTS_FOLDER="dev/citools" - local TESTSREPORTER_SCRIPTS_FOLDER="dev/testsreporter" - local COVERAGE_SCRIPTS_FOLDER="dev/coverage" - local CODEOWNERS_SCRIPTS_FOLDER="dev/codeowners" - local PACKAGENAMES_SCRIPTS_FOLDER="dev/packagenames" - local BACKPORTS_SCRIPTS_FOLDER="dev/backports" - local DEV_SCRIPTS_FOLDER="dev/scripts" - - if git ls-tree -d --name-only main:${MAGEFILE_SCRIPTS_FOLDER} > /dev/null 2>&1 ; then - echo "--- Copying magefile scripts from $SOURCE_BRANCH..." - echo "Copying $MAGEFILE_SCRIPTS_FOLDER from $SOURCE_BRANCH..." - git checkout "$SOURCE_BRANCH" -- "${MAGEFILE_SCRIPTS_FOLDER}" - git add "${MAGEFILE_SCRIPTS_FOLDER}" - - echo "Copying $TESTSREPORTER_SCRIPTS_FOLDER from $SOURCE_BRANCH..." - git checkout "$SOURCE_BRANCH" -- "${TESTSREPORTER_SCRIPTS_FOLDER}" - git add "${TESTSREPORTER_SCRIPTS_FOLDER}" - - echo "Copying $COVERAGE_SCRIPTS_FOLDER from $SOURCE_BRANCH..." - git checkout "$SOURCE_BRANCH" -- "${COVERAGE_SCRIPTS_FOLDER}" - git add "${COVERAGE_SCRIPTS_FOLDER}" - - echo "Copying $CODEOWNERS_SCRIPTS_FOLDER from $SOURCE_BRANCH..." - git checkout "$SOURCE_BRANCH" -- "${CODEOWNERS_SCRIPTS_FOLDER}" - git add "${CODEOWNERS_SCRIPTS_FOLDER}" - - echo "Copying $PACKAGENAMES_SCRIPTS_FOLDER from $SOURCE_BRANCH..." - git checkout "$SOURCE_BRANCH" -- "${PACKAGENAMES_SCRIPTS_FOLDER}" - git add "${PACKAGENAMES_SCRIPTS_FOLDER}" - - echo "Copying $BACKPORTS_SCRIPTS_FOLDER from $SOURCE_BRANCH..." - git checkout "$SOURCE_BRANCH" -- "${BACKPORTS_SCRIPTS_FOLDER}" - git add "${BACKPORTS_SCRIPTS_FOLDER}" - - echo "Copying $DEV_SCRIPTS_FOLDER from $SOURCE_BRANCH..." - git checkout "$SOURCE_BRANCH" -- "${DEV_SCRIPTS_FOLDER}" - git add "${DEV_SCRIPTS_FOLDER}" + local DEV_FOLDER="dev" + + if git ls-tree -d --name-only main:${DEV_FOLDER} > /dev/null 2>&1 ; then + echo "--- Copying $DEV_FOLDER from $SOURCE_BRANCH..." + git checkout "$SOURCE_BRANCH" -- "${DEV_FOLDER}" + git add "${DEV_FOLDER}" echo "Copying magefile.go from $SOURCE_BRANCH..." git checkout "$SOURCE_BRANCH" -- "magefile.go" diff --git a/.buildkite/scripts/non_package_patterns.txt b/.buildkite/scripts/non_package_patterns.txt index ab8a7c16c5f..f0dbc802594 100644 --- a/.buildkite/scripts/non_package_patterns.txt +++ b/.buildkite/scripts/non_package_patterns.txt @@ -18,12 +18,14 @@ ^\.buildkite/scripts/trigger_backport\.sh ^\.buildkite/scripts/trigger_backport_lib\.sh ^\.buildkite/scripts/build_packages\.sh +^\.buildkite/scripts/check_backport_owners\.sh ^\.buildkite/scripts/check_changelog_entries\.sh ^\.buildkite/scripts/packages/.+\.sh ^\.buildkite/scripts/requirements-ci-python-scripts\.txt ^\.buildkite/scripts/run_buildkite_scripts_tests\.sh ^\.buildkite/scripts/run_dev_scripts_tests\.sh ^\.buildkite/scripts/test_backport_branch\.sh +^\.buildkite/scripts/test_check_backport_owners\.sh ^\.buildkite/scripts/test_check_changelog_entries\.sh ^\.buildkite/scripts/test_helpers\.sh ^\.buildkite/scripts/test_non_package_patterns\.sh @@ -38,6 +40,9 @@ ^\.mergify\.yml ^catalog-info\.yaml ^dev/backports/ +^dev/codeowners/ +^dev/gitutil/ +^dev/requiresupdate/ ^dev/scripts/ ^docs/ ^CODE_OF_CONDUCT\.md diff --git a/.buildkite/scripts/run_buildkite_scripts_tests.sh b/.buildkite/scripts/run_buildkite_scripts_tests.sh index 6f32e5fa37e..4a5e2c27b80 100755 --- a/.buildkite/scripts/run_buildkite_scripts_tests.sh +++ b/.buildkite/scripts/run_buildkite_scripts_tests.sh @@ -45,6 +45,10 @@ echo "" echo "=== Running check_changelog_entries.sh tests ===" run_tests_if_exists "${REPO_ROOT}/.buildkite/scripts/test_check_changelog_entries.sh" +echo "" +echo "=== Running check_backport_owners.sh tests ===" +run_tests_if_exists "${REPO_ROOT}/.buildkite/scripts/test_check_backport_owners.sh" + echo "" echo "=== Running trigger_backport_lib.sh tests ===" # yq is required by generate_trigger_pipeline(); install it if not already available. diff --git a/.buildkite/scripts/test_non_package_patterns.sh b/.buildkite/scripts/test_non_package_patterns.sh index c47593f3f60..9487d0616cc 100755 --- a/.buildkite/scripts/test_non_package_patterns.sh +++ b/.buildkite/scripts/test_non_package_patterns.sh @@ -45,6 +45,7 @@ NON_PACKAGE_PATHS=( ".buildkite/scripts/trigger_backport.sh" ".buildkite/scripts/trigger_backport_lib.sh" ".buildkite/scripts/build_packages.sh" + ".buildkite/scripts/check_backport_owners.sh" ".buildkite/scripts/check_changelog_entries.sh" ".buildkite/scripts/packages/aws.sh" ".buildkite/scripts/packages/nginx.sh" @@ -52,6 +53,7 @@ NON_PACKAGE_PATHS=( ".buildkite/scripts/run_buildkite_scripts_tests.sh" ".buildkite/scripts/run_dev_scripts_tests.sh" ".buildkite/scripts/test_backport_branch.sh" + ".buildkite/scripts/test_check_backport_owners.sh" ".buildkite/scripts/test_check_changelog_entries.sh" ".buildkite/scripts/test_helpers.sh" ".buildkite/scripts/test_non_package_patterns.sh" @@ -66,6 +68,9 @@ NON_PACKAGE_PATHS=( ".mergify.yml" "catalog-info.yaml" "dev/backports/some_script.sh" + "dev/codeowners/codeowners.go" + "dev/gitutil/git.go" + "dev/requiresupdate/requiresupdate.go" "dev/scripts/foo.sh" "docs/extend/developer-workflow.md" "docs/some/nested/page.md" diff --git a/.github/workflows/pr-buildkite-detective.yml b/.github/workflows/pr-buildkite-detective.yml index 47078c56a4d..1bf14f3688a 100644 --- a/.github/workflows/pr-buildkite-detective.yml +++ b/.github/workflows/pr-buildkite-detective.yml @@ -10,10 +10,30 @@ permissions: pull-requests: write # required by gh-aw compiler for add-comment jobs: - run: + check-pr: if: >- github.event.state == 'failure' && contains(github.event.context, 'buildkite') + runs-on: ubuntu-latest + outputs: + has-open-pr: ${{ steps.find-pr.outputs.has-open-pr }} + steps: + - name: Check for open PR associated with commit + id: find-pr + env: + GH_TOKEN: ${{ github.token }} + run: | + count=$(gh api "repos/${{ github.repository }}/commits/${{ github.event.sha }}/pulls" \ + --jq '[.[] | select(.state == "open")] | length') + if [ "$count" -gt 0 ]; then + echo "has-open-pr=true" >> "$GITHUB_OUTPUT" + else + echo "has-open-pr=false" >> "$GITHUB_OUTPUT" + fi + + run: + needs: check-pr + if: needs.check-pr.outputs.has-open-pr == 'true' uses: elastic/ai-github-actions/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml@v0 secrets: BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_LOGS_API_TOKEN }} diff --git a/dev/backports/apply/apply.go b/dev/backports/apply/apply.go index f28d9c98a06..228750be9bd 100644 --- a/dev/backports/apply/apply.go +++ b/dev/backports/apply/apply.go @@ -8,6 +8,7 @@ import ( "bytes" "errors" "fmt" + "maps" "os" "path/filepath" "regexp" @@ -21,10 +22,19 @@ import ( "github.com/elastic/integrations/dev/backports" "github.com/elastic/integrations/dev/backports/changelog" - "github.com/elastic/integrations/dev/backports/gitutil" + "github.com/elastic/integrations/dev/backports/owners" "github.com/elastic/integrations/dev/citools" + "github.com/elastic/integrations/dev/codeowners" + "github.com/elastic/integrations/dev/gitutil" ) +// ownersSourceBranch is the ownership source of truth for syncOwners — main +// is always authoritative. A named constant (not an env var or Options +// field) purely so the value lives in one place, easy to tweak here for +// local debugging/testing; check_backport_owners.sh keeps its own identical +// constant since the two run in separate processes. +const ownersSourceBranch = "main" + // Options controls the behaviour of Apply. type Options struct { SHA string // commit to cherry-pick (required) @@ -49,6 +59,7 @@ type Result struct { PRURL string `json:"pr_url,omitempty"` ConflictingFiles []string `json:"conflicting_files,omitempty"` SuggestedCommand string `json:"suggested_command,omitempty"` + OwnerSyncWarning string `json:"owner_sync_warning,omitempty"` // non-empty when owner sync was skipped } // branchRE matches valid backport branch names (mirrors dev/backports/inventory.go). @@ -156,14 +167,17 @@ func Apply(opts Options) (*Result, error) { return nil, err } + ownerSyncWarning := a.syncOwners(remote, ownersSourceBranch, opts.Package, pkgDir) + if opts.DryRun { success = true return &Result{ - Status: "success", - SHA: opts.SHA, - TargetBranch: branchName, - NewVersion: newVersion, - WorkingBranch: workingBranch, + Status: "success", + SHA: opts.SHA, + TargetBranch: branchName, + NewVersion: newVersion, + WorkingBranch: workingBranch, + OwnerSyncWarning: ownerSyncWarning, }, nil } @@ -178,11 +192,12 @@ func Apply(opts Options) (*Result, error) { success = true return &Result{ - Status: "success", - SHA: opts.SHA, - TargetBranch: branchName, - NewVersion: newVersion, - PRURL: prURL, + Status: "success", + SHA: opts.SHA, + TargetBranch: branchName, + NewVersion: newVersion, + PRURL: prURL, + OwnerSyncWarning: ownerSyncWarning, }, nil } @@ -550,6 +565,176 @@ func (a applier) commitChanges(pkgDir, sha, newVersion string) error { return nil } +// syncOwners brings pkgDir's manifest.yml owner and CODEOWNERS entries in +// line with sourceBranch's, as its own commit on top of the cherry-pick. It is +// best-effort: any failure reading or parsing sourceBranch's state (fetch +// failure, unparsable manifest, missing CODEOWNERS) is returned as a warning +// string (and printed to stderr for human-mode callers) rather than failing the +// whole backport. The CI check on PRs targeting backport-* branches +// (elastic/integrations#19686) is the actual enforcement mechanism; this is a +// convenience that keeps most backport PRs correct without it. +// Returns "" on success or no-op, or a non-empty warning message when skipped. +func (a applier) syncOwners(remote, sourceBranch, pkg, pkgDir string) string { + warn := func(format string, args ...any) string { + msg := fmt.Sprintf(format, args...) + fmt.Fprintf(os.Stderr, "warning: %s\n", msg) + return msg + } + + plan, pkgPath, err := a.computeOwnerSyncPlan(remote, sourceBranch, pkgDir) + if err != nil { + return warn("skipping owner sync for %s: %v", pkg, err) + } + if plan.Empty() { + return "" + } + + manifestPath := filepath.Join(pkgDir, "manifest.yml") + codeownersPath := filepath.Join(a.workDir, codeowners.DefaultCodeownersPath) + rollback := func() { + if rbErr := a.git.Run("checkout", "--", manifestPath, codeownersPath); rbErr != nil { + fmt.Fprintf(os.Stderr, "warning: could not restore files after owner sync failure for %s: %v\n", pkg, rbErr) + } + } + + if err := writeOwnerSyncPlan(a.workDir, pkgDir, pkgPath, plan); err != nil { + rollback() + return warn("skipping owner sync for %s: %v", pkg, err) + } + if err := a.commitOwnerSync(pkg, manifestPath); err != nil { + rollback() + return warn("committing owner sync for %s: %v", pkg, err) + } + return "" +} + +// computeOwnerSyncPlan fetches remote/sourceBranch and compares pkgDir's +// current CODEOWNERS/manifest.yml owner against sourceBranch's, returning the +// changes needed (if any) and pkgDir's CODEOWNERS path (e.g. +// "/packages/aws"). A found-false result from owners.Plan (e.g. the package +// no longer exists on sourceBranch) is reported as an empty, no-error plan: +// it's a normal skip, not a failure. +// +// This fetch is a second network round-trip on top of the backport-branch +// fetch already done in prepareWorkingBranch. It is intentional: ownership +// comparison requires a current view of sourceBranch — a cached remote ref +// could be arbitrarily stale — and there is no safe way to skip it. +func (a applier) computeOwnerSyncPlan(remote, sourceBranch, pkgDir string) (plan owners.SyncPlan, pkgPath string, err error) { + if err := a.git.Run("fetch", remote, sourceBranch); err != nil { + return owners.SyncPlan{}, "", fmt.Errorf("fetching %s: %w", sourceBranch, err) + } + remoteRef := remote + "/" + sourceBranch + + relPkgDir, err := filepath.Rel(a.workDir, pkgDir) + if err != nil { + return owners.SyncPlan{}, "", fmt.Errorf("resolving package path: %w", err) + } + relPkgDir = filepath.ToSlash(relPkgDir) + pkgPath = "/" + relPkgDir + + syncPlan, found, err := owners.Compare(a.git, a.workDir, pkgDir, relPkgDir, remoteRef) + if err != nil { + return owners.SyncPlan{}, "", err + } + if !found { + return owners.SyncPlan{}, pkgPath, nil + } + return syncPlan, pkgPath, nil +} + +// writeOwnerSyncPlan applies plan's changes to pkgDir/manifest.yml and +// workDir/.github/CODEOWNERS. +func writeOwnerSyncPlan(workDir, pkgDir, pkgPath string, plan owners.SyncPlan) error { + if plan.ManifestOwner != "" { + if err := setManifestOwner(filepath.Join(pkgDir, "manifest.yml"), plan.ManifestOwner); err != nil { + return fmt.Errorf("updating manifest owner: %w", err) + } + } + + updates := make(map[string][]string, len(plan.SubPaths)+1) + if plan.PackageOwner != nil { + updates[pkgPath] = plan.PackageOwner + } + maps.Copy(updates, plan.SubPaths) + if len(updates) == 0 { + return nil + } + + codeownersPath := filepath.Join(workDir, codeowners.DefaultCodeownersPath) + data, err := os.ReadFile(codeownersPath) + if err != nil { + return fmt.Errorf("reading %s: %w", codeowners.DefaultCodeownersPath, err) + } + info, err := os.Stat(codeownersPath) + if err != nil { + return err + } + + updated := owners.ApplyUpdates(string(data), updates, pkgPath) + if err := os.WriteFile(codeownersPath, []byte(updated), info.Mode()); err != nil { + return fmt.Errorf("writing %s: %w", codeowners.DefaultCodeownersPath, err) + } + return nil +} + +// setManifestOwner rewrites the "github:" line inside manifest.yml's "owner:" +// block to newOwner, preserving the rest of the file's formatting. +func setManifestOwner(manifestPath, newOwner string) error { + data, err := os.ReadFile(manifestPath) + if err != nil { + return fmt.Errorf("reading %s: %w", manifestPath, err) + } + info, err := os.Stat(manifestPath) + if err != nil { + return err + } + + lines := bytes.Split(data, []byte("\n")) + ownerIdx := slices.IndexFunc(lines, func(l []byte) bool { + return bytes.HasPrefix(l, []byte("owner:")) + }) + if ownerIdx == -1 { + return fmt.Errorf("owner block not found in %s", manifestPath) + } + + githubIdx := -1 + for i := ownerIdx + 1; i < len(lines); i++ { + if len(lines[i]) > 0 && lines[i][0] != ' ' && lines[i][0] != '\t' { + break // left the owner block + } + // TrimLeft drops the indentation so the prefix check matches the key + // itself, not a comment mentioning "github:" further into the line. + if bytes.HasPrefix(bytes.TrimLeft(lines[i], " \t"), []byte("github:")) { + githubIdx = i + break + } + } + if githubIdx == -1 { + return fmt.Errorf("owner.github line not found in %s", manifestPath) + } + + prefixEnd := bytes.Index(lines[githubIdx], []byte("github:")) + len("github:") + lines[githubIdx] = append(append([]byte{}, lines[githubIdx][:prefixEnd]...), []byte(" "+newOwner)...) + + updated := bytes.Join(lines, []byte("\n")) + return os.WriteFile(manifestPath, updated, info.Mode()) +} + +// commitOwnerSync stages manifest.yml and CODEOWNERS and commits them +// separately from the cherry-pick commit. +func (a applier) commitOwnerSync(pkg, manifestPath string) error { + if err := a.git.Run("add", manifestPath); err != nil { + return fmt.Errorf("staging manifest.yml: %w", err) + } + if err := a.git.Run("add", filepath.Join(a.workDir, codeowners.DefaultCodeownersPath)); err != nil { + return fmt.Errorf("staging CODEOWNERS: %w", err) + } + if err := a.git.Run("commit", "-m", fmt.Sprintf("Sync %s package owners from main", pkg)); err != nil { + return fmt.Errorf("committing owner sync: %w", err) + } + return nil +} + // conflictingFiles returns files in a conflict state after a failed cherry-pick. func (a applier) conflictingFiles() ([]string, error) { out, err := a.git.Output("status", "--porcelain") diff --git a/dev/backports/apply/apply_integration_test.go b/dev/backports/apply/apply_integration_test.go index d53b85c6dce..5224321854f 100644 --- a/dev/backports/apply/apply_integration_test.go +++ b/dev/backports/apply/apply_integration_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/elastic/integrations/dev/backports/gitutil" + "github.com/elastic/integrations/dev/gitutil" ) // setupIntegrationRepo creates a bare remote and a local clone pre-populated @@ -568,6 +568,376 @@ func TestApplyIntegration_ReportsConflictWhenManifestMissingBeforeCherryPick(t * assert.Empty(t, strings.TrimSpace(branches)) } +// setupIntegrationRepoWithOwnerDrift is like setupIntegrationRepo, but adds +// a .github/CODEOWNERS entry and a manifest.yml owner.github field for the +// kubernetes package, then changes both on main — after the backport branch +// was cut, but independently of the fix commit being cherry-picked — to +// model ownership changing hands on main over a branch's lifetime. +func setupIntegrationRepoWithOwnerDrift(t *testing.T) (workDir, fixSHA string) { + t.Helper() + + run := func(dir string, args ...string) string { + t.Helper() + cmd := exec.Command("git", args...) + cmd.Dir = dir + out, err := cmd.CombinedOutput() + require.NoError(t, err, "git %v: %s", args, out) + return strings.TrimRight(string(out), "\n") + } + + remoteDir := t.TempDir() + run(remoteDir, "init", "--bare", "-q") + + workDir = t.TempDir() + run(workDir, "clone", "-q", remoteDir, ".") + run(workDir, "config", "user.email", "test@test.com") + run(workDir, "config", "user.name", "Test") + run(workDir, "config", "commit.gpgsign", "false") + + pkgDir := filepath.Join(workDir, "packages", "kubernetes") + require.NoError(t, os.MkdirAll(pkgDir, 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(workDir, ".github"), 0o755)) + + write := func(rel, content string) { + t.Helper() + require.NoError(t, os.WriteFile(filepath.Join(workDir, rel), []byte(content), 0o644)) + } + + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.0\nowner:\n github: elastic/obs-old-team\n") + write("packages/kubernetes/changelog.yml", "- version: \"1.0.0\"\n"+ + " changes:\n"+ + " - description: Initial release.\n"+ + " type: enhancement\n"+ + " link: https://github.com/elastic/integrations/pull/1\n") + write(".github/CODEOWNERS", "/packages/kubernetes @elastic/obs-old-team\n") + + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Initial release") + baseCommit := run(workDir, "rev-parse", "--short=10", "HEAD") + + write(".backports.yml", "backports:\n"+ + " - package: kubernetes\n"+ + " branch: backport-kubernetes-1.x\n"+ + " base_version: \"1.0.0\"\n"+ + " base_commit: \""+baseCommit+"\"\n"+ + " maintained_until: null\n"+ + " archived: false\n"+ + " remove_other_packages: false\n") + + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Add backports config") + run(workDir, "push", "-q", "origin", "HEAD:main") + + // Create the backport branch here — ownership still matches main. + run(workDir, "checkout", "-q", "-b", "backport-kubernetes-1.x") + run(workDir, "push", "-q", "origin", "backport-kubernetes-1.x") + run(workDir, "checkout", "-q", "main") + + // Ownership changes hands on main, unrelated to the upcoming fix commit. + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.0\nowner:\n github: elastic/obs-new-team\n") + write(".github/CODEOWNERS", "/packages/kubernetes @elastic/obs-new-team\n") + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Reassign kubernetes ownership") + + // The fix commit to cherry-pick — a normal bugfix, unrelated to ownership. + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.1\nowner:\n github: elastic/obs-new-team\n") + write("packages/kubernetes/changelog.yml", "- version: \"1.0.1\"\n"+ + " changes:\n"+ + " - description: Fix timeout in metrics collection.\n"+ + " type: bugfix\n"+ + " link: https://github.com/elastic/integrations/pull/999\n"+ + "- version: \"1.0.0\"\n"+ + " changes:\n"+ + " - description: Initial release.\n"+ + " type: enhancement\n"+ + " link: https://github.com/elastic/integrations/pull/1\n") + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Fix timeout in metrics collection") + fixSHA = run(workDir, "rev-parse", "HEAD") + run(workDir, "push", "-q", "origin", "HEAD:main") + run(workDir, "checkout", "-q", "main") + + return workDir, fixSHA +} + +func TestApplyIntegration_SyncsOwnersFromMain(t *testing.T) { + workDir, fixSHA := setupIntegrationRepoWithOwnerDrift(t) + + result, err := Apply(Options{ + SHA: fixSHA, + Package: "kubernetes", + Target: "backport-kubernetes-1.x", + Remote: "origin", + DryRun: true, + PackagesDir: "packages", + Repository: "elastic/integrations", + WorkDir: workDir, + }) + require.NoError(t, err) + require.NotNil(t, result) + assert.Equal(t, "success", result.Status) + + // The backport branch's manifest owner and CODEOWNERS entry must now match + // main's current owner, even though the cherry-picked fix commit itself + // never touched ownership. + manifestData, err := os.ReadFile(filepath.Join(workDir, "packages", "kubernetes", "manifest.yml")) + require.NoError(t, err) + assert.Contains(t, string(manifestData), "github: elastic/obs-new-team") + + codeownersData, err := os.ReadFile(filepath.Join(workDir, ".github", "CODEOWNERS")) + require.NoError(t, err) + assert.Contains(t, string(codeownersData), "/packages/kubernetes @elastic/obs-new-team") + + // The owner sync must be its own commit, separate from the cherry-pick + // commit, so both are clearly attributable in review — and it must have + // been created before the (skipped, DryRun) push, i.e. it's visible in the + // local log immediately. + subjects, err := gitutil.Git{Dir: workDir}.Output("log", "--format=%s", "-n", "2") + require.NoError(t, err) + lines := strings.Split(strings.TrimSpace(subjects), "\n") + require.Len(t, lines, 2) + assert.Contains(t, lines[0], "owner") + assert.Contains(t, lines[1], "Fix timeout in metrics collection") +} + +// setupIntegrationRepoWithMatchingOwners is like +// setupIntegrationRepoWithOwnerDrift, but ownership never changes on main — +// the backport branch and main agree throughout. This models the common case +// where sync has nothing to do. +func setupIntegrationRepoWithMatchingOwners(t *testing.T) (workDir, fixSHA string) { + t.Helper() + + run := func(dir string, args ...string) string { + t.Helper() + cmd := exec.Command("git", args...) + cmd.Dir = dir + out, err := cmd.CombinedOutput() + require.NoError(t, err, "git %v: %s", args, out) + return strings.TrimRight(string(out), "\n") + } + + remoteDir := t.TempDir() + run(remoteDir, "init", "--bare", "-q") + + workDir = t.TempDir() + run(workDir, "clone", "-q", remoteDir, ".") + run(workDir, "config", "user.email", "test@test.com") + run(workDir, "config", "user.name", "Test") + run(workDir, "config", "commit.gpgsign", "false") + + pkgDir := filepath.Join(workDir, "packages", "kubernetes") + require.NoError(t, os.MkdirAll(pkgDir, 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(workDir, ".github"), 0o755)) + + write := func(rel, content string) { + t.Helper() + require.NoError(t, os.WriteFile(filepath.Join(workDir, rel), []byte(content), 0o644)) + } + + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.0\nowner:\n github: elastic/obs-team\n") + write("packages/kubernetes/changelog.yml", "- version: \"1.0.0\"\n"+ + " changes:\n"+ + " - description: Initial release.\n"+ + " type: enhancement\n"+ + " link: https://github.com/elastic/integrations/pull/1\n") + write(".github/CODEOWNERS", "/packages/kubernetes @elastic/obs-team\n") + + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Initial release") + baseCommit := run(workDir, "rev-parse", "--short=10", "HEAD") + + write(".backports.yml", "backports:\n"+ + " - package: kubernetes\n"+ + " branch: backport-kubernetes-1.x\n"+ + " base_version: \"1.0.0\"\n"+ + " base_commit: \""+baseCommit+"\"\n"+ + " maintained_until: null\n"+ + " archived: false\n"+ + " remove_other_packages: false\n") + + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Add backports config") + run(workDir, "push", "-q", "origin", "HEAD:main") + + run(workDir, "checkout", "-q", "-b", "backport-kubernetes-1.x") + run(workDir, "push", "-q", "origin", "backport-kubernetes-1.x") + run(workDir, "checkout", "-q", "main") + + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.1\nowner:\n github: elastic/obs-team\n") + write("packages/kubernetes/changelog.yml", "- version: \"1.0.1\"\n"+ + " changes:\n"+ + " - description: Fix timeout in metrics collection.\n"+ + " type: bugfix\n"+ + " link: https://github.com/elastic/integrations/pull/999\n"+ + "- version: \"1.0.0\"\n"+ + " changes:\n"+ + " - description: Initial release.\n"+ + " type: enhancement\n"+ + " link: https://github.com/elastic/integrations/pull/1\n") + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Fix timeout in metrics collection") + fixSHA = run(workDir, "rev-parse", "HEAD") + run(workDir, "push", "-q", "origin", "HEAD:main") + run(workDir, "checkout", "-q", "main") + + return workDir, fixSHA +} + +func TestApplyIntegration_SkipsOwnerSyncCommitWhenOwnersMatch(t *testing.T) { + workDir, fixSHA := setupIntegrationRepoWithMatchingOwners(t) + + result, err := Apply(Options{ + SHA: fixSHA, + Package: "kubernetes", + Target: "backport-kubernetes-1.x", + Remote: "origin", + DryRun: true, + PackagesDir: "packages", + Repository: "elastic/integrations", + WorkDir: workDir, + }) + require.NoError(t, err) + require.NotNil(t, result) + assert.Equal(t, "success", result.Status) + + // No owner drift, so no separate sync commit — only the cherry-pick commit. + subjects, err := gitutil.Git{Dir: workDir}.Output("log", "--format=%s", "-n", "2") + require.NoError(t, err) + lines := strings.Split(strings.TrimSpace(subjects), "\n") + require.Len(t, lines, 2) + assert.Contains(t, lines[0], "Fix timeout in metrics collection") + assert.NotContains(t, lines[0], "owner") + assert.Contains(t, lines[1], "Add backports config") +} + +// setupIntegrationRepoWithUnreadableMainOwner is like +// setupIntegrationRepoWithMatchingOwners, but main clears its manifest.yml +// owner.github value (to "") in a commit ahead of the branch, unrelated to +// the fix commit. The owner.github line itself is present throughout, on +// both sides, and only its value changes — the same clean, value-only-change +// shape as setupIntegrationRepoWithOwnerDrift, so the cherry-pick merges +// without conflict (see the two 3-way-merge cases side by side: a line +// theirs never touches always keeps ours' value, no matter how different +// ours is from base — only a *structural* add/remove adjacent to a line +// theirs does touch is conflict-prone, which this deliberately avoids). This +// models a sync failure that isn't "package removed from main" (which Plan +// already handles by skipping cleanly) but a genuine parse/read failure on +// main's side: an empty owner.github is invalid, not merely absent. +func setupIntegrationRepoWithUnreadableMainOwner(t *testing.T) (workDir, fixSHA string) { + t.Helper() + + run := func(dir string, args ...string) string { + t.Helper() + cmd := exec.Command("git", args...) + cmd.Dir = dir + out, err := cmd.CombinedOutput() + require.NoError(t, err, "git %v: %s", args, out) + return strings.TrimRight(string(out), "\n") + } + + remoteDir := t.TempDir() + run(remoteDir, "init", "--bare", "-q") + + workDir = t.TempDir() + run(workDir, "clone", "-q", remoteDir, ".") + run(workDir, "config", "user.email", "test@test.com") + run(workDir, "config", "user.name", "Test") + run(workDir, "config", "commit.gpgsign", "false") + + pkgDir := filepath.Join(workDir, "packages", "kubernetes") + require.NoError(t, os.MkdirAll(pkgDir, 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(workDir, ".github"), 0o755)) + + write := func(rel, content string) { + t.Helper() + require.NoError(t, os.WriteFile(filepath.Join(workDir, rel), []byte(content), 0o644)) + } + + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.0\nowner:\n github: elastic/obs-team\n") + write("packages/kubernetes/changelog.yml", "- version: \"1.0.0\"\n"+ + " changes:\n"+ + " - description: Initial release.\n"+ + " type: enhancement\n"+ + " link: https://github.com/elastic/integrations/pull/1\n") + write(".github/CODEOWNERS", "/packages/kubernetes @elastic/obs-team\n") + + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Initial release") + baseCommit := run(workDir, "rev-parse", "--short=10", "HEAD") + + write(".backports.yml", "backports:\n"+ + " - package: kubernetes\n"+ + " branch: backport-kubernetes-1.x\n"+ + " base_version: \"1.0.0\"\n"+ + " base_commit: \""+baseCommit+"\"\n"+ + " maintained_until: null\n"+ + " archived: false\n"+ + " remove_other_packages: false\n") + + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Add backports config") + run(workDir, "push", "-q", "origin", "HEAD:main") + + run(workDir, "checkout", "-q", "-b", "backport-kubernetes-1.x") + run(workDir, "push", "-q", "origin", "backport-kubernetes-1.x") + run(workDir, "checkout", "-q", "main") + + // Main clears the owner value (not the line itself) — unrelated to the fix. + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.0\nowner:\n github: \"\"\n") + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Clear kubernetes owner") + + write("packages/kubernetes/manifest.yml", "format_version: \"3.0.0\"\nname: kubernetes\ntype: integration\nversion: 1.0.1\nowner:\n github: \"\"\n") + write("packages/kubernetes/changelog.yml", "- version: \"1.0.1\"\n"+ + " changes:\n"+ + " - description: Fix timeout in metrics collection.\n"+ + " type: bugfix\n"+ + " link: https://github.com/elastic/integrations/pull/999\n"+ + "- version: \"1.0.0\"\n"+ + " changes:\n"+ + " - description: Initial release.\n"+ + " type: enhancement\n"+ + " link: https://github.com/elastic/integrations/pull/1\n") + run(workDir, "add", ".") + run(workDir, "commit", "-q", "-m", "Fix timeout in metrics collection") + fixSHA = run(workDir, "rev-parse", "HEAD") + run(workDir, "push", "-q", "origin", "HEAD:main") + run(workDir, "checkout", "-q", "main") + + return workDir, fixSHA +} + +func TestApplyIntegration_ContinuesWhenMainOwnerUnreadable(t *testing.T) { + workDir, fixSHA := setupIntegrationRepoWithUnreadableMainOwner(t) + + result, err := Apply(Options{ + SHA: fixSHA, + Package: "kubernetes", + Target: "backport-kubernetes-1.x", + Remote: "origin", + DryRun: true, + PackagesDir: "packages", + Repository: "elastic/integrations", + WorkDir: workDir, + }) + require.NoError(t, err, "a best-effort sync failure must not fail the whole backport") + require.NotNil(t, result) + assert.Equal(t, "success", result.Status) + + // No sync commit was possible, so the branch's own owner is left as-is — + // and there must be no second commit at all. + manifestData, err := os.ReadFile(filepath.Join(workDir, "packages", "kubernetes", "manifest.yml")) + require.NoError(t, err) + assert.Contains(t, string(manifestData), "github: elastic/obs-team") + + subjects, err := gitutil.Git{Dir: workDir}.Output("log", "--format=%s", "-n", "2") + require.NoError(t, err) + lines := strings.Split(strings.TrimSpace(subjects), "\n") + require.Len(t, lines, 2) + assert.Contains(t, lines[0], "Fix timeout in metrics collection") + assert.Contains(t, lines[1], "Add backports config") +} + func TestApplyIntegration_DryRun(t *testing.T) { workDir, fixSHA := setupIntegrationRepo(t) diff --git a/dev/backports/apply/apply_test.go b/dev/backports/apply/apply_test.go index 459047f591f..4c14872b87e 100644 --- a/dev/backports/apply/apply_test.go +++ b/dev/backports/apply/apply_test.go @@ -11,6 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/elastic/integrations/dev/backports/owners" ) func TestResolveBranchName(t *testing.T) { @@ -309,6 +311,123 @@ func TestSetManifestVersion(t *testing.T) { } } +func TestSetManifestOwner(t *testing.T) { + tests := []struct { + name string + content string + newOwner string + wantContent string + wantErr bool + }{ + { + name: "basic replace", + content: "name: aws\nversion: 6.14.2\nowner:\n github: elastic/obs-old-team\n", + newOwner: "elastic/obs-new-team", + wantContent: "name: aws\nversion: 6.14.2\nowner:\n github: elastic/obs-new-team\n", + }, + { + // The whole point of a targeted line rewrite (mirroring + // setManifestVersion) is that every other field — before the + // owner block, and the sibling "type:" field inside it — must + // survive byte-for-byte, not just "look similar". + name: "preserves rest of file, including sibling owner.type field", + content: "format_version: \"3.0.0\"\nname: aws\ntype: integration\nversion: 6.14.2\n" + + "owner:\n github: elastic/obs-old-team\n type: elastic\ndescription: An integration.\n", + newOwner: "elastic/obs-new-team", + wantContent: "format_version: \"3.0.0\"\nname: aws\ntype: integration\nversion: 6.14.2\n" + + "owner:\n github: elastic/obs-new-team\n type: elastic\ndescription: An integration.\n", + }, + { + name: "missing owner block", + content: "name: aws\nversion: 6.14.2\n", + wantErr: true, + }, + { + name: "owner block without a github field", + content: "name: aws\nversion: 6.14.2\nowner:\n type: elastic\n", + wantErr: true, + }, + { + // A comment mentioning "github:" ahead of the real field must not + // be mistaken for it — the match has to be anchored to the key, + // not just look for the substring anywhere on the line. + name: "ignores a comment mentioning github: before the real field", + content: "name: aws\nversion: 6.14.2\nowner:\n # see github: https://example.com/teams\n github: elastic/obs-old-team\n", + newOwner: "elastic/obs-new-team", + wantContent: "name: aws\nversion: 6.14.2\nowner:\n # see github: https://example.com/teams\n github: elastic/obs-new-team\n", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + path := filepath.Join(t.TempDir(), "manifest.yml") + require.NoError(t, os.WriteFile(path, []byte(tc.content), 0o644)) + + err := setManifestOwner(path, tc.newOwner) + if tc.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + updated, err := os.ReadFile(path) + require.NoError(t, err) + assert.Equal(t, tc.wantContent, string(updated)) + }) + } +} + +// The CODEOWNERS-rewriting logic itself is tested directly in +// dev/backports/owners (owners.ApplyUpdates) — writeOwnerSyncPlan is a thin +// file-I/O wrapper around it plus setManifestOwner, tested here. +func TestWriteOwnerSyncPlan(t *testing.T) { + workDir := t.TempDir() + pkgDir := filepath.Join(workDir, "packages", "aws") + require.NoError(t, os.MkdirAll(filepath.Join(workDir, ".github"), 0o755)) + require.NoError(t, os.MkdirAll(pkgDir, 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(workDir, ".github", "CODEOWNERS"), + []byte("/packages/aws @elastic/obs-old-team\n"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(pkgDir, "manifest.yml"), + []byte("name: aws\nowner:\n github: elastic/obs-old-team\n"), 0o644)) + + plan := owners.SyncPlan{ + ManifestOwner: "elastic/obs-new-team", + PackageOwner: []string{"@elastic/obs-new-team"}, + SubPaths: map[string][]string{ + "/packages/aws/data_stream/cloudtrail": {"@elastic/security-team"}, + }, + } + + require.NoError(t, writeOwnerSyncPlan(workDir, pkgDir, "/packages/aws", plan)) + + manifestData, err := os.ReadFile(filepath.Join(pkgDir, "manifest.yml")) + require.NoError(t, err) + assert.Contains(t, string(manifestData), "github: elastic/obs-new-team") + + codeownersData, err := os.ReadFile(filepath.Join(workDir, ".github", "CODEOWNERS")) + require.NoError(t, err) + assert.Equal(t, + "/packages/aws @elastic/obs-new-team\n/packages/aws/data_stream/cloudtrail @elastic/security-team\n", + string(codeownersData)) +} + +func TestWriteOwnerSyncPlan_SkipsCodeownersWhenPlanHasNoCodeownersChanges(t *testing.T) { + workDir := t.TempDir() + pkgDir := filepath.Join(workDir, "packages", "aws") + require.NoError(t, os.MkdirAll(pkgDir, 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(pkgDir, "manifest.yml"), + []byte("name: aws\nowner:\n github: elastic/obs-old-team\n"), 0o644)) + + // No .github/CODEOWNERS file exists at all — writeOwnerSyncPlan must not + // try to read/write it when the plan has no PackageOwner/SubPaths changes. + plan := owners.SyncPlan{ManifestOwner: "elastic/obs-new-team"} + + require.NoError(t, writeOwnerSyncPlan(workDir, pkgDir, "/packages/aws", plan)) + + manifestData, err := os.ReadFile(filepath.Join(pkgDir, "manifest.yml")) + require.NoError(t, err) + assert.Contains(t, string(manifestData), "github: elastic/obs-new-team") +} + func TestParseEntryFields(t *testing.T) { tests := []struct { name string diff --git a/dev/backports/changelog/collect.go b/dev/backports/changelog/collect.go index 4e23a44761d..e9284b87856 100644 --- a/dev/backports/changelog/collect.go +++ b/dev/backports/changelog/collect.go @@ -13,8 +13,8 @@ import ( "github.com/cli/go-gh/v2" - "github.com/elastic/integrations/dev/backports/gitutil" "github.com/elastic/integrations/dev/citools" + "github.com/elastic/integrations/dev/gitutil" ) // CollectResult holds the outputs produced by Collect. diff --git a/dev/backports/changelog/sync.go b/dev/backports/changelog/sync.go index cf5be4f15c9..d6539d5b607 100644 --- a/dev/backports/changelog/sync.go +++ b/dev/backports/changelog/sync.go @@ -13,7 +13,7 @@ import ( "github.com/cli/go-gh/v2" - "github.com/elastic/integrations/dev/backports/gitutil" + "github.com/elastic/integrations/dev/gitutil" ) // SyncResult holds outputs produced by CreateSyncPR. diff --git a/dev/backports/gitutil/git.go b/dev/backports/gitutil/git.go deleted file mode 100644 index e716d0540d6..00000000000 --- a/dev/backports/gitutil/git.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package gitutil - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "strings" -) - -// Git runs git commands in Dir. An empty Dir means the current working directory. -type Git struct{ Dir string } - -// Run runs a git command forwarding stdout and stderr to the terminal. -func (g Git) Run(args ...string) error { - cmd := exec.Command("git", args...) - cmd.Dir = g.Dir - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() -} - -// Output runs a git command and returns its stdout as a string. -// On failure the returned error includes git's stderr output. -func (g Git) Output(args ...string) (string, error) { - var stderr bytes.Buffer - cmd := exec.Command("git", args...) - cmd.Dir = g.Dir - cmd.Stderr = &stderr - out, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("%w: %s", err, strings.TrimSpace(stderr.String())) - } - return string(out), nil -} diff --git a/dev/citools/packagemanifest.go b/dev/citools/packagemanifest.go index 7858733a442..95e1a45c90d 100644 --- a/dev/citools/packagemanifest.go +++ b/dev/citools/packagemanifest.go @@ -6,6 +6,7 @@ package citools import ( "fmt" + "os" "github.com/elastic/go-ucfg" "github.com/elastic/go-ucfg/yaml" @@ -27,29 +28,65 @@ type conditions struct { Elastic elasticConditions `config:"elastic" json:"elastic" yaml:"elastic"` } +type requiresEntry struct { + Package string `config:"package" json:"package" yaml:"package"` + Version string `config:"version" json:"version" yaml:"version"` +} + +type requiresBlock struct { + Input []requiresEntry `config:"input" json:"input" yaml:"input"` + Content []requiresEntry `config:"content" json:"content" yaml:"content"` +} + +// owner identifies the GitHub owner of a package, as recorded in its manifest.yml. +type owner struct { + Github string `config:"github" json:"github" yaml:"github"` +} + type packageManifest struct { - FormatVersion string `config:"format_version" json:"format_version" yaml:"format_version"` - Name string `config:"name" json:"name" yaml:"name"` - Type string `config:"type" json:"type" yaml:"type"` - Version string `config:"version" json:"version" yaml:"version"` - License string `config:"license" json:"license" yaml:"license"` - Conditions conditions `config:"conditions" json:"conditions" yaml:"conditions"` + FormatVersion string `config:"format_version" json:"format_version" yaml:"format_version"` + Name string `config:"name" json:"name" yaml:"name"` + Type string `config:"type" json:"type" yaml:"type"` + Version string `config:"version" json:"version" yaml:"version"` + License string `config:"license" json:"license" yaml:"license"` + Conditions conditions `config:"conditions" json:"conditions" yaml:"conditions"` + Requires *requiresBlock `config:"requires" json:"requires,omitempty" yaml:"requires,omitempty"` + Owner owner `config:"owner" json:"owner" yaml:"owner"` } func (m *packageManifest) IsValid() bool { return m.FormatVersion != "" && m.Name != "" && m.Type != "" && m.Version != "" } +func (m *packageManifest) HasRequires() bool { + return m.Requires != nil && (len(m.Requires.Input) > 0 || len(m.Requires.Content) > 0) +} + +// ParsePackageManifest parses manifest.yml content read from anywhere — a +// worktree file, or content read from another git ref (e.g. via `git show +// :packages//manifest.yml`). +func ParsePackageManifest(content []byte) (*packageManifest, error) { + cfg, err := yaml.NewConfig(content, ucfg.PathSep(".")) + if err != nil { + return nil, fmt.Errorf("failed to parse package manifest: %w", err) + } + + var manifest packageManifest + if err := cfg.Unpack(&manifest); err != nil { + return nil, fmt.Errorf("failed to unpack package manifest: %w", err) + } + return &manifest, nil +} + func ReadPackageManifest(path string) (*packageManifest, error) { - cfg, err := yaml.NewConfigWithFile(path, ucfg.PathSep(".")) + content, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("reading file failed (path: %s): %w", path, err) } - var manifest packageManifest - err = cfg.Unpack(&manifest) + manifest, err := ParsePackageManifest(content) if err != nil { - return nil, fmt.Errorf("unpacking package manifest failed (path: %s): %w", path, err) + return nil, fmt.Errorf("%s: %w", path, err) } - return &manifest, nil + return manifest, nil } diff --git a/dev/citools/packages.go b/dev/citools/packages.go index 46ed226524d..ec5c4ac3759 100644 --- a/dev/citools/packages.go +++ b/dev/citools/packages.go @@ -15,10 +15,12 @@ import ( const ManifestFileName = "manifest.yml" -// PackageInfo holds the filesystem path and manifest name of a discovered package. +// PackageInfo holds the filesystem path and manifest fields of a discovered package. type PackageInfo struct { - Path string - Name string + Path string + Name string + Type string + HasRequires bool } // ListPackagesWithNames returns the path and manifest name of every valid package @@ -46,7 +48,12 @@ func ListPackagesWithNames(dir string) ([]PackageInfo, error) { if !manifest.IsValid() { return nil } - pkgs = append(pkgs, PackageInfo{Path: path, Name: manifest.Name}) + pkgs = append(pkgs, PackageInfo{ + Path: path, + Name: manifest.Name, + Type: manifest.Type, + HasRequires: manifest.HasRequires(), + }) // No need to look deeper once a package is found. return filepath.SkipDir }) diff --git a/dev/codeowners/codeowners.go b/dev/codeowners/codeowners.go index b7794a92666..16e3d897dba 100644 --- a/dev/codeowners/codeowners.go +++ b/dev/codeowners/codeowners.go @@ -7,7 +7,9 @@ package codeowners import ( "bufio" "fmt" + "io" "os" + "path" "path/filepath" "strings" @@ -72,6 +74,104 @@ func PackageOwners(packageName, dataStream, codeownersPath string) ([]string, er return dataStreamTeams, nil } +// Owners holds a parsed CODEOWNERS file for repeated lookups without re-reading disk. +// Obtain one via LoadOwners; use PackageOwnersByPath to look up a package by its +// filesystem path rather than its folder basename. +type Owners struct { + inner *githubOwners +} + +// LoadOwners parses the CODEOWNERS file at codeownersPath once. Use the returned +// *Owners for repeated lookups across many packages instead of calling +// PackageOwners (which re-reads the file on every call). +func LoadOwners(codeownersPath string) (*Owners, error) { + inner, err := readGithubOwners(codeownersPath) + if err != nil { + return nil, err + } + return &Owners{inner: inner}, nil +} + +// ParseOwners parses CODEOWNERS content from a string, applying the same +// single-field exclusion-rule validation that readGithubOwners does when +// reading from disk. A file that passes mage check never triggers this error. +func ParseOwners(content string) (*Owners, error) { + o, err := scanGithubOwners(strings.NewReader(content), "") + if err != nil { + return nil, err + } + return &Owners{inner: o}, nil +} + +// Resolve returns the owners that apply to p, walking up parent directories +// until an explicit CODEOWNERS entry is found. p must be a CODEOWNERS-style +// slash-prefixed path (e.g. "/packages/aws/data_stream/cloudtrail"). Returns +// (nil, false) when no entry exists for p or any of its ancestors. +func (o *Owners) Resolve(p string) ([]string, bool) { + p = strings.TrimSuffix(p, "/") + if p == "" { + p = "/" + } + for { + if owners, ok := o.inner.owners[p]; ok { + return owners, true + } + if p == "/" || p == "." { + return nil, false + } + p = path.Dir(p) + } +} + +// EntriesUnder returns the full CODEOWNERS paths of every explicit entry +// nested under prefix (e.g. "/packages/aws" returns +// "/packages/aws/data_stream/cloudtrail" and "/packages/aws/kibana", but not +// "/packages/aws" itself or the unrelated "/packages/awsome"). Order is +// unspecified. +func (o *Owners) EntriesUnder(prefix string) []string { + prefix = strings.TrimSuffix(prefix, "/") + "/" + var paths []string + for p := range o.inner.owners { + if strings.HasPrefix(p, prefix) { + paths = append(paths, p) + } + } + return paths +} + +// ExplicitEntry returns the owners explicitly defined for exactly this +// CODEOWNERS path — no walk-up/fallback resolution. Returns (nil, false) if +// no explicit entry exists for this exact path. +func (o *Owners) ExplicitEntry(p string) ([]string, bool) { + p = strings.TrimSuffix(p, "/") + owners, ok := o.inner.owners[p] + return owners, ok +} + +// PackageOwnersByPath returns the owning team(s) for the package at pkgPath +// (relative to the repo root, e.g. "packages/observability/nginx") and, when +// dataStream is set, the more-specific data-stream-level owner if one is defined. +// +// Prefer this over PackageOwners when the full package path is available: +// it handles arbitrary directory nesting by walking up the tree and avoids +// the folder-basename ambiguity in PackageOwners. See +// https://github.com/elastic/elastic-package/issues/3586. +func (o *Owners) PackageOwnersByPath(pkgPath, dataStream string) ([]string, error) { + teams, found := o.inner.findOwnerForFile(filepath.Join(pkgPath, citools.ManifestFileName)) + if !found { + return nil, fmt.Errorf("no owner found for package path %q", pkgPath) + } + if dataStream == "" { + return teams, nil + } + dataStreamDir := filepath.Join(pkgPath, "data_stream", dataStream) + dataStreamTeams, found := o.inner.owners["/"+filepath.ToSlash(dataStreamDir)] + if !found { + return teams, nil + } + return dataStreamTeams, nil +} + type githubOwners struct { owners map[string][]string path string @@ -113,13 +213,16 @@ func readGithubOwners(codeownersPath string) (*githubOwners, error) { return nil, fmt.Errorf("failed to open %q: %w", codeownersPath, err) } defer f.Close() + return scanGithubOwners(f, codeownersPath) +} +func scanGithubOwners(r io.Reader, sourcePath string) (*githubOwners, error) { codeowners := githubOwners{ owners: make(map[string][]string), - path: codeownersPath, + path: sourcePath, } - scanner := bufio.NewScanner(f) + scanner := bufio.NewScanner(r) lineNumber := 0 for scanner.Scan() { lineNumber++ @@ -131,15 +234,15 @@ func readGithubOwners(codeownersPath string) (*githubOwners, error) { if len(fields) == 1 { err := codeowners.checkSingleField(fields[0]) if err != nil { - return nil, fmt.Errorf("invalid line %d in %q: %w", lineNumber, codeownersPath, err) + return nil, fmt.Errorf("invalid line %d in %q: %w", lineNumber, sourcePath, err) } continue } - path, owners := fields[0], fields[1:] + ownerPath, owners := fields[0], fields[1:] // remove trailing slash from path - path = strings.TrimSuffix(path, "/") - codeowners.owners[path] = owners + ownerPath = strings.TrimSuffix(ownerPath, "/") + codeowners.owners[ownerPath] = owners } if err := scanner.Err(); err != nil { return nil, fmt.Errorf("scanner error: %w", err) diff --git a/dev/codeowners/codeowners_test.go b/dev/codeowners/codeowners_test.go index 26208dcb322..e2b728eb34f 100644 --- a/dev/codeowners/codeowners_test.go +++ b/dev/codeowners/codeowners_test.go @@ -11,6 +11,143 @@ import ( "github.com/stretchr/testify/require" ) +// Tests for the exported Owners API (ParseOwners, LoadOwners, Resolve, +// EntriesUnder, ExplicitEntry, PackageOwnersByPath). These mirror the +// behaviours the dev/backports/owners package relies on, ensuring the shared +// implementation stays consistent. + +func TestParseOwners(t *testing.T) { + t.Run("valid content parses successfully", func(t *testing.T) { + const content = `/packages/aws @elastic/obs-infraobs-integrations +/packages/aws/data_stream/cloudtrail @elastic/security-service-integrations +# a comment line is skipped +` + o, err := ParseOwners(content) + require.NoError(t, err) + owners, ok := o.ExplicitEntry("/packages/aws") + require.True(t, ok) + assert.Equal(t, []string{"@elastic/obs-infraobs-integrations"}, owners) + }) + + t.Run("single-field exclusion rule that removes owners from a defined path is rejected", func(t *testing.T) { + // checkSingleField must reject any exclusion-only line that would strip + // ownership from a path already covered by an explicit entry — same + // validation readGithubOwners performs when reading from disk. + const content = `/packages/aws @elastic/obs-infraobs-integrations +/packages/aws/data_stream/cloudtrail +` + _, err := ParseOwners(content) + assert.Error(t, err) + }) + + t.Run("trailing slash on path is stripped", func(t *testing.T) { + const content = "/packages/aws/ @elastic/obs-infraobs-integrations\n" + o, err := ParseOwners(content) + require.NoError(t, err) + _, ok := o.ExplicitEntry("/packages/aws") + assert.True(t, ok) + }) +} + +func TestResolve(t *testing.T) { + const content = ` +/packages/aws @elastic/obs-infraobs-integrations +/packages/aws/data_stream/cloudtrail @elastic/security-service-integrations +/packages/nested/foo @elastic/ecosystem +` + o, err := ParseOwners(content) + require.NoError(t, err) + + cases := []struct { + name string + path string + expected []string + found bool + }{ + { + name: "explicit package root", + path: "/packages/aws", + expected: []string{"@elastic/obs-infraobs-integrations"}, + found: true, + }, + { + name: "explicit data stream override", + path: "/packages/aws/data_stream/cloudtrail", + expected: []string{"@elastic/security-service-integrations"}, + found: true, + }, + { + name: "data stream without override falls back to package owner", + path: "/packages/aws/data_stream/vpcflow", + expected: []string{"@elastic/obs-infraobs-integrations"}, + found: true, + }, + { + name: "nested category package", + path: "/packages/nested/foo", + expected: []string{"@elastic/ecosystem"}, + found: true, + }, + { + name: "unknown path with no ancestor entry", + path: "/packages/does-not-exist", + found: false, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + got, found := o.Resolve(c.path) + assert.Equal(t, c.found, found) + if c.found { + assert.Equal(t, c.expected, got) + } + }) + } +} + +func TestEntriesUnder(t *testing.T) { + const content = ` +/packages/aws @elastic/obs-infraobs-integrations +/packages/aws/data_stream/cloudtrail @elastic/security-service-integrations +/packages/aws/kibana @elastic/obs-infraobs-integrations +/packages/awsome @elastic/unrelated-team +` + o, err := ParseOwners(content) + require.NoError(t, err) + + got := o.EntriesUnder("/packages/aws") + assert.ElementsMatch(t, []string{ + "/packages/aws/data_stream/cloudtrail", + "/packages/aws/kibana", + }, got) +} + +func TestExplicitEntry(t *testing.T) { + const content = ` +/packages/aws @elastic/obs-infraobs-integrations +/packages/aws/data_stream/cloudtrail @elastic/security-service-integrations +` + o, err := ParseOwners(content) + require.NoError(t, err) + + t.Run("returns entry for an explicitly defined path", func(t *testing.T) { + got, ok := o.ExplicitEntry("/packages/aws/data_stream/cloudtrail") + require.True(t, ok) + assert.Equal(t, []string{"@elastic/security-service-integrations"}, got) + }) + + t.Run("returns false for a path that only resolves via walk-up", func(t *testing.T) { + _, ok := o.ExplicitEntry("/packages/aws/data_stream/vpcflow") + assert.False(t, ok) + }) + + t.Run("returns false for an unknown path", func(t *testing.T) { + _, ok := o.ExplicitEntry("/packages/other") + assert.False(t, ok) + }) +} + func TestCheckManifest(t *testing.T) { cases := []struct { codeownersPath string @@ -271,3 +408,78 @@ func TestReturnPackageOwners(t *testing.T) { }) } } + +func TestPackageOwnersByPath(t *testing.T) { + cases := []struct { + title string + codeownersPath string + pkgPath string + datastream string + expected []string + expectedError bool + }{ + { + title: "nested package", + codeownersPath: "testdata/CODEOWNERS-nested-valid", + pkgPath: "testdata/nested_packages/category/package_nested_1", + datastream: "", + expected: []string{"@elastic/integrations-developer-experience"}, + expectedError: false, + }, + { + title: "nested package inherits category owner", + codeownersPath: "testdata/CODEOWNERS-nested-category-owner", + pkgPath: "testdata/nested_packages/category/package_nested_2", + datastream: "", + expected: []string{"@elastic/integrations-developer-experience"}, + expectedError: false, + }, + { + title: "nested package data stream", + codeownersPath: "testdata/CODEOWNERS-nested-streams-valid", + pkgPath: "testdata/nested_packages/category/package_nested_1", + datastream: "stream_1", + expected: []string{"@pkoutsovasilis"}, + expectedError: false, + }, + { + title: "top-level package", + codeownersPath: "testdata/CODEOWNERS-nested-valid", + pkgPath: "testdata/nested_packages/package_top", + datastream: "", + expected: []string{"@elastic/integrations-developer-experience"}, + expectedError: false, + }, + { + title: "data stream not in CODEOWNERS falls back to package owner", + codeownersPath: "testdata/CODEOWNERS-nested-streams-valid", + pkgPath: "testdata/nested_packages/category/package_nested_1", + datastream: "stream_unknown", + expected: []string{"@elastic/integrations-developer-experience"}, + expectedError: false, + }, + { + title: "package path not found", + codeownersPath: "testdata/CODEOWNERS-owners-packages-datastreams", + pkgPath: "packages/other", + datastream: "", + expected: []string{}, + expectedError: true, + }, + } + + for _, c := range cases { + t.Run(c.title, func(t *testing.T) { + owners, err := LoadOwners(c.codeownersPath) + require.NoError(t, err) + + got, err := owners.PackageOwnersByPath(c.pkgPath, c.datastream) + if c.expectedError { + assert.Error(t, err) + return + } + require.NoError(t, err) + assert.Equal(t, c.expected, got) + }) + } +} diff --git a/magefile.go b/magefile.go index 0b8b8a41738..39b7281149b 100644 --- a/magefile.go +++ b/magefile.go @@ -26,11 +26,14 @@ import ( "github.com/elastic/integrations/dev/backports/apply" "github.com/elastic/integrations/dev/backports/changelog" bpchecklist "github.com/elastic/integrations/dev/backports/checklist" + bpowners "github.com/elastic/integrations/dev/backports/owners" bppackages "github.com/elastic/integrations/dev/backports/packages" "github.com/elastic/integrations/dev/citools" "github.com/elastic/integrations/dev/codeowners" "github.com/elastic/integrations/dev/coverage" + "github.com/elastic/integrations/dev/gitutil" "github.com/elastic/integrations/dev/packagenames" + "github.com/elastic/integrations/dev/requiresupdate" "github.com/elastic/integrations/dev/testsreporter" ) @@ -389,24 +392,29 @@ func CheckBackportBranchActive(branch string, asJSON *bool) error { return nil } -// DetectBackportPackages lists the packages touched by commits between before and after. -// Runs git diff --name-only before..after and maps the changed files to package names -// using the packages/ directory as the root. -// Plain output: one package name per line. Pass -asJSON for a JSON array. -func DetectBackportPackages(before, after string, asJSON *bool) error { +// diffPackages runs git diff --name-only before..after and maps the changed +// files to package names. Shared by DetectBackportPackages and +// CheckBackportOwners so the diff-to-package logic lives in one place. +func diffPackages(before, after string) ([]string, error) { out, err := sh.Output("git", "diff", "--name-only", before+".."+after) if err != nil { - return fmt.Errorf("running git diff: %w", err) + return nil, fmt.Errorf("running git diff: %w", err) } - var files []string for _, line := range strings.Split(out, "\n") { if line = strings.TrimSpace(line); line != "" { files = append(files, line) } } + return bppackages.DetectPackages(files, "packages") +} - pkgs, err := bppackages.DetectPackages(files, "packages") +// DetectBackportPackages lists the packages touched by commits between before and after. +// Runs git diff --name-only before..after and maps the changed files to package names +// using the packages/ directory as the root. +// Plain output: one package name per line. Pass -asJSON for a JSON array. +func DetectBackportPackages(before, after string, asJSON *bool) error { + pkgs, err := diffPackages(before, after) if err != nil { return err } @@ -425,6 +433,54 @@ func DetectBackportPackages(before, after string, asJSON *bool) error { return nil } +// CheckBackportOwners reports package owner mismatches between the current +// worktree and remote/sourceBranch (the ownership source of truth, normally +// "main"), for every package changed between before and after — before..after, +// following DetectBackportPackages's convention: before is normally the PR's +// merge-base with sourceBranch, after is the PR's own commit. +// Prints a JSON array to stdout; see check_backport_owners.sh's +// build_owner_check_comment for the exact shape it expects. A package fully +// in sync, or no longer present on sourceBranch, is omitted entirely. +func CheckBackportOwners(remote, sourceBranch, before, after string) error { + if err := sh.Run("git", "fetch", remote, sourceBranch); err != nil { + return fmt.Errorf("fetching %s: %w", sourceBranch, err) + } + remoteRef := remote + "/" + sourceBranch + + pkgs, err := diffPackages(before, after) + if err != nil { + return fmt.Errorf("detecting packages: %w", err) + } + + pkgIndex, err := changelog.BuildPackageIndex("packages") + if err != nil { + return fmt.Errorf("building package index: %w", err) + } + + mismatches := bpowners.CheckPackages(gitutil.Git{}, "", remoteRef, pkgs, pkgIndex) + + type mismatchJSON struct { + Package string `json:"package"` + Teams []string `json:"teams,omitempty"` + Error string `json:"error,omitempty"` + } + results := make([]mismatchJSON, 0, len(mismatches)) + for _, m := range mismatches { + entry := mismatchJSON{Package: m.Package, Teams: m.Teams} + if m.Err != nil { + entry.Error = m.Err.Error() + } + results = append(results, entry) + } + + data, err := json.Marshal(results) + if err != nil { + return fmt.Errorf("marshalling results: %w", err) + } + fmt.Println(string(data)) + return nil +} + // RenderBackportChecklist prints the backport-checklist comment body for a PR. // It reads the list of packages from artifactPath (a JSON file with shape // {"pr_number": N, "packages": [...]}) and the existing comment body (if any) from @@ -654,3 +710,16 @@ func writeGitHubOutputs(outputs map[string]string) error { } return nil } + +// RequiresUpdate updates required package versions for all integration packages, +// adds a changelog entry per modified package, and opens one PR (or issue) per +// package. +// +// Usage: mage RequiresUpdate [-dryRun] [-preview] +// +// Pass -dryRun to preview proposals without applying changes (also skips +// publishing, since no files would be written); pass -preview to print what +// would be published without touching git or GitHub. +func RequiresUpdate(dryRun, preview *bool) error { + return requiresupdate.Run(dryRun != nil && *dryRun, preview != nil && *preview) +} diff --git a/packages/aws/changelog.yml b/packages/aws/changelog.yml index c277b5f408b..687c1f92318 100644 --- a/packages/aws/changelog.yml +++ b/packages/aws/changelog.yml @@ -1,4 +1,24 @@ # newer versions go on top +- version: "7.0.0" + changes: + - description: Hide the CloudWatch, EBS, EC2, ECS, and S3 metric/log inputs when the Identity Federation setup access option is selected, since only the GuardDuty API input supports identity federation. + type: enhancement + link: https://github.com/elastic/integrations/pull/19828 + - description: Reorganize AWS credentials configuration into a `Setup Access` selector with Identity Federation, Direct Access Keys, Temporary Access Keys, Assume Role, Assume Role with External ID, and Shared Credentials options. Existing access keys, role ARN, and shared credential settings continue to function and are auto-mapped to the corresponding option. + type: enhancement + link: https://github.com/elastic/integrations/pull/19828 + - description: Switch the GuardDuty httpjson stream from manual SigV4 HMAC signing to the native `auth.aws` block. + type: enhancement + link: https://github.com/elastic/integrations/pull/19828 + - description: Store the `external_id` variable as a secret. + type: breaking-change + link: https://github.com/elastic/integrations/pull/19828 + - description: Add `assume_role_duration`, `assume_role_expiry_window`, and `supports_identity_federation` variables. + type: enhancement + link: https://github.com/elastic/integrations/pull/19828 + - description: Require Kibana and Elastic Agent ^9.4.0 (drop support for Kibana 8.x, Kibana 9.x below 9.4.0, and Elastic Agent below 9.4.0). The var_groups manifest feature and `auth.aws` runtime require this minimum. + type: breaking-change + link: https://github.com/elastic/integrations/pull/19828 - version: "6.21.0" changes: - description: Poll Amazon Inspector findings on `updatedAt` instead of `lastObservedAt` so that findings AWS marks CLOSED or SUPPRESSED are collected and no longer remain stale in Elastic. diff --git a/packages/aws/data_stream/guardduty/agent/stream/httpjson.yml.hbs b/packages/aws/data_stream/guardduty/agent/stream/httpjson.yml.hbs index 9772b464549..08bf4acba8e 100644 --- a/packages/aws/data_stream/guardduty/agent/stream/httpjson.yml.hbs +++ b/packages/aws/data_stream/guardduty/agent/stream/httpjson.yml.hbs @@ -15,10 +15,8 @@ request.proxy_url: {{proxy_url}} {{#if ssl}} request.ssl: {{ssl}} {{/if}} + request.transforms: - - set: - target: header.X-Amz-Date - value: '[[formatDate (now) "20060102T150405Z"]]' - set: target: body.maxResults value: 50 @@ -35,20 +33,12 @@ request.transforms: re-evaluates (now) on every pagination page, which can change the query and invalidate the NextToken. A CEL rewrite can reintroduce the upper bound safely since it can pin the value once per collection interval. --}} - - set: - target: header.Authorization - value: '[[$now := (now)]][[(sprintf "AWS4-HMAC-SHA256 Credential={{access_key_id}}/%s/{{aws_region}}/guardduty/aws4_request, SignedHeaders=host;x-amz-date, Signature=%s" (formatDate ($now) "20060102") (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" "AWS4{{secret_access_key}}" (formatDate ($now) "20060102"))) "{{aws_region}}")) "guardduty")) "aws4_request")) "AWS4-HMAC-SHA256\n" (formatDate ($now) "20060102T150405Z") "\n" (sprintf "%s/%s\n" (formatDate ($now) "20060102") "{{aws_region}}/guardduty/aws4_request") (hash "sha256" "POST\n" "/detector/{{detector_id}}/findings\n" "\n" "host:guardduty.{{aws_region}}.{{tld}}\n" (sprintf "x-amz-date:%s\n\n" (formatDate ($now) "20060102T150405Z")) "host;x-amz-date\n" (hash "sha256" (sprintf `%s` .body)))))]]' response.pagination: - set: target: body.nextToken value: '[[if (ne .last_response.body.nextToken "")]][[.last_response.body.nextToken]][[end]]' fail_on_template_error: true do_not_log_failure: true - - delete: - target: header.Authorization - - set: - target: header.Authorization - value: '[[$now := (now)]][[(sprintf "AWS4-HMAC-SHA256 Credential={{access_key_id}}/%s/{{aws_region}}/guardduty/aws4_request, SignedHeaders=host;x-amz-date, Signature=%s" (formatDate ($now) "20060102") (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" "AWS4{{secret_access_key}}" (formatDate ($now) "20060102"))) "{{aws_region}}")) "guardduty")) "aws4_request")) "AWS4-HMAC-SHA256\n" (formatDate ($now) "20060102T150405Z") "\n" (sprintf "%s/%s\n" (formatDate ($now) "20060102") "{{aws_region}}/guardduty/aws4_request") (hash "sha256" "POST\n" "/detector/{{detector_id}}/findings\n" "\n" "host:guardduty.{{aws_region}}.{{tld}}\n" (sprintf "x-amz-date:%s\n\n" (formatDate ($now) "20060102T150405Z")) "host;x-amz-date\n" (hash "sha256" (sprintf `%s` .body)))))]]' chain: - step: request.url: https://guardduty.{{aws_region}}.{{tld}}/detector/{{detector_id}}/findings/get @@ -64,9 +54,6 @@ chain: {{/if}} request.method: POST request.transforms: - - set: - target: header.X-Amz-Date - value: '[[formatDate (now) "20060102T150405Z"]]' - set: target: body.findingIds value: '[[toJSON .parent_last_response.body.findingIds]]' @@ -75,9 +62,6 @@ chain: target: body.sortCriteria value: '{"attributeName":"updatedAt","orderBy":"ASC"}' value_type: json - - set: - target: header.Authorization - value: '[[$now := (now)]][[(sprintf "AWS4-HMAC-SHA256 Credential={{access_key_id}}/%s/{{aws_region}}/guardduty/aws4_request, SignedHeaders=host;x-amz-date, Signature=%s" (formatDate ($now) "20060102") (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" (hexDecode (hmac "sha256" "AWS4{{secret_access_key}}" (formatDate ($now) "20060102"))) "{{aws_region}}")) "guardduty")) "aws4_request")) "AWS4-HMAC-SHA256\n" (formatDate ($now) "20060102T150405Z") "\n" (sprintf "%s/%s\n" (formatDate ($now) "20060102") "{{aws_region}}/guardduty/aws4_request") (hash "sha256" "POST\n" "/detector/{{detector_id}}/findings/get\n" "\n" "host:guardduty.{{aws_region}}.{{tld}}\n" (sprintf "x-amz-date:%s\n\n" (formatDate ($now) "20060102T150405Z")) "host;x-amz-date\n" (hash "sha256" (sprintf `%s` .body)))))]]' response.split: target: body.findings cursor: @@ -101,3 +85,34 @@ publisher_pipeline.disable_host: true processors: {{processors}} {{/if}} +auth.aws: +{{#if access_key_id}} + access_key_id: {{access_key_id}} +{{/if}} +{{#if secret_access_key}} + secret_access_key: {{secret_access_key}} +{{/if}} +{{#if session_token}} + session_token: {{session_token}} +{{/if}} +{{#if shared_credential_file}} + shared_credential_file: {{shared_credential_file}} +{{/if}} +{{#if credential_profile_name}} + credential_profile_name: {{credential_profile_name}} +{{/if}} +{{#if role_arn}} + role_arn: {{role_arn}} +{{/if}} +{{#if external_id}} + external_id: {{external_id}} +{{/if}} +{{#if assume_role_duration}} + assume_role.duration: {{assume_role_duration}} +{{/if}} +{{#if assume_role_expiry_window}} + assume_role.expiry_window: {{assume_role_expiry_window}} +{{/if}} +{{#if supports_identity_federation}} + use_cloud_connectors: {{supports_identity_federation}} +{{/if}} diff --git a/packages/aws/manifest.yml b/packages/aws/manifest.yml index ee9dae64487..5bbad6ee374 100644 --- a/packages/aws/manifest.yml +++ b/packages/aws/manifest.yml @@ -1,7 +1,7 @@ -format_version: 3.4.0 +format_version: 3.6.1 name: aws title: AWS -version: 6.21.0 +version: 7.0.0 description: Collect logs and metrics from Amazon Web Services (AWS) with Elastic Agent. type: integration categories: @@ -21,7 +21,10 @@ conditions: elastic: subscription: basic kibana: - version: "^8.19.4 || ^9.2.1" + version: "^9.4.0" + # auth.aws support in CEL and HTTPJSON inputs requires Elastic Agent 9.4.0+. + agent: + version: "^9.4.0" screenshots: - src: /img/metricbeat-aws-overview.png title: metricbeat aws overview @@ -79,7 +82,22 @@ vars: multi: false required: false show_user: false + secret: true description: External ID to use when assuming a role in another account, see [the AWS documentation for use of external IDs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) + - name: assume_role_duration + type: duration + title: Assume Role Duration + multi: false + required: false + show_user: false + description: Duration of the assumed role session. + - name: assume_role_expiry_window + type: duration + title: Assume Role Expiry Window + multi: false + required: false + show_user: false + description: Amount of time before the assumed role session expires during which credentials are refreshed. - name: default_region type: text title: Default AWS Region @@ -95,6 +113,43 @@ vars: required: false show_user: false description: URL to proxy connections in the form of http\[s\]://:@: + - name: supports_identity_federation + type: bool + title: Supports Identity Federation + multi: false + required: false + show_user: false +var_groups: + - name: credential_type + required: true + title: Setup Access + selector_title: Preferred method + options: + - name: identity_federation + title: Identity Federation + vars: [role_arn, external_id, supports_identity_federation] + hide_in_deployment_modes: [default] + provider: aws + iac_template_url: https://console.aws.amazon.com/cloudformation/home#/stacks/quickcreate?templateURL=https://elastic-cspm-cft.s3.eu-central-1.amazonaws.com/cloudformation-cloud-connectors-guardduty-9.4.0.yml¶m_ElasticResourceId=RESOURCE_ID + - name: direct_access_key + title: Direct Access Keys + vars: [access_key_id, secret_access_key] + - name: temporary_access_key + title: Temporary Access Keys + vars: [access_key_id, secret_access_key, session_token] + hide_in_deployment_modes: [agentless] + - name: assume_role + title: Assume Role + vars: [role_arn] + hide_in_deployment_modes: [agentless] + - name: assume_role_external_id + title: Assume Role with External ID + vars: [role_arn, external_id] + hide_in_deployment_modes: [agentless] + - name: shared_credentials + title: Shared Credentials + vars: [shared_credential_file, credential_profile_name] + hide_in_deployment_modes: [agentless] policy_templates: - name: awshealth title: AWS Health @@ -108,6 +163,8 @@ policy_templates: title: Collect AWS Health metrics (experimental) description: Collect AWS Health metrics (experimental). input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -139,6 +196,8 @@ policy_templates: title: Collect billing metrics description: Collect billing metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -198,10 +257,14 @@ policy_templates: title: Collect logs from CloudWatch description: Collecting logs using aws-cloudwatch input input_group: logs + hide_in_var_group_options: + credential_type: [identity_federation] - type: aws/metrics title: Collect metrics from CloudWatch description: Collecting metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -238,6 +301,8 @@ policy_templates: - type: cel title: Collect AWS Config logs via API description: Collecting AWS Config logs via API. + hide_in_var_group_options: + credential_type: [identity_federation] icons: - src: /img/logo-aws-config.svg title: AWS Config logo @@ -261,6 +326,8 @@ policy_templates: title: Collect dynamodb metrics description: Collect dynamodb metrics input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -293,6 +360,8 @@ policy_templates: title: Collect EBS metrics description: Collect EBS metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -329,10 +398,14 @@ policy_templates: title: Collect EC2 logs from CloudWatch description: Collecting logs from EC2 using aws-cloudwatch input input_group: logs + hide_in_var_group_options: + credential_type: [identity_federation] - type: aws/metrics title: Collect EC2 metrics description: Collecting EC2 metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -365,6 +438,8 @@ policy_templates: title: Collect ECS metrics description: Collecting ECS metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -393,14 +468,20 @@ policy_templates: title: Collect ELB logs from S3 description: Collecting logs from ELB using aws-s3 input input_group: logs + hide_in_var_group_options: + credential_type: [identity_federation] - type: aws-cloudwatch title: Collect ELB logs from CloudWatch description: Collecting logs from ELB using aws-cloudwatch input input_group: logs + hide_in_var_group_options: + credential_type: [identity_federation] - type: aws/metrics title: Collect ELB metrics description: Collecting ELB metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -453,10 +534,14 @@ policy_templates: title: Collect Lambda metrics description: Collect Lambda metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] - type: aws-cloudwatch title: Collect lambda logs from CloudWatch description: Collecting AWS lambda logs using aws-cloudwatch input input_group: logs + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -555,6 +640,8 @@ policy_templates: title: Collect RDS metrics description: Collect RDS metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -593,6 +680,8 @@ policy_templates: title: Collect S3 metrics description: Collecting S3 metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -651,6 +740,8 @@ policy_templates: title: Collect SNS metrics description: Collect SNS metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -682,6 +773,8 @@ policy_templates: title: Collect SQS metrics description: Collect SQS metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -713,6 +806,8 @@ policy_templates: title: Collect Transit Gateway metrics description: Collect Transit Gateway metrics using AWS CloudWatch input_group: metrics + hide_in_var_group_options: + credential_type: [identity_federation] deployment_modes: default: enabled: true @@ -922,6 +1017,8 @@ policy_templates: - type: httpjson title: Collect AWS Security Hub CSPM logs via API description: Collecting AWS Security Hub CSPM logs via API. + hide_in_var_group_options: + credential_type: [identity_federation] screenshots: - src: /img/securityhub_cspm_findings_insights_dashboard.png title: Security Hub CSPM Findings and Insights dashboard screenshot @@ -958,6 +1055,8 @@ policy_templates: - type: httpjson title: Collect Amazon Inspector logs via API description: Collecting Amazon Inspector logs via API. + hide_in_var_group_options: + credential_type: [identity_federation] screenshots: - src: /img/inspector-findings-overview-dashboard.png title: Inspector Findings Overview dashboard @@ -1003,6 +1102,8 @@ policy_templates: - type: aws-s3 title: Collect Amazon GuardDuty logs via AWS S3 or SQS description: Collecting Amazon GuardDuty logs via AWS S3 or SQS input. + hide_in_var_group_options: + credential_type: [identity_federation] screenshots: - src: /img/guardduty-findings-overview.png title: GuardDuty Findings Overview dashboard screenshot diff --git a/packages/aws_rds_otel/changelog.yml b/packages/aws_rds_otel/changelog.yml index 94380c89b44..be0a0623e59 100644 --- a/packages/aws_rds_otel/changelog.yml +++ b/packages/aws_rds_otel/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "0.10.0" + changes: + - description: Add drill-down dashboards + type: enhancement + link: https://github.com/elastic/integrations/pull/20082 - version: "0.9.0" changes: - description: Add tags to Kibana assets diff --git a/packages/aws_rds_otel/kibana/dashboard/aws_rds_otel-c92e1216-83f6-4de7-9d7f-1bcb42d5988a.json b/packages/aws_rds_otel/kibana/dashboard/aws_rds_otel-c92e1216-83f6-4de7-9d7f-1bcb42d5988a.json index 0f0c37edbb0..8340ce546f0 100644 --- a/packages/aws_rds_otel/kibana/dashboard/aws_rds_otel-c92e1216-83f6-4de7-9d7f-1bcb42d5988a.json +++ b/packages/aws_rds_otel/kibana/dashboard/aws_rds_otel-c92e1216-83f6-4de7-9d7f-1bcb42d5988a.json @@ -1,2873 +1,2836 @@ { - "accessControl": { - "accessMode": "default", - "owner": "u_LQY3UOHdVkYrbjy8PgOCQKR-fROZ1M0Vh7DvpOH6S40_0" - }, - "attributes": { - "description": "AWS RDS dashboard for CloudWatch metrics collected by the OpenTelemetry Collector.", - "kibanaSavedObjectMeta": { - "searchSourceJSON": { - "query": { - "language": "kuery", - "query": "" - } - } - }, - "optionsJSON": { - "autoApplyFilters": false, - "hidePanelBorders": false, - "hidePanelTitles": false, - "syncColors": false, - "syncCursor": true, - "syncTooltips": false, - "useMargins": true - }, - "panelsJSON": [ - { - "embeddableConfig": { - "content": "## ![Amazon RDS](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCA4MCA4MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgPHRpdGxlPkljb24tQXJjaGl0ZWN0dXJlLzY0L0FyY2hfQW1hem9uLVJEU182NDwvdGl0bGU+ICAgIDxnIGlkPSJJY29uLUFyY2hpdGVjdHVyZS82NC9BcmNoX0FtYXpvbi1SRFNfNjQiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9Ikljb24tQXJjaGl0ZWN0dXJlLUJHLzY0L0RhdGFiYXNlIiBmaWxsPSIjQzkyNUQxIj4gICAgICAgICAgICA8cmVjdCBpZD0iUmVjdGFuZ2xlIiB4PSIwIiB5PSIwIiB3aWR0aD0iODAiIGhlaWdodD0iODAiPjwvcmVjdD4gICAgICAgIDwvZz4gICAgICAgIDxwYXRoIGQ9Ik0xNS40MTQsMTQgTDI0LjcwNywyMy4yOTMgTDIzLjI5MywyNC43MDcgTDE0LDE1LjQxNCBMMTQsMjMgTDEyLDIzIEwxMiwxMyBDMTIsMTIuNDQ4IDEyLjQ0NywxMiAxMywxMiBMMjMsMTIgTDIzLDE0IEwxNS40MTQsMTQgWiBNNjgsMTMgTDY4LDIzIEw2NiwyMyBMNjYsMTUuNDE0IEw1Ni43MDcsMjQuNzA3IEw1NS4yOTMsMjMuMjkzIEw2NC41ODYsMTQgTDU3LDE0IEw1NywxMiBMNjcsMTIgQzY3LjU1MywxMiA2OCwxMi40NDggNjgsMTMgTDY4LDEzIFogTTY2LDU3IEw2OCw1NyBMNjgsNjcgQzY4LDY3LjU1MiA2Ny41NTMsNjggNjcsNjggTDU3LDY4IEw1Nyw2NiBMNjQuNTg2LDY2IEw1NS4yOTMsNTYuNzA3IEw1Ni43MDcsNTUuMjkzIEw2Niw2NC41ODYgTDY2LDU3IFogTTY1LjUsMzkuMjEzIEM2NS41LDM1Ljg5NCA2MS42NjgsMzIuNjE1IDU1LjI1LDMwLjQ0MiBMNTUuODkxLDI4LjU0OCBDNjMuMjY4LDMxLjA0NSA2Ny41LDM0LjkzMiA2Ny41LDM5LjIxMyBDNjcuNSw0My40OTUgNjMuMjY4LDQ3LjM4MyA1NS44OSw0OS44NzkgTDU1LjI0OSw0Ny45ODQgQzYxLjY2OCw0NS44MTIgNjUuNSw0Mi41MzQgNjUuNSwzOS4yMTMgTDY1LjUsMzkuMjEzIFogTTE0LjU1NiwzOS4yMTMgQzE0LjU1Niw0Mi4zOTMgMTguMTQzLDQ1LjU4NSAyNC4xNTIsNDcuNzUzIEwyMy40NzMsNDkuNjM0IEMxNi41MzUsNDcuMTMxIDEyLjU1Niw0My4zMzMgMTIuNTU2LDM5LjIxMyBDMTIuNTU2LDM1LjA5NCAxNi41MzUsMzEuMjk2IDIzLjQ3MywyOC43OTIgTDI0LjE1MiwzMC42NzMgQzE4LjE0MywzMi44NDIgMTQuNTU2LDM2LjAzNCAxNC41NTYsMzkuMjEzIEwxNC41NTYsMzkuMjEzIFogTTI0LjcwNyw1Ni43MDcgTDE1LjQxNCw2NiBMMjMsNjYgTDIzLDY4IEwxMyw2OCBDMTIuNDQ3LDY4IDEyLDY3LjU1MiAxMiw2NyBMMTIsNTcgTDE0LDU3IEwxNCw2NC41ODYgTDIzLjI5Myw1NS4yOTMgTDI0LjcwNyw1Ni43MDcgWiBNNDAsMzEuMjg2IEMzMi44NTQsMzEuMjg2IDI5LDI5LjQ0IDI5LDI4LjY4NiBDMjksMjcuOTMxIDMyLjg1NCwyNi4wODYgNDAsMjYuMDg2IEM0Ny4xNDUsMjYuMDg2IDUxLDI3LjkzMSA1MSwyOC42ODYgQzUxLDI5LjQ0IDQ3LjE0NSwzMS4yODYgNDAsMzEuMjg2IEw0MCwzMS4yODYgWiBNNDAuMDI5LDM5LjAzMSBDMzMuMTg3LDM5LjAzMSAyOSwzNy4xNjIgMjksMzYuMTQ1IEwyOSwzMS4yODQgQzMxLjQ2MywzMi42NDMgMzUuODMyLDMzLjI4NiA0MCwzMy4yODYgQzQ0LjE2OCwzMy4yODYgNDguNTM3LDMyLjY0MyA1MSwzMS4yODQgTDUxLDM2LjE0NSBDNTEsMzcuMTYzIDQ2LjgzNSwzOS4wMzEgNDAuMDI5LDM5LjAzMSBMNDAuMDI5LDM5LjAzMSBaIE00MC4wMjksNDYuNjY3IEMzMy4xODcsNDYuNjY3IDI5LDQ0Ljc5OCAyOSw0My43ODEgTDI5LDM4Ljg2MiBDMzEuNDMxLDQwLjI5MSAzNS43NDIsNDEuMDMxIDQwLjAyOSw0MS4wMzEgQzQ0LjI5Miw0MS4wMzEgNDguNTc4LDQwLjI5MiA1MSwzOC44NjcgTDUxLDQzLjc4MSBDNTEsNDQuNzk5IDQ2LjgzNSw0Ni42NjcgNDAuMDI5LDQ2LjY2NyBMNDAuMDI5LDQ2LjY2NyBaIE00MCw1My41MTggQzMyLjg4Myw1My41MTggMjksNTEuNjA1IDI5LDUwLjYyMiBMMjksNDYuNDk4IEMzMS40MzEsNDcuOTI3IDM1Ljc0Miw0OC42NjcgNDAuMDI5LDQ4LjY2NyBDNDQuMjkyLDQ4LjY2NyA0OC41NzgsNDcuOTI5IDUxLDQ2LjUwMyBMNTEsNTAuNjIyIEM1MSw1MS42MDUgNDcuMTE3LDUzLjUxOCA0MCw1My41MTggTDQwLDUzLjUxOCBaIE00MCwyNC4wODYgQzMzLjczOSwyNC4wODYgMjcsMjUuNTI1IDI3LDI4LjY4NiBMMjcsNTAuNjIyIEMyNyw1My44MzYgMzMuNTQsNTUuNTE4IDQwLDU1LjUxOCBDNDYuNDYsNTUuNTE4IDUzLDUzLjgzNiA1Myw1MC42MjIgTDUzLDI4LjY4NiBDNTMsMjUuNTI1IDQ2LjI2MSwyNC4wODYgNDAsMjQuMDg2IEw0MCwyNC4wODYgWiIgaWQ9IkFtYXpvbi1SRFNfSWNvbl82NF9TcXVpZCIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPiAgICA8L2c+PC9zdmc+)  AWS RDS dashboard", - "description": "Monitor AWS RDS database instances across your fleet in real time.\nFilter by DB instance at the top. Spot saturated CPU, idle databases, and storage outliers in the summary table — click any database to drill down.\nTo get started, instrument your RDS instances with the AWS integration.", - "hide_border": true, - "hide_title": true, - "settings": { - "open_links_in_new_tab": true - } - }, - "gridData": { - "h": 2, - "i": "hdr", - "w": 42, - "x": 0, - "y": 0 - }, - "panelIndex": "hdr", - "type": "markdown" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Navigation tile — clicking opens the Kibana Dashboards library searched for “AWS OTel” dashboards in a new browser tab, carrying the current panel time range to the destination.", - "references": [], - "state": { - "adHocDataViews": { - "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", - "managed": false, - "name": "metrics-aws.rds*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", - "timeField": "@timestamp", - "title": "metrics-aws.rds*" - } - ], - "layers": { - "layer-nav-otel": { - "columns": [ - { - "columnId": "col-nav-otel", - "customLabel": true, - "fieldName": "value", - "inMetricDimension": true, - "label": "Browse other AWS OTel dashboards", - "meta": { - "esType": "keyword", - "type": "string" - } - } - ], - "index": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nROW value = \"AWS-Managed-OTel\" | KEEP value" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", - "name": "textBasedLanguages-datasource-layer-layer-nav-otel", - "type": "index-pattern" + "attributes": { + "description": "AWS RDS dashboard for CloudWatch metrics collected by the OpenTelemetry Collector.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "query": { + "language": "kuery", + "query": "" } - ], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nROW value = \"AWS-Managed-OTel\" | KEEP value" - }, - "visualization": { - "applyColorTo": "background", - "color": "#61a2ff00", - "colorMode": "background", - "icon": "popout", - "iconAlign": "right", - "layerId": "layer-nav-otel", - "layerType": "data", - "metricAccessor": "col-nav-otel", - "primaryAlign": "left", - "primaryPosition": "bottom", - "showBar": false, - "titlesTextAlign": "left", - "titlesTextSize": "xxs", - "valueFontMode": "fit", - "valuesTextSize": "xs" - } - }, - "title": "", - "version": 2, - "visualizationType": "lnsMetric" - }, - "description": "Navigation tile — clicking opens the Kibana Dashboards library searched for “AWS OTel” dashboards in a new browser tab, carrying the current panel time range to the destination.", - "drilldowns": [ - { - "encode_url": false, - "label": "Browse AWS OTel dashboards", - "open_in_new_tab": true, - "trigger": "on_click_value", - "type": "url_drilldown", - "url": "{{kibanaUrl}}/app/dashboards#/list?_g=(filters:!(),refreshInterval:(pause:!t,value:60000),time:(from:{{context.panel.timeRange.from}},to:{{context.panel.timeRange.to}}))&s=AWS%20OTel" } - ], - "hide_border": true }, - "gridData": { - "h": 2, - "i": "nav-otel-dashboards", - "w": 6, - "x": 42, - "y": 0 + "optionsJSON": { + "autoApplyFilters": false, + "hidePanelBorders": false, + "hidePanelTitles": false, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": true }, - "panelIndex": "nav-otel-dashboards", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" + "panelsJSON": [ + { + "embeddableConfig": { + "content": "## ![Amazon RDS](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCA4MCA4MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgPHRpdGxlPkljb24tQXJjaGl0ZWN0dXJlLzY0L0FyY2hfQW1hem9uLVJEU182NDwvdGl0bGU+ICAgIDxnIGlkPSJJY29uLUFyY2hpdGVjdHVyZS82NC9BcmNoX0FtYXpvbi1SRFNfNjQiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9Ikljb24tQXJjaGl0ZWN0dXJlLUJHLzY0L0RhdGFiYXNlIiBmaWxsPSIjQzkyNUQxIj4gICAgICAgICAgICA8cmVjdCBpZD0iUmVjdGFuZ2xlIiB4PSIwIiB5PSIwIiB3aWR0aD0iODAiIGhlaWdodD0iODAiPjwvcmVjdD4gICAgICAgIDwvZz4gICAgICAgIDxwYXRoIGQ9Ik0xNS40MTQsMTQgTDI0LjcwNywyMy4yOTMgTDIzLjI5MywyNC43MDcgTDE0LDE1LjQxNCBMMTQsMjMgTDEyLDIzIEwxMiwxMyBDMTIsMTIuNDQ4IDEyLjQ0NywxMiAxMywxMiBMMjMsMTIgTDIzLDE0IEwxNS40MTQsMTQgWiBNNjgsMTMgTDY4LDIzIEw2NiwyMyBMNjYsMTUuNDE0IEw1Ni43MDcsMjQuNzA3IEw1NS4yOTMsMjMuMjkzIEw2NC41ODYsMTQgTDU3LDE0IEw1NywxMiBMNjcsMTIgQzY3LjU1MywxMiA2OCwxMi40NDggNjgsMTMgTDY4LDEzIFogTTY2LDU3IEw2OCw1NyBMNjgsNjcgQzY4LDY3LjU1MiA2Ny41NTMsNjggNjcsNjggTDU3LDY4IEw1Nyw2NiBMNjQuNTg2LDY2IEw1NS4yOTMsNTYuNzA3IEw1Ni43MDcsNTUuMjkzIEw2Niw2NC41ODYgTDY2LDU3IFogTTY1LjUsMzkuMjEzIEM2NS41LDM1Ljg5NCA2MS42NjgsMzIuNjE1IDU1LjI1LDMwLjQ0MiBMNTUuODkxLDI4LjU0OCBDNjMuMjY4LDMxLjA0NSA2Ny41LDM0LjkzMiA2Ny41LDM5LjIxMyBDNjcuNSw0My40OTUgNjMuMjY4LDQ3LjM4MyA1NS44OSw0OS44NzkgTDU1LjI0OSw0Ny45ODQgQzYxLjY2OCw0NS44MTIgNjUuNSw0Mi41MzQgNjUuNSwzOS4yMTMgTDY1LjUsMzkuMjEzIFogTTE0LjU1NiwzOS4yMTMgQzE0LjU1Niw0Mi4zOTMgMTguMTQzLDQ1LjU4NSAyNC4xNTIsNDcuNzUzIEwyMy40NzMsNDkuNjM0IEMxNi41MzUsNDcuMTMxIDEyLjU1Niw0My4zMzMgMTIuNTU2LDM5LjIxMyBDMTIuNTU2LDM1LjA5NCAxNi41MzUsMzEuMjk2IDIzLjQ3MywyOC43OTIgTDI0LjE1MiwzMC42NzMgQzE4LjE0MywzMi44NDIgMTQuNTU2LDM2LjAzNCAxNC41NTYsMzkuMjEzIEwxNC41NTYsMzkuMjEzIFogTTI0LjcwNyw1Ni43MDcgTDE1LjQxNCw2NiBMMjMsNjYgTDIzLDY4IEwxMyw2OCBDMTIuNDQ3LDY4IDEyLDY3LjU1MiAxMiw2NyBMMTIsNTcgTDE0LDU3IEwxNCw2NC41ODYgTDIzLjI5Myw1NS4yOTMgTDI0LjcwNyw1Ni43MDcgWiBNNDAsMzEuMjg2IEMzMi44NTQsMzEuMjg2IDI5LDI5LjQ0IDI5LDI4LjY4NiBDMjksMjcuOTMxIDMyLjg1NCwyNi4wODYgNDAsMjYuMDg2IEM0Ny4xNDUsMjYuMDg2IDUxLDI3LjkzMSA1MSwyOC42ODYgQzUxLDI5LjQ0IDQ3LjE0NSwzMS4yODYgNDAsMzEuMjg2IEw0MCwzMS4yODYgWiBNNDAuMDI5LDM5LjAzMSBDMzMuMTg3LDM5LjAzMSAyOSwzNy4xNjIgMjksMzYuMTQ1IEwyOSwzMS4yODQgQzMxLjQ2MywzMi42NDMgMzUuODMyLDMzLjI4NiA0MCwzMy4yODYgQzQ0LjE2OCwzMy4yODYgNDguNTM3LDMyLjY0MyA1MSwzMS4yODQgTDUxLDM2LjE0NSBDNTEsMzcuMTYzIDQ2LjgzNSwzOS4wMzEgNDAuMDI5LDM5LjAzMSBMNDAuMDI5LDM5LjAzMSBaIE00MC4wMjksNDYuNjY3IEMzMy4xODcsNDYuNjY3IDI5LDQ0Ljc5OCAyOSw0My43ODEgTDI5LDM4Ljg2MiBDMzEuNDMxLDQwLjI5MSAzNS43NDIsNDEuMDMxIDQwLjAyOSw0MS4wMzEgQzQ0LjI5Miw0MS4wMzEgNDguNTc4LDQwLjI5MiA1MSwzOC44NjcgTDUxLDQzLjc4MSBDNTEsNDQuNzk5IDQ2LjgzNSw0Ni42NjcgNDAuMDI5LDQ2LjY2NyBMNDAuMDI5LDQ2LjY2NyBaIE00MCw1My41MTggQzMyLjg4Myw1My41MTggMjksNTEuNjA1IDI5LDUwLjYyMiBMMjksNDYuNDk4IEMzMS40MzEsNDcuOTI3IDM1Ljc0Miw0OC42NjcgNDAuMDI5LDQ4LjY2NyBDNDQuMjkyLDQ4LjY2NyA0OC41NzgsNDcuOTI5IDUxLDQ2LjUwMyBMNTEsNTAuNjIyIEM1MSw1MS42MDUgNDcuMTE3LDUzLjUxOCA0MCw1My41MTggTDQwLDUzLjUxOCBaIE00MCwyNC4wODYgQzMzLjczOSwyNC4wODYgMjcsMjUuNTI1IDI3LDI4LjY4NiBMMjcsNTAuNjIyIEMyNyw1My44MzYgMzMuNTQsNTUuNTE4IDQwLDU1LjUxOCBDNDYuNDYsNTUuNTE4IDUzLDUzLjgzNiA1Myw1MC42MjIgTDUzLDI4LjY4NiBDNTMsMjUuNTI1IDQ2LjI2MSwyNC4wODYgNDAsMjQuMDg2IEw0MCwyNC4wODYgWiIgaWQ9IkFtYXpvbi1SRFNfSWNvbl82NF9TcXVpZCIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPiAgICA8L2c+PC9zdmc+)\u0026nbsp;\u0026nbsp;AWS RDS dashboard", + "description": "Monitor AWS RDS database instances across your fleet in real time.\nFilter by DB instance at the top. Spot saturated CPU, idle databases, and storage outliers in the summary table — click any database to drill down.\nTo get started, instrument your RDS instances with the AWS integration.", + "hide_border": true, + "hide_title": true, + "settings": { + "open_links_in_new_tab": true } - ], - "layers": { - "4146621d-d1e8-4240-9a4c-52c6b0289dd8": { - "columns": [ - { - "columnId": "total", - "customLabel": false, - "fieldName": "total", - "inMetricDimension": true, - "label": "total", - "meta": { - "esType": "long", - "type": "number" - } - }, - { - "columnId": "saturated", - "customLabel": false, - "fieldName": "saturated", - "inMetricDimension": true, - "label": "saturated", - "meta": { - "esType": "long", - "type": "number" - } - }, - { - "columnId": "low_storage", - "customLabel": false, - "fieldName": "low_storage", - "inMetricDimension": true, - "label": "low_storage", - "meta": { - "esType": "long", - "type": "number" - } - }, - { - "columnId": "healthy", - "customLabel": false, - "fieldName": "healthy", - "inMetricDimension": true, - "label": "healthy", - "meta": { - "esType": "long", - "type": "number" - } + }, + "gridData": { + "h": 2, + "i": "hdr", + "w": 42, + "x": 0, + "y": 0 + }, + "panelIndex": "hdr", + "type": "markdown" + }, + { + "embeddableConfig": { + "attributes": { + "description": "Navigation tile — clicking opens the Kibana Dashboards library searched for “AWS OTel” dashboards in a new browser tab, carrying the current panel time range to the destination.", + "references": [], + "state": { + "adHocDataViews": { + "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", + "managed": false, + "name": "metrics-aws.rds*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", + "timeField": "@timestamp", + "title": "metrics-aws.rds*" + } + ], + "layers": { + "layer-nav-otel": { + "columns": [ + { + "columnId": "col-nav-otel", + "customLabel": true, + "fieldName": "value", + "inMetricDimension": true, + "label": "Browse other AWS OTel dashboards", + "meta": { + "esType": "keyword", + "type": "string" + } + } + ], + "index": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nROW value = \"AWS-Managed-OTel\" | KEEP value" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "0f4e60230636aaf1697f0e9d3717ae56ca807278b1a57a7b138a1e7175e0e697", + "name": "textBasedLanguages-datasource-layer-layer-nav-otel", + "type": "index-pattern" + } + ], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nROW value = \"AWS-Managed-OTel\" | KEEP value" + }, + "visualization": { + "applyColorTo": "background", + "color": "#61a2ff00", + "colorMode": "background", + "icon": "popout", + "iconAlign": "right", + "layerId": "layer-nav-otel", + "layerType": "data", + "metricAccessor": "col-nav-otel", + "primaryAlign": "left", + "primaryPosition": "bottom", + "showBar": false, + "titlesTextAlign": "left", + "titlesTextSize": "xxs", + "valueFontMode": "fit", + "valuesTextSize": "xs" + } }, + "title": "", + "version": 2, + "visualizationType": "lnsMetric" + }, + "description": "Navigation tile — clicking opens the Kibana Dashboards library searched for “AWS OTel” dashboards in a new browser tab, carrying the current panel time range to the destination.", + "drilldowns": [ { - "columnId": "timestamp", - "customLabel": false, - "fieldName": "timestamp", - "label": "timestamp", - "meta": { - "esType": "date", - "type": "date" - } + "encode_url": false, + "label": "Browse AWS OTel dashboards", + "open_in_new_tab": true, + "trigger": "on_click_value", + "type": "url_drilldown", + "url": "{{kibanaUrl}}/app/dashboards#/list?_g=(filters:!(),refreshInterval:(pause:!t,value:60000),time:(from:{{context.panel.timeRange.from}},to:{{context.panel.timeRange.to}}))\u0026s=AWS%20OTel" } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS b_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n b_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n b_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)))\n BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region\n| EVAL state = CASE(\n b_cpu IS NULL AND b_storage IS NULL AND b_conn IS NULL, \"Unknown\",\n b_cpu > 80, \"saturated\",\n b_storage < 5368709120, \"low_storage\",\n \"healthy\")\n| STATS total = COUNT(*),\n saturated = COUNT(*) WHERE state == \"saturated\",\n low_storage = COUNT(*) WHERE state == \"low_storage\",\n healthy = COUNT(*) WHERE state == \"healthy\"\n BY timestamp\n| SORT timestamp ASC" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS b_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n b_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n b_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)))\n BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region\n| EVAL state = CASE(\n b_cpu IS NULL AND b_storage IS NULL AND b_conn IS NULL, \"Unknown\",\n b_cpu > 80, \"saturated\",\n b_storage < 5368709120, \"low_storage\",\n \"healthy\")\n| STATS total = COUNT(*),\n saturated = COUNT(*) WHERE state == \"saturated\",\n low_storage = COUNT(*) WHERE state == \"low_storage\",\n healthy = COUNT(*) WHERE state == \"healthy\"\n BY timestamp\n| SORT timestamp ASC" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false - }, - "fittingFunction": "Linear", - "gridlinesVisibilitySettings": { - "x": true, - "yLeft": true, - "yRight": true - }, - "labelsOrientation": { - "x": 0, - "yLeft": 0, - "yRight": 0 - }, - "layers": [ - { - "accessors": [ - "total", - "saturated", - "low_storage", - "healthy" ], - "layerId": "4146621d-d1e8-4240-9a4c-52c6b0289dd8", - "layerType": "data", - "seriesType": "line", - "xAccessor": "timestamp", - "yConfig": [ - { - "forAccessor": "total", - "color": "#61A2FF" - }, - { - "forAccessor": "saturated", - "color": "#F6726A" - }, - { - "forAccessor": "low_storage", - "color": "#D6BF57" - }, - { - "forAccessor": "healthy", - "color": "#24C292" - } - ] - } - ], - "legend": { - "isVisible": true, - "layout": "list", - "position": "bottom" + "hide_border": true }, - "preferredSeriesType": "line", - "tickLabelsVisibilitySettings": { - "x": true, - "yLeft": true, - "yRight": true + "gridData": { + "h": 2, + "i": "nav-otel-dashboards", + "w": 6, + "x": 42, + "y": 0 }, - "valueLabels": "hide" - } + "panelIndex": "nav-otel-dashboards", + "type": "vis" }, - "title": "", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Count of RDS databases over time, classified per time bucket by health — saturated (CPU > 80%), low-storage (free storage < 5 GiB), idle (no connections), or healthy. A rising saturated series indicates spreading CPU pressure.", - "drilldowns": [], - "title": "Database count over time" - }, - "gridData": { - "h": 12, - "i": "chart-db-count", - "sectionId": "aws-rds-overview-section", - "w": 20, - "x": 28, - "y": 0 - }, - "panelIndex": "chart-db-count", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "pie-layer-chart-status-donut": { - "columns": [ - { - "columnId": "rds_state", - "customLabel": true, - "fieldName": "rds_state", - "label": "State", - "meta": { - "esType": "keyword", - "type": "string" - } - }, - { - "columnId": "databases", - "customLabel": true, - "fieldName": "databases", - "inMetricDimension": true, - "label": "Databases", - "meta": { - "esType": "long", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur > 80, \"saturated\",\n storage_cur < 5368709120, \"low-storage\",\n \"healthy\")\n| STATS databases = COUNT(*) BY rds_state = state" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur > 80, \"saturated\",\n storage_cur < 5368709120, \"low-storage\",\n \"healthy\")\n| STATS databases = COUNT(*) BY rds_state = state" - }, - "visualization": { - "layers": [ - { - "categoryDisplay": "default", - "colorMapping": { - "assignments": [ - { - "color": { - "colorCode": "#F6726A", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "saturated" + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "4146621d-d1e8-4240-9a4c-52c6b0289dd8": { + "columns": [ + { + "columnId": "total", + "customLabel": true, + "fieldName": "total", + "inMetricDimension": true, + "label": "Total", + "meta": { + "esType": "long", + "type": "number" + } + }, + { + "columnId": "saturated", + "customLabel": true, + "fieldName": "saturated", + "inMetricDimension": true, + "label": "Saturated", + "meta": { + "esType": "long", + "type": "number" + } + }, + { + "columnId": "low_storage", + "customLabel": true, + "fieldName": "low_storage", + "inMetricDimension": true, + "label": "Low storage", + "meta": { + "esType": "long", + "type": "number" + } + }, + { + "columnId": "healthy", + "customLabel": true, + "fieldName": "healthy", + "inMetricDimension": true, + "label": "Healthy", + "meta": { + "esType": "long", + "type": "number" + } + }, + { + "columnId": "timestamp", + "customLabel": false, + "fieldName": "timestamp", + "label": "timestamp", + "meta": { + "esType": "date", + "type": "date" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS b_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n b_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n b_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)))\n BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region\n| EVAL state = CASE(\n b_cpu IS NULL AND b_storage IS NULL AND b_conn IS NULL, \"Unknown\",\n b_cpu \u003e 80, \"saturated\",\n b_storage \u003c 10737418240, \"low_storage\",\n \"healthy\")\n| STATS total = COUNT(*),\n saturated = COUNT(*) WHERE state == \"saturated\",\n low_storage = COUNT(*) WHERE state == \"low_storage\",\n healthy = COUNT(*) WHERE state == \"healthy\"\n BY timestamp\n| SORT timestamp ASC" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS b_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n b_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n b_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)))\n BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region\n| EVAL state = CASE(\n b_cpu IS NULL AND b_storage IS NULL AND b_conn IS NULL, \"Unknown\",\n b_cpu \u003e 80, \"saturated\",\n b_storage \u003c 10737418240, \"low_storage\",\n \"healthy\")\n| STATS total = COUNT(*),\n saturated = COUNT(*) WHERE state == \"saturated\",\n low_storage = COUNT(*) WHERE state == \"low_storage\",\n healthy = COUNT(*) WHERE state == \"healthy\"\n BY timestamp\n| SORT timestamp ASC" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "fittingFunction": "Linear", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "total", + "saturated", + "low_storage", + "healthy" + ], + "layerId": "4146621d-d1e8-4240-9a4c-52c6b0289dd8", + "layerType": "data", + "seriesType": "line", + "xAccessor": "timestamp", + "yConfig": [ + { + "color": "#61A2FF", + "forAccessor": "total" + }, + { + "color": "#F6726A", + "forAccessor": "saturated" + }, + { + "color": "#D6BF57", + "forAccessor": "low_storage" + }, + { + "color": "#24C292", + "forAccessor": "healthy" + } + ] + } + ], + "legend": { + "isVisible": true, + "layout": "list", + "position": "bottom" + }, + "preferredSeriesType": "line", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" } - ], - "touched": true }, - { - "color": { - "colorCode": "#D6BF57", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "low-storage" + "title": "", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Count of RDS databases over time, classified per time bucket by health — saturated (CPU \u003e 80%), low-storage (free storage \u003c 5 GiB), idle (no connections), or healthy. A rising saturated series indicates spreading CPU pressure.", + "title": "Database count over time" + }, + "gridData": { + "h": 12, + "i": "chart-db-count", + "sectionId": "aws-rds-overview-section", + "w": 20, + "x": 28, + "y": 0 + }, + "panelIndex": "chart-db-count", + "type": "vis" + }, + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "pie-layer-chart-status-donut": { + "columns": [ + { + "columnId": "rds_state", + "customLabel": true, + "fieldName": "rds_state", + "label": "State", + "meta": { + "esType": "keyword", + "type": "string" + } + }, + { + "columnId": "databases", + "customLabel": true, + "fieldName": "databases", + "inMetricDimension": true, + "label": "Databases", + "meta": { + "esType": "long", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS databases = COUNT(*) BY rds_state = state" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS databases = COUNT(*) BY rds_state = state" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "colorMapping": { + "assignments": [ + { + "color": { + "colorCode": "#F6726A", + "type": "colorCode" + }, + "rules": [ + { + "type": "raw", + "value": "saturated" + } + ], + "touched": true + }, + { + "color": { + "colorCode": "#D6BF57", + "type": "colorCode" + }, + "rules": [ + { + "type": "raw", + "value": "low-storage" + } + ], + "touched": true + }, + { + "color": { + "colorCode": "#24C292", + "type": "colorCode" + }, + "rules": [ + { + "type": "raw", + "value": "healthy" + } + ], + "touched": true + }, + { + "color": { + "colorCode": "#BFDBFF", + "type": "colorCode" + }, + "rules": [ + { + "type": "raw", + "value": "Unknown" + } + ], + "touched": true + } + ], + "colorMode": { + "type": "categorical" + }, + "paletteId": "default", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rules": [ + { + "type": "other" + } + ], + "touched": false + } + ] + }, + "emptySizeRatio": 0.7, + "layerId": "pie-layer-chart-status-donut", + "layerType": "data", + "legendDisplay": "default", + "legendPosition": "right", + "metrics": [ + "databases" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "percentDecimals": 1, + "primaryGroups": [ + "rds_state" + ] + } + ], + "shape": "donut" } - ], - "touched": true }, - { - "color": { - "colorCode": "#24C292", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "healthy" + "title": "", + "version": 2, + "visualizationType": "lnsPie" + }, + "description": "Share of RDS databases by latest state — saturated (CPU \u003e 80%), low-storage (free storage \u003c 5 GiB), idle (no connections), or healthy. Uses the most recent value per database within a 5-minute freshness window.", + "title": "Databases by status" + }, + "gridData": { + "h": 12, + "i": "chart-status-donut", + "sectionId": "aws-rds-overview-section", + "w": 20, + "x": 8, + "y": 0 + }, + "panelIndex": "chart-status-donut", + "type": "vis" + }, + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "layer-kpi-total": { + "columns": [ + { + "columnId": "col-kpi-total", + "customLabel": true, + "fieldName": "total", + "inMetricDimension": true, + "label": "Databases", + "meta": { + "esType": "long", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| STATS total = COUNT(*)\n| KEEP total" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| STATS total = COUNT(*)\n| KEEP total" + }, + "visualization": { + "applyColorTo": "background", + "color": "#61a2ff00", + "colorMode": "background", + "layerId": "layer-kpi-total", + "layerType": "data", + "metricAccessor": "col-kpi-total", + "primaryAlign": "left", + "primaryPosition": "top", + "showBar": false, + "titlesTextAlign": "left" } - ], - "touched": true }, - { - "color": { - "colorCode": "#BFDBFF", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "Unknown" - } - ], - "touched": true - } - ], - "colorMode": { - "type": "categorical" - }, - "paletteId": "default", - "specialAssignments": [ - { - "color": { - "type": "loop" - }, - "rules": [ - { - "type": "other" - } - ], - "touched": false - } - ] + "title": "", + "version": 2, + "visualizationType": "lnsMetric" }, - "emptySizeRatio": 0.7, - "layerId": "pie-layer-chart-status-donut", - "layerType": "data", - "legendDisplay": "default", - "legendPosition": "right", - "metrics": [ - "databases" - ], - "nestedLegend": false, - "numberDisplay": "percent", - "percentDecimals": 1, - "primaryGroups": [ - "rds_state" - ] - } - ], - "shape": "donut" - } - }, - "title": "", - "version": 2, - "visualizationType": "lnsPie" - }, - "description": "Share of RDS databases by latest state — saturated (CPU > 80%), low-storage (free storage < 5 GiB), idle (no connections), or healthy. Uses the most recent value per database within a 5-minute freshness window.", - "drilldowns": [], - "title": "Databases by status" - }, - "gridData": { - "h": 12, - "i": "chart-status-donut", - "sectionId": "aws-rds-overview-section", - "w": 20, - "x": 8, - "y": 0 - }, - "panelIndex": "chart-status-donut", - "type": "vis" - }, - { - "embeddableConfig": { - "description": "One hexagon per RDS database, ordered worst-first with CPU-saturated or low-storage databases first. Toggle Color by between Status, CPU utilization, or Free Storage; metric views support Min, Max, Avg, and Last over the dashboard time range. Click any hexagon to filter the dashboard or open metrics for that database.", - "drilldowns": [], - "hide_title": false, - "savedVis": { - "data": { - "aggs": [], - "searchSource": { - "filter": [], - "projectRouting": "_alias:*", - "query": { - "language": "kuery", - "query": "" - } - } - }, - "description": "One hexagon per RDS database, ordered worst-first with CPU-saturated or low-storage databases first. Toggle Color by between Status, CPU utilization, or Free Storage; metric views support Min, Max, Avg, and Last over the dashboard time range. Click any hexagon to filter the dashboard or open metrics for that database.", - "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"One hexagon per RDS database, ordered worst-first with CPU-saturated or low-storage databases first. States: saturated (CPU > 80%), low-storage (< 5 GB free), healthy (passing all checks), Unknown (no metric data). Toggle Color by between Status, CPU utilization, or Free Storage; metric views support Min, Max, Avg, and Last over the dashboard time range. Click any hexagon to filter the dashboard or open metrics for that database.\",\n \"usermeta\": {\n \"x_rds_hexmap\": true\n },\n \"padding\": {\n \"top\": 10,\n \"left\": 10,\n \"right\": 10,\n \"bottom\": 15\n },\n \"data\": [\n {\n \"name\": \"ts_probe\",\n \"url\": {\n \"%type%\": \"esql\",\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"query\": \"ROW round_key = CONCAT(TO_STRING(?_tstart), \\\"|\\\", TO_STRING(?_tend)), fetched_at = NOW()\"\n }\n },\n {\n \"name\": \"raw_all\",\n \"url\": {\n \"%type%\": \"esql\",\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"query\": \"SET unmapped_fields = \\\"nullify\\\";\\nFROM metrics-aws.rds.otel-* | WHERE @timestamp >= ?_tstart AND @timestamp <= ?_tend\\n AND DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \\\"\\\"\\n AND stat == \\\"Average\\\" | STATS cpu_min = MIN(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n cpu_max = MAX(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n cpu_avg = AVG(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n cpu_last = LAST(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`, @timestamp)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n st_min = MIN(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL,\\n st_max = MAX(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL,\\n st_avg = AVG(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL,\\n st_last = LAST(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, @timestamp)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL\\n BY entity_id = DBInstanceIdentifier\\n, cloud.region\\n| EVAL storage_min = st_min / 1073741824,\\n storage_max = st_max / 1073741824,\\n storage_avg = st_avg / 1073741824,\\n storage_last = st_last / 1073741824,\\n status_num = CASE(\\n cpu_last IS NULL AND st_last IS NULL, 3,\\n cpu_last > 80, 0,\\n st_last < 5368709120, 1,\\n 2),\\n status_label = CASE(\\n cpu_last IS NULL AND st_last IS NULL, \\\"Unknown\\\",\\n cpu_last > 80, \\\"saturated\\\",\\n st_last < 5368709120, \\\"low-storage\\\",\\n \\\"healthy\\\"),\\n severity_rank = status_num,\\n round_key = CONCAT(TO_STRING(?_tstart), \\\"|\\\", TO_STRING(?_tend)),\\n fetched_at = NOW()\\n| KEEP entity_id, status_num, status_label, severity_rank,\\n cpu_min, cpu_max, cpu_avg, cpu_last,\\n storage_min, storage_max, storage_avg, storage_last,\\n round_key, fetched_at\\n| LIMIT 10000\"\n }\n },\n {\n \"name\": \"ranked_status\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"severity_rank\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_min\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_min == null ? 1e12 : -datum.cpu_min * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_max\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_max == null ? 1e12 : -datum.cpu_max * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_avg\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_avg == null ? 1e12 : -datum.cpu_avg * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_last\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_last == null ? 1e12 : -datum.cpu_last * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_min\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_min == null ? 1e12 : datum.storage_min * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_max\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_max == null ? 1e12 : datum.storage_max * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_avg\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_avg == null ? 1e12 : datum.storage_avg * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_last\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_last == null ? 1e12 : datum.storage_last * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"active\",\n \"values\": [],\n \"on\": [\n {\n \"trigger\": \"ts_round !== '' && active_round !== '' && active_round !== ts_round\",\n \"remove\": \"true\"\n },\n {\n \"trigger\": \"metric === 'status' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_status')\"\n },\n {\n \"trigger\": \"metric === 'cpu' && effective_agg === 'min' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_min')\"\n },\n {\n \"trigger\": \"metric === 'cpu' && effective_agg === 'max' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_max')\"\n },\n {\n \"trigger\": \"metric === 'cpu' && effective_agg === 'avg' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_avg')\"\n },\n {\n \"trigger\": \"metric === 'cpu' && effective_agg === 'last' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_last')\"\n },\n {\n \"trigger\": \"metric === 'storage' && effective_agg === 'min' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_min')\"\n },\n {\n \"trigger\": \"metric === 'storage' && effective_agg === 'max' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_max')\"\n },\n {\n \"trigger\": \"metric === 'storage' && effective_agg === 'avg' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_avg')\"\n },\n {\n \"trigger\": \"metric === 'storage' && effective_agg === 'last' && len_raw > 0 && raw_round === ts_round && ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_last')\"\n }\n ]\n },\n {\n \"name\": \"entities\",\n \"source\": \"active\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"active_val\",\n \"expr\": \"metric=='status' ? null : (metric=='cpu' ? (effective_agg=='min' ? datum.cpu_min : effective_agg=='max' ? datum.cpu_max : effective_agg=='avg' ? datum.cpu_avg : effective_agg=='last' ? datum.cpu_last : null) : (metric=='storage' ? (effective_agg=='min' ? datum.storage_min : effective_agg=='max' ? datum.storage_max : effective_agg=='avg' ? datum.storage_avg : effective_agg=='last' ? datum.storage_last : null) : null))\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"index0\",\n \"expr\": \"datum.active_rank - 1\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"col\",\n \"expr\": \"datum.index0 % gridCols\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"row\",\n \"expr\": \"floor(datum.index0 / gridCols)\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"x\",\n \"expr\": \"datum.col * gapX + (datum.row % 2 == 1 ? gapX / 2 : 0) + hexR + 5\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"y\",\n \"expr\": \"datum.row * gapY + hexR + 5 + hexOffsetY\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"hexSize\",\n \"expr\": \"hexR * hexR * 3.46\"\n }\n ]\n },\n {\n \"name\": \"status_counts\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"groupby\": [\n \"status_num\"\n ],\n \"ops\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ]\n }\n ]\n },\n {\n \"name\": \"status_legend\",\n \"values\": [\n {\n \"label\": \"Saturated\",\n \"val\": 0\n },\n {\n \"label\": \"Low storage\",\n \"val\": 1\n },\n {\n \"label\": \"Healthy\",\n \"val\": 2\n },\n {\n \"label\": \"Unknown\",\n \"val\": 3\n }\n ],\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"status_counts\",\n \"key\": \"status_num\",\n \"fields\": [\n \"val\"\n ],\n \"values\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ],\n \"default\": 0\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"idx\"\n ]\n }\n ]\n },\n {\n \"name\": \"cpu_counts\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"v\",\n \"expr\": \"agg == 'min' ? datum.cpu_min : agg == 'max' ? datum.cpu_max : agg == 'avg' ? datum.cpu_avg : agg == 'last' ? datum.cpu_last : null\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"bucket\",\n \"expr\": \"datum.v == null ? 3 : (datum.v >= 80 ? 2 : datum.v >= 60 ? 1 : 0)\"\n },\n {\n \"type\": \"aggregate\",\n \"groupby\": [\n \"bucket\"\n ],\n \"ops\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ]\n }\n ]\n },\n {\n \"name\": \"storage_counts\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"v\",\n \"expr\": \"agg == 'min' ? datum.storage_min : agg == 'max' ? datum.storage_max : agg == 'avg' ? datum.storage_avg : agg == 'last' ? datum.storage_last : null\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"bucket\",\n \"expr\": \"datum.v == null ? 3 : (datum.v >= 20 ? 2 : datum.v >= 5 ? 1 : 0)\"\n },\n {\n \"type\": \"aggregate\",\n \"groupby\": [\n \"bucket\"\n ],\n \"ops\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ]\n }\n ]\n },\n {\n \"name\": \"cpu_legend_stops\",\n \"values\": [\n {\n \"label\": \"≥ 80%\",\n \"val\": 90,\n \"bucket\": 2,\n \"is_nodata\": false\n },\n {\n \"label\": \"60 – 79%\",\n \"val\": 70,\n \"bucket\": 1,\n \"is_nodata\": false\n },\n {\n \"label\": \"< 60%\",\n \"val\": 0,\n \"bucket\": 0,\n \"is_nodata\": false\n },\n {\n \"label\": \"Unknown\",\n \"val\": null,\n \"bucket\": 3,\n \"is_nodata\": true\n }\n ],\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"cpu_counts\",\n \"key\": \"bucket\",\n \"fields\": [\n \"bucket\"\n ],\n \"values\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ],\n \"default\": 0\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"idx\"\n ]\n }\n ]\n },\n {\n \"name\": \"storage_legend_stops\",\n \"values\": [\n {\n \"label\": \"< 5 GB\",\n \"val\": 2,\n \"bucket\": 0,\n \"is_nodata\": false\n },\n {\n \"label\": \"5 – 19 GB\",\n \"val\": 10,\n \"bucket\": 1,\n \"is_nodata\": false\n },\n {\n \"label\": \"≥ 20 GB\",\n \"val\": 50,\n \"bucket\": 2,\n \"is_nodata\": false\n },\n {\n \"label\": \"Unknown\",\n \"val\": null,\n \"bucket\": 3,\n \"is_nodata\": true\n }\n ],\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"storage_counts\",\n \"key\": \"bucket\",\n \"fields\": [\n \"bucket\"\n ],\n \"values\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ],\n \"default\": 0\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"idx\"\n ]\n }\n ]\n },\n {\n \"name\": \"spinner_dots\",\n \"values\": [\n {\n \"i\": 0\n },\n {\n \"i\": 1\n },\n {\n \"i\": 2\n },\n {\n \"i\": 3\n },\n {\n \"i\": 4\n },\n {\n \"i\": 5\n },\n {\n \"i\": 6\n },\n {\n \"i\": 7\n }\n ]\n },\n {\n \"name\": \"pills\",\n \"values\": [\n {\n \"id\": \"status\",\n \"label\": \"Status\",\n \"group\": \"metric\",\n \"x\": 69,\n \"w\": 48,\n \"available_aggs\": [],\n \"default_agg\": \"last\"\n },\n {\n \"id\": \"cpu\",\n \"label\": \"CPU %\",\n \"group\": \"metric\",\n \"x\": 125,\n \"w\": 58,\n \"available_aggs\": [\n \"min\",\n \"max\",\n \"avg\",\n \"last\"\n ],\n \"default_agg\": \"last\"\n },\n {\n \"id\": \"storage\",\n \"label\": \"Free Storage (GB)\",\n \"group\": \"metric\",\n \"x\": 191,\n \"w\": 128,\n \"available_aggs\": [\n \"min\",\n \"max\",\n \"avg\",\n \"last\"\n ],\n \"default_agg\": \"last\"\n },\n {\n \"id\": \"min\",\n \"label\": \"Min\",\n \"group\": \"agg\",\n \"x\": 425,\n \"w\": 36,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"max\",\n \"label\": \"Max\",\n \"group\": \"agg\",\n \"x\": 465,\n \"w\": 36,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"avg\",\n \"label\": \"Avg\",\n \"group\": \"agg\",\n \"x\": 505,\n \"w\": 36,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"last\",\n \"label\": \"Last\",\n \"group\": \"agg\",\n \"x\": 545,\n \"w\": 40,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"sum\",\n \"label\": \"Sum\",\n \"group\": \"agg\",\n \"x\": 589,\n \"w\": 40,\n \"valid_for\": []\n }\n ]\n },\n {\n \"name\": \"menu_items_data\",\n \"values\": [\n {\n \"id\": \"filter\",\n \"label\": \"Filter dashboard by this database\",\n \"idx\": 0\n },\n {\n \"id\": \"metrics\",\n \"label\": \"View database metrics in Discover\",\n \"idx\": 1\n }\n ]\n },\n {\n \"name\": \"menu_visible\",\n \"values\": [\n {\n \"_\": 0\n }\n ],\n \"transform\": [\n {\n \"type\": \"filter\",\n \"expr\": \"selected_entity != null\"\n }\n ]\n },\n {\n \"name\": \"menu_items_visible\",\n \"source\": \"menu_items_data\",\n \"transform\": [\n {\n \"type\": \"filter\",\n \"expr\": \"selected_entity != null\"\n }\n ]\n }\n ],\n \"signals\": [\n {\n \"name\": \"metric\",\n \"value\": \"status\",\n \"on\": [\n {\n \"events\": \"@pill_bg:click\",\n \"update\": \"datum.group === 'metric' ? datum.id : metric\"\n }\n ]\n },\n {\n \"name\": \"agg\",\n \"value\": \"last\",\n \"on\": [\n {\n \"events\": \"@pill_bg:click\",\n \"update\": \"datum.group === 'agg' && metric !== 'status' && indexof(datum.valid_for, metric) >= 0 ? datum.id : ( datum.group === 'metric' && datum.id !== 'status' ? (indexof(datum.available_aggs, agg) >= 0 ? agg : datum.default_agg) : agg )\"\n }\n ]\n },\n {\n \"name\": \"effective_agg\",\n \"update\": \"metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'\"\n },\n {\n \"name\": \"groupHeaderH\",\n \"value\": 20\n },\n {\n \"name\": \"groupGap\",\n \"value\": 10\n },\n {\n \"name\": \"group_by\",\n \"value\": \"none\"\n },\n {\n \"name\": \"len_raw\",\n \"update\": \"length(data('raw_all'))\"\n },\n {\n \"name\": \"len_active\",\n \"update\": \"length(data('active'))\"\n },\n {\n \"name\": \"ts_round\",\n \"update\": \"data('ts_probe')[0] ? data('ts_probe')[0].round_key : ''\"\n },\n {\n \"name\": \"time_from\",\n \"update\": \"ts_round !== '' && indexof(ts_round, '|') > 0 ? slice(ts_round, 0, indexof(ts_round, '|')) : ''\"\n },\n {\n \"name\": \"time_to\",\n \"update\": \"ts_round !== '' && indexof(ts_round, '|') > 0 ? slice(ts_round, indexof(ts_round, '|') + 1) : ''\"\n },\n {\n \"name\": \"g_param\",\n \"update\": \"time_from !== '' && time_to !== '' ? '_g=(time:(from:%27' + time_from + '%27,to:%27' + time_to + '%27))&' : ''\"\n },\n {\n \"name\": \"raw_round\",\n \"update\": \"data('raw_all')[0] ? data('raw_all')[0].round_key : ''\"\n },\n {\n \"name\": \"active_round\",\n \"update\": \"raw_round\"\n },\n {\n \"name\": \"raw_fetched_str\",\n \"update\": \"data('raw_all')[0] ? data('raw_all')[0].fetched_at : ''\"\n },\n {\n \"name\": \"active_fetched\",\n \"update\": \"raw_fetched_str !== '' ? toDate(raw_fetched_str) : 0\"\n },\n {\n \"name\": \"tick\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": {\n \"type\": \"timer\",\n \"throttle\": 100\n },\n \"update\": \"now()\"\n }\n ]\n },\n {\n \"name\": \"url_change_at\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"hashchange\"\n },\n \"update\": \"now()\"\n },\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"popstate\"\n },\n \"update\": \"now()\"\n }\n ]\n },\n {\n \"name\": \"fetch_tracker\",\n \"init\": \"{seen: 0, arrived_at: 0}\",\n \"on\": [\n {\n \"events\": {\n \"signal\": \"tick\"\n },\n \"update\": \"active_fetched > 0 && active_fetched !== fetch_tracker.seen ? {seen: active_fetched, arrived_at: tick} : fetch_tracker\"\n }\n ]\n },\n {\n \"name\": \"loading_raw\",\n \"update\": \"len_active === 0 || ts_round === '' || active_round === '' || active_round !== ts_round || (url_change_at > 0 && fetch_tracker.arrived_at < url_change_at)\"\n },\n {\n \"name\": \"loading_started_at\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": {\n \"signal\": \"tick\"\n },\n \"update\": \"loading_raw ? (loading_started_at === 0 ? tick : loading_started_at) : 0\"\n }\n ]\n },\n {\n \"name\": \"loading_elapsed\",\n \"update\": \"loading_started_at > 0 ? tick - loading_started_at : 0\"\n },\n {\n \"name\": \"no_data\",\n \"update\": \"loading_raw && ts_round !== '' && len_raw === 0 && loading_elapsed > 2000\"\n },\n {\n \"name\": \"loading\",\n \"update\": \"loading_raw && !no_data\"\n },\n {\n \"name\": \"loading_timeout\",\n \"update\": \"loading && loading_elapsed > 15000\"\n },\n {\n \"name\": \"total_entities\",\n \"update\": \"len_raw\"\n },\n {\n \"name\": \"legendW\",\n \"value\": 138\n },\n {\n \"name\": \"buttonsH\",\n \"value\": 34\n },\n {\n \"name\": \"availW\",\n \"update\": \"width - 20 - legendW\"\n },\n {\n \"name\": \"n_groups\",\n \"value\": 0\n },\n {\n \"name\": \"availH\",\n \"update\": \"height - 20 - buttonsH - (group_by !== 'none' ? n_groups * (groupHeaderH + groupGap) : 0)\"\n },\n {\n \"name\": \"hexOffsetY\",\n \"update\": \"buttonsH\"\n },\n {\n \"name\": \"idealCols\",\n \"update\": \"total_entities > 0 && availH > 0 ? max(1, round(sqrt(total_entities * (availW / availH)))) : 1\"\n },\n {\n \"name\": \"idealRows\",\n \"update\": \"max(1, ceil(total_entities / idealCols))\"\n },\n {\n \"name\": \"hexRInitial\",\n \"update\": \"min(availW / (idealCols * 2 + 0), availH / (idealRows * 2 + 0))\"\n },\n {\n \"name\": \"maxColsAtHexR\",\n \"update\": \"max(idealCols, floor(availW / (max(3, hexRInitial) * 2)))\"\n },\n {\n \"name\": \"maxColsAtMinR\",\n \"update\": \"max(1, floor(availW / (3 * 2)))\"\n },\n {\n \"name\": \"gridCols\",\n \"update\": \"max(1, min(total_entities, min(maxColsAtHexR, maxColsAtMinR)))\"\n },\n {\n \"name\": \"gridRows\",\n \"update\": \"group_by === 'none' ? max(1, ceil(total_entities / gridCols)) : max(1, ceil(total_entities / gridCols) + max(0, n_groups - 1))\"\n },\n {\n \"name\": \"rByWidth\",\n \"update\": \"availW / (gridCols * 1.76 + 0.88)\"\n },\n {\n \"name\": \"rByHeight\",\n \"update\": \"availH / (gridRows * 1.54 + 0.92)\"\n },\n {\n \"name\": \"hexR\",\n \"update\": \"max(3, min(90, min(rByWidth, rByHeight)))\"\n },\n {\n \"name\": \"gapX\",\n \"update\": \"hexR * 1.76\"\n },\n {\n \"name\": \"gapY\",\n \"update\": \"hexR * 1.54\"\n },\n {\n \"name\": \"legendX\",\n \"update\": \"width - legendW + 4\"\n },\n {\n \"name\": \"tooltip\",\n \"value\": {},\n \"on\": [\n {\n \"events\": \"@hexagons:mouseover\",\n \"update\": \"datum\"\n },\n {\n \"events\": \"@hexagons:mouseout\",\n \"update\": \"{}\"\n }\n ]\n },\n {\n \"name\": \"selected_entity\",\n \"value\": null,\n \"on\": [\n {\n \"events\": \"@hexagons:click\",\n \"update\": \"{id: datum.entity_id, x: datum.x, y: datum.y}\"\n },\n {\n \"events\": \"@menu_backdrop:click\",\n \"update\": \"null\"\n },\n {\n \"events\": \"@menu_item_bg:click\",\n \"update\": \"null\"\n }\n ]\n },\n {\n \"name\": \"menu_x\",\n \"update\": \"selected_entity ? ((selected_entity.x + hexR + 4 + 248 > width - legendW - 4) ? max(4, selected_entity.x - hexR - 248 - 4) : max(4, selected_entity.x + hexR + 4)) : 0\"\n },\n {\n \"name\": \"menu_y\",\n \"update\": \"selected_entity ? max(buttonsH + 4, min(selected_entity.y - 75, height - 90 - 4)) : 0\"\n }\n ],\n \"scales\": [\n {\n \"name\": \"status_color\",\n \"type\": \"ordinal\",\n \"domain\": [\n 0,\n 1,\n 2,\n 3\n ],\n \"range\": [\n \"#F6726A\",\n \"#D6BF57\",\n \"#24C292\",\n \"#BFDBFF\"\n ]\n },\n {\n \"name\": \"cpu_color\",\n \"type\": \"threshold\",\n \"domain\": [\n 60,\n 80\n ],\n \"range\": [\n \"#24C292\",\n \"#D6BF57\",\n \"#F6726A\"\n ]\n },\n {\n \"name\": \"storage_color\",\n \"type\": \"threshold\",\n \"domain\": [\n 5,\n 20\n ],\n \"range\": [\n \"#F6726A\",\n \"#D6BF57\",\n \"#24C292\"\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 5\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"value\": \"Color by:\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": 600\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 345\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"value\": \"Aggregation:\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": 600\n },\n \"fill\": {\n \"value\": \"#838C99\"\n },\n \"opacity\": {\n \"signal\": \"(metric === 'cpu' || metric === 'storage') ? 1 : 0.5\"\n }\n }\n }\n },\n {\n \"name\": \"pill_bg\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"pills\"\n },\n \"encode\": {\n \"enter\": {},\n \"update\": {\n \"x\": {\n \"field\": \"x\"\n },\n \"x2\": {\n \"signal\": \"datum.x + datum.w\"\n },\n \"y\": {\n \"value\": 6\n },\n \"y2\": {\n \"value\": 28\n },\n \"cornerRadius\": {\n \"value\": 4\n },\n \"fill\": {\n \"signal\": \"((datum.group === 'metric' && datum.id === metric) || (datum.group === 'agg' && datum.id === effective_agg)) ? '#0077CC' : 'transparent'\"\n },\n \"stroke\": {\n \"signal\": \"((datum.group === 'metric' && datum.id === metric) || (datum.group === 'agg' && datum.id === effective_agg)) ? '#0064B0' : '#838C99'\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"opacity\": {\n \"signal\": \"(datum.group === 'agg' && (!(metric === 'cpu' || metric === 'storage') || indexof(datum.valid_for, metric) < 0)) ? 0.5 : 1\"\n },\n \"cursor\": {\n \"signal\": \"(datum.group === 'agg' && (!(metric === 'cpu' || metric === 'storage') || indexof(datum.valid_for, metric) < 0)) ? 'default' : 'pointer'\"\n }\n }\n }\n },\n {\n \"name\": \"pill_label\",\n \"type\": \"text\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"pills\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"datum.x + datum.w / 2\"\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"field\": \"label\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"signal\": \"((datum.group === 'metric' && datum.id === metric) || (datum.group === 'agg' && datum.id === effective_agg)) ? '#FFFFFF' : '#838C99'\"\n },\n \"opacity\": {\n \"signal\": \"(datum.group === 'agg' && (!(metric === 'cpu' || metric === 'storage') || indexof(datum.valid_for, metric) < 0)) ? 0.5 : 1\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"width - legendW - 4\"\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"signal\": \"total_entities === 0 ? '' : (total_entities < 10000 ? 'Showing ' + total_entities + ' databases' : 'Showing top 10,000 databases (limit reached)')\"\n },\n \"align\": {\n \"value\": \"right\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n }\n }\n },\n {\n \"name\": \"hexagons\",\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"entities\"\n },\n \"encode\": {\n \"enter\": {\n \"cursor\": {\n \"value\": \"pointer\"\n }\n },\n \"update\": {\n \"x\": {\n \"field\": \"x\"\n },\n \"y\": {\n \"field\": \"y\"\n },\n \"size\": {\n \"field\": \"hexSize\"\n },\n \"fill\": [\n {\n \"test\": \"metric == 'status'\",\n \"scale\": \"status_color\",\n \"field\": \"status_num\"\n },\n {\n \"test\": \"datum.active_val == null\",\n \"value\": \"#BFDBFF\"\n },\n {\n \"test\": \"metric == 'cpu'\",\n \"scale\": \"cpu_color\",\n \"field\": \"active_val\"\n },\n {\n \"test\": \"metric == 'storage'\",\n \"scale\": \"storage_color\",\n \"field\": \"active_val\"\n },\n {\n \"value\": \"#BFDBFF\"\n }\n ],\n \"fillOpacity\": {\n \"value\": 0.92\n },\n \"shape\": {\n \"value\": \"M0,-1L0.866,-0.5L0.866,0.5L0,1L-0.866,0.5L-0.866,-0.5Z\"\n },\n \"strokeWidth\": [\n {\n \"test\": \"selected_entity && selected_entity.id === datum.entity_id\",\n \"value\": 3.5\n },\n {\n \"test\": \"tooltip.entity_id === datum.entity_id\",\n \"value\": 3\n },\n {\n \"value\": 1\n }\n ],\n \"stroke\": [\n {\n \"test\": \"selected_entity && selected_entity.id === datum.entity_id\",\n \"value\": \"#0077CC\"\n },\n {\n \"test\": \"tooltip.entity_id === datum.entity_id\",\n \"value\": \"#222\"\n },\n {\n \"value\": \"#FFFFFF\"\n }\n ],\n \"strokeOpacity\": [\n {\n \"test\": \"selected_entity && selected_entity.id === datum.entity_id\",\n \"value\": 1\n },\n {\n \"test\": \"tooltip.entity_id === datum.entity_id\",\n \"value\": 1\n },\n {\n \"value\": 0.3\n }\n ]\n }\n }\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"legendX\"\n },\n \"y\": {\n \"signal\": \"buttonsH + 8\"\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"text\": {\n \"value\": \"Status\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"opacity\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"status_legend\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 6\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"size\": {\n \"value\": 110\n },\n \"shape\": {\n \"value\": \"circle\"\n },\n \"fill\": {\n \"scale\": \"status_color\",\n \"field\": \"val\"\n }\n },\n \"update\": {\n \"opacity\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": {\n \"data\": \"status_legend\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 18\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"datum.label + ' (' + datum.count + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"legendX\"\n },\n \"y\": {\n \"signal\": \"buttonsH + 8\"\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"'CPU% (' + agg + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"cpu_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 6\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"size\": {\n \"value\": 110\n },\n \"shape\": {\n \"value\": \"circle\"\n }\n },\n \"update\": {\n \"fill\": [\n {\n \"test\": \"datum.is_nodata\",\n \"value\": \"#BFDBFF\"\n },\n {\n \"scale\": \"cpu_color\",\n \"field\": \"val\"\n }\n ],\n \"opacity\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": {\n \"data\": \"cpu_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 18\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"datum.label + ' (' + datum.count + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"legendX\"\n },\n \"y\": {\n \"signal\": \"buttonsH + 8\"\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"'Free storage (' + agg + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"storage_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 6\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"size\": {\n \"value\": 110\n },\n \"shape\": {\n \"value\": \"circle\"\n }\n },\n \"update\": {\n \"fill\": [\n {\n \"test\": \"datum.is_nodata\",\n \"value\": \"#BFDBFF\"\n },\n {\n \"scale\": \"storage_color\",\n \"field\": \"val\"\n }\n ],\n \"opacity\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": {\n \"data\": \"storage_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 18\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"datum.label + ' (' + datum.count + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"tooltip.x + 18 + 290 > width - legendW - 10 ? max(tooltip.x - 18 - 290, 5) : tooltip.x + 18\"\n },\n \"y\": {\n \"signal\": \"max(tooltip.y - 30, 5)\"\n },\n \"width\": {\n \"value\": 290\n },\n \"height\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) <= 36 ? 110 : 124) : 110\"\n },\n \"opacity\": [\n {\n \"test\": \"tooltip.entity_id\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ],\n \"fill\": {\n \"value\": \"#0E1728\"\n },\n \"stroke\": {\n \"value\": \"#2A3144\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"cornerRadius\": {\n \"value\": 8\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"value\": 12\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) <= 36 ? [tooltip.entity_id] : [slice(tooltip.entity_id, 0, 36), slice(tooltip.entity_id, 36)]) : ['']\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"lineHeight\": {\n \"value\": 14\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#fff\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) <= 36 ? 36 : 50) : 36\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'Status: ' + tooltip.status_label : ''\"\n },\n \"fontSize\": {\n \"value\": 10\n },\n \"fontWeight\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": \"bold\"\n },\n {\n \"value\": \"normal\"\n }\n ],\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"signal\": \"metric == 'status' ? (tooltip.status_num == 0 ? '#F6726A' : tooltip.status_num == 1 ? '#D6BF57' : tooltip.status_num == 2 ? '#24C292' : tooltip.status_num == 3 ? '#BFDBFF' : '#BFDBFF') : '#9da4b3'\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) <= 36 ? 50 : 64) : 50\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'CPU% (' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last') + '): ' + (tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] != null ? format(tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))], '.1f') + '%' : 'Unknown') : ''\"\n },\n \"fontSize\": {\n \"value\": 10\n },\n \"fontWeight\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": \"bold\"\n },\n {\n \"value\": \"normal\"\n }\n ],\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"signal\": \"metric == 'cpu' ? (tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] == null ? '#9da4b3' : tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] >= 80 ? '#F6726A' : tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] >= 60 ? '#D6BF57' : '#24C292') : '#9da4b3'\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) <= 36 ? 64 : 78) : 64\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'Free Storage (' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last') + '): ' + (tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] != null ? format(tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))], '.1f') + ' GB' : 'Unknown') : ''\"\n },\n \"fontSize\": {\n \"value\": 10\n },\n \"fontWeight\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": \"bold\"\n },\n {\n \"value\": \"normal\"\n }\n ],\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"signal\": \"metric == 'storage' ? (tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] == null ? '#9da4b3' : tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] >= 20 ? '#24C292' : tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] >= 5 ? '#D6BF57' : '#F6726A') : '#9da4b3'\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) <= 36 ? 82 : 96) : 82\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? '› Click for actions' : ''\"\n },\n \"fontSize\": {\n \"value\": 9\n },\n \"fontStyle\": {\n \"value\": \"italic\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"value\": \"#9da4b3\"\n }\n }\n }\n }\n ]\n },\n {\n \"type\": \"rect\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2 - 120\"\n },\n \"x2\": {\n \"signal\": \"(width - legendW) / 2 + 120\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 - 45\"\n },\n \"y2\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 + 45\"\n },\n \"fill\": {\n \"value\": \"#1A1C21\"\n },\n \"fillOpacity\": {\n \"signal\": \"(loading || loading_timeout) ? 0.92 : 0\"\n },\n \"stroke\": {\n \"value\": \"#838C99\"\n },\n \"strokeOpacity\": {\n \"signal\": \"(loading || loading_timeout) ? 0.4 : 0\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"cornerRadius\": {\n \"value\": 12\n }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"spinner_dots\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2 + 18 * cos(datum.i * PI / 4 - PI / 2)\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 - 8 + 18 * sin(datum.i * PI / 4 - PI / 2)\"\n },\n \"size\": {\n \"value\": 70\n },\n \"shape\": {\n \"value\": \"circle\"\n },\n \"fill\": {\n \"value\": \"#0077CC\"\n },\n \"opacity\": {\n \"signal\": \"loading ? 0.15 + 0.85 * (1 - (((floor(tick / 100) % 8) - datum.i + 8) % 8) / 7) : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 + 28\"\n },\n \"text\": {\n \"value\": \"Loading data…\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"value\": \"#FFFFFF\"\n },\n \"opacity\": {\n \"signal\": \"loading && !loading_timeout ? 1 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 + 28\"\n },\n \"text\": {\n \"value\": \"Still loading… (taking longer than usual)\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"value\": \"#FFFFFF\"\n },\n \"opacity\": {\n \"signal\": \"loading_timeout ? 1 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2\"\n },\n \"text\": {\n \"value\": \"No databases for the selected time range\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 13\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"value\": \"#838C99\"\n },\n \"opacity\": {\n \"signal\": \"no_data ? 1 : 0\"\n }\n }\n }\n },\n {\n \"name\": \"menu_backdrop\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"enter\": {\n \"cursor\": {\n \"value\": \"default\"\n }\n },\n \"update\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"x2\": {\n \"signal\": \"width\"\n },\n \"y2\": {\n \"signal\": \"height\"\n },\n \"fill\": {\n \"value\": \"#000000\"\n },\n \"fillOpacity\": {\n \"value\": 0\n }\n }\n }\n },\n {\n \"name\": \"menu_box\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x\"\n },\n \"y\": {\n \"signal\": \"menu_y\"\n },\n \"width\": {\n \"value\": 248\n },\n \"height\": {\n \"value\": 90\n },\n \"fill\": {\n \"value\": \"#0E1728\"\n },\n \"stroke\": {\n \"value\": \"#2A3144\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"cornerRadius\": {\n \"value\": 6\n }\n }\n }\n },\n {\n \"name\": \"menu_header\",\n \"type\": \"text\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x + 12\"\n },\n \"y\": {\n \"signal\": \"menu_y + 13.0\"\n },\n \"text\": {\n \"signal\": \"selected_entity ? 'Database: ' + (length(selected_entity.id) > 30 ? slice(selected_entity.id, 0, 28) + '…' : selected_entity.id) : ''\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": 600\n },\n \"fill\": {\n \"value\": \"#98A2B3\"\n }\n }\n }\n },\n {\n \"name\": \"menu_separator\",\n \"type\": \"rule\",\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x + 8\"\n },\n \"x2\": {\n \"signal\": \"menu_x + 240\"\n },\n \"y\": {\n \"signal\": \"menu_y + 26\"\n },\n \"stroke\": {\n \"value\": \"#2A3144\"\n },\n \"strokeWidth\": {\n \"value\": 1\n }\n }\n }\n },\n {\n \"name\": \"menu_item_bg\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"menu_items_visible\"\n },\n \"encode\": {\n \"enter\": {\n \"cursor\": {\n \"value\": \"pointer\"\n }\n },\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x\"\n },\n \"y\": {\n \"signal\": \"menu_y + 30 + datum.idx * 30\"\n },\n \"width\": {\n \"value\": 248\n },\n \"height\": {\n \"value\": 30\n },\n \"fill\": {\n \"value\": \"#0E1728\"\n },\n \"href\": {\n \"signal\": \"selected_entity ? (datum.id === 'filter' ? ('/app/dashboards#/view/aws_rds_otel-c92e1216-83f6-4de7-9d7f-1bcb42d5988a?' + g_param + '_a=(filters:!((meta:(alias:!n,disabled:!f,index:%27metrics-*%27,key:DBInstanceIdentifier,negate:!f,params:(query:%27' + selected_entity.id + '%27),type:phrase),query:(match_phrase:(DBInstanceIdentifier:%27' + selected_entity.id + '%27)))),query:(language:kuery,query:%27%27))') : datum.id === 'metrics' ? ('/app/discover#/?_g=(time:(from:%27' + time_from + '%27,to:%27' + time_to + '%27))&_a=(dataSource:(dataViewId:%27metrics-*%27,type:dataView),query:(language:kuery,query:%27' + 'DBInstanceIdentifier:%22' + selected_entity.id + '%22' + '%27))') : '') : ''\"\n }\n },\n \"hover\": {\n \"fill\": {\n \"value\": \"#1A2640\"\n }\n }\n }\n },\n {\n \"name\": \"menu_item_label\",\n \"type\": \"text\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"menu_items_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x + 14\"\n },\n \"y\": {\n \"signal\": \"menu_y + 30 + datum.idx * 30 + 15.0\"\n },\n \"text\": {\n \"field\": \"label\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fill\": {\n \"value\": \"#DFE5EF\"\n }\n }\n }\n }\n ],\n \"background\": \"transparent\",\n \"autosize\": {\n \"type\": \"fit\",\n \"contains\": \"padding\"\n }\n}" - }, - "title": "RDS databases — hexagon map", - "type": "vega", - "uiState": {} - }, - "title": "RDS databases — hexagon map (click an hex for actions)" - }, - "gridData": { - "x": 0, - "y": 0, - "w": 48, - "h": 15, - "i": "rds-hexmap-0001-aaaa-bbbb-ccccdddd0000", - "sectionId": "aws-rds-list-section" - }, - "panelIndex": "rds-hexmap-0001-aaaa-bbbb-ccccdddd0000", - "type": "legacy_vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Total number of RDS databases — distinct DB instance identifiers reporting metrics in the latest collected data for the selected time range.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "layer-kpi-total": { - "columns": [ - { - "columnId": "col-kpi-total", - "customLabel": true, - "fieldName": "total", - "inMetricDimension": true, - "label": "Databases", - "meta": { - "esType": "long", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND stat IN (\"Average\", \"Maximum\") | STATS last_seen = MAX(@timestamp) BY DBInstanceIdentifier, cloud.region | INLINE STATS latest = MAX(last_seen) | WHERE DATE_DIFF(\"minutes\", last_seen, latest) <= 5 | STATS total = COUNT(*) | KEEP total" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "textBasedLanguages-datasource-layer-layer-kpi-total", - "type": "index-pattern" - } - ], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND stat IN (\"Average\", \"Maximum\") | STATS last_seen = MAX(@timestamp) BY DBInstanceIdentifier, cloud.region | INLINE STATS latest = MAX(last_seen) | WHERE DATE_DIFF(\"minutes\", last_seen, latest) <= 5 | STATS total = COUNT(*) | KEEP total" - }, - "visualization": { - "applyColorTo": "background", - "color": "#61a2ff00", - "colorMode": "background", - "layerId": "layer-kpi-total", - "layerType": "data", - "metricAccessor": "col-kpi-total", - "primaryAlign": "left", - "primaryPosition": "top", - "showBar": false, - "titlesTextAlign": "left" - } - }, - "title": "", - "version": 2, - "visualizationType": "lnsMetric" - }, - "description": "Total number of RDS databases — distinct DB instance identifiers reporting metrics in the latest collected data for the selected time range.", - "hide_title": true, - "title": "" - }, - "gridData": { - "h": 6, - "i": "kpi-total", - "sectionId": "aws-rds-overview-section", - "w": 4, - "x": 0, - "y": 0 - }, - "panelIndex": "kpi-total", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Number of low-storage RDS databases — those whose free storage dropped below 5 GiB, within a 5-minute freshness window. At risk of running out of disk. (Aurora instances are excluded — their storage auto-scales.)", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "layer-kpi-low-storage": { - "columns": [ - { - "columnId": "col-kpi-low-storage", - "customLabel": true, - "fieldName": "low_storage", - "inMetricDimension": true, - "label": "Low storage", - "meta": { - "esType": "long", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND stat IN (\"Maximum\", \"Minimum\") | STATS cpu_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL)), conn_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)), storage_cur = MIN(CASE(stat == \"Minimum\", `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)), last_seen = MAX(@timestamp) BY DBInstanceIdentifier, cloud.region | INLINE STATS latest_global = MAX(last_seen) | WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5 | EVAL state = CASE(cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\", cpu_cur > 80, \"saturated\", storage_cur < 5368709120, \"low-storage\", \"healthy\") | STATS low_storage = COUNT(*) WHERE state == \"low-storage\" | KEEP low_storage" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "textBasedLanguages-datasource-layer-layer-kpi-low-storage", - "type": "index-pattern" - } - ], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND stat IN (\"Maximum\", \"Minimum\") | STATS cpu_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL)), conn_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)), storage_cur = MIN(CASE(stat == \"Minimum\", `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)), last_seen = MAX(@timestamp) BY DBInstanceIdentifier, cloud.region | INLINE STATS latest_global = MAX(last_seen) | WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5 | EVAL state = CASE(cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\", cpu_cur > 80, \"saturated\", storage_cur < 5368709120, \"low-storage\", \"healthy\") | STATS low_storage = COUNT(*) WHERE state == \"low-storage\" | KEEP low_storage" - }, - "visualization": { - "applyColorTo": "value", - "color": "#61a2ff00", - "colorMode": "background", - "layerId": "layer-kpi-low-storage", - "layerType": "data", - "metricAccessor": "col-kpi-low-storage", - "palette": { - "name": "custom", - "params": { - "colorStops": [ - { - "color": "#24C292", - "stop": 0 - }, - { - "color": "#D6BF57", - "stop": 1 - } - ], - "continuity": "above", - "maxSteps": 5, - "name": "custom", - "progression": "fixed", - "rangeMax": null, - "rangeMin": 0, - "rangeType": "number", - "reverse": false, - "steps": 3, - "stops": [ - { - "color": "#24C292", - "stop": 1 - }, - { - "color": "#D6BF57", - "stop": 2 - } - ] - }, - "type": "palette" + "description": "Total number of RDS databases — distinct DB instance identifiers reporting metrics in the latest collected data for the selected time range.", + "hide_title": true, + "title": "" }, - "primaryAlign": "left", - "primaryPosition": "top", - "showBar": false, - "titlesTextAlign": "left" - } - }, - "title": "", - "version": 2, - "visualizationType": "lnsMetric" - }, - "description": "Number of low-storage RDS databases — those whose free storage dropped below 5 GiB, within a 5-minute freshness window. At risk of running out of disk. (Aurora instances are excluded — their storage auto-scales.)", - "hide_title": true, - "title": "" - }, - "gridData": { - "h": 6, - "i": "kpi-low-storage", - "sectionId": "aws-rds-overview-section", - "w": 4, - "x": 0, - "y": 6 - }, - "panelIndex": "kpi-low-storage", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "layer-kpi-healthy": { - "columns": [ - { - "columnId": "col-kpi-healthy", - "customLabel": true, - "fieldName": "healthy", - "inMetricDimension": true, - "label": "Healthy", - "meta": { - "esType": "long", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur > 80, \"saturated\",\n storage_cur < 5368709120, \"low-storage\",\n \"healthy\")\n| STATS healthy = COUNT(*) WHERE state == \"healthy\"\n| KEEP healthy" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur > 80, \"saturated\",\n storage_cur < 5368709120, \"low-storage\",\n \"healthy\")\n| STATS healthy = COUNT(*) WHERE state == \"healthy\"\n| KEEP healthy" - }, - "visualization": { - "applyColorTo": "background", - "color": "#61a2ff00", - "colorMode": "background", - "layerId": "layer-kpi-healthy", - "layerType": "data", - "metricAccessor": "col-kpi-healthy", - "primaryAlign": "left", - "primaryPosition": "top", - "showBar": false, - "titlesTextAlign": "left" - } - }, - "title": "", - "version": 2, - "visualizationType": "lnsMetric" - }, - "description": "Number of healthy RDS databases — with active connections and CPU at or below 80%, within a 5-minute freshness window.", - "drilldowns": [], - "hide_title": true, - "title": "" - }, - "gridData": { - "h": 6, - "i": "kpi-healthy", - "sectionId": "aws-rds-overview-section", - "w": 4, - "x": 4, - "y": 6 - }, - "panelIndex": "kpi-healthy", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "ff67c6af-1965-4a2a-9048-45188451659a": { - "columns": [ - { - "columnId": "saturated", - "customLabel": false, - "fieldName": "saturated", - "inMetricDimension": true, - "label": "Saturated", - "meta": { - "esType": "long", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur > 80, \"saturated\",\n storage_cur < 5368709120, \"low-storage\",\n \"healthy\")\n| STATS saturated = COUNT(*) WHERE state == \"saturated\"\n| KEEP saturated" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minutes\", last_seen, latest_global) <= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur > 80, \"saturated\",\n storage_cur < 5368709120, \"low-storage\",\n \"healthy\")\n| STATS saturated = COUNT(*) WHERE state == \"saturated\"\n| KEEP saturated" - }, - "visualization": { - "applyColorTo": "value", - "color": "#61a2ff00", - "colorMode": "background", - "layerId": "ff67c6af-1965-4a2a-9048-45188451659a", - "layerType": "data", - "metricAccessor": "saturated", - "palette": { - "name": "custom", - "params": { - "colorStops": [ - { - "color": "#24C292", - "stop": 0 - }, - { - "color": "#F6726A", - "stop": 1 - } - ], - "continuity": "above", - "maxSteps": 5, - "name": "custom", - "progression": "fixed", - "rangeMax": null, - "rangeMin": 0, - "rangeType": "number", - "reverse": false, - "steps": 3, - "stops": [ - { - "color": "#24C292", - "stop": 1 - }, - { - "color": "#F6726A", - "stop": 2 - } - ] - }, - "type": "palette" + "gridData": { + "h": 6, + "i": "kpi-total", + "sectionId": "aws-rds-overview-section", + "w": 4, + "x": 0, + "y": 0 }, - "primaryAlign": "left", - "primaryPosition": "top", - "showBar": false, - "titlesTextAlign": "left" - } + "panelIndex": "kpi-total", + "type": "vis" }, - "title": "", - "version": 2, - "visualizationType": "lnsMetric" - }, - "description": "Number of saturated RDS databases — those whose latest CPU utilization exceeds 80%, within a 5-minute freshness window. Indicates CPU-bound databases that may slow queries.", - "drilldowns": [], - "hide_title": true, - "title": "" - }, - "gridData": { - "h": 6, - "i": "kpi-saturated", - "sectionId": "aws-rds-overview-section", - "w": 4, - "x": 4, - "y": 0 - }, - "panelIndex": "kpi-saturated", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "tbl-layer-tbl-instances": { - "columns": [ - { - "columnId": "DBInstanceIdentifier", - "customLabel": true, - "fieldName": "DBInstanceIdentifier", - "label": "DB instance", - "meta": { - "esType": "keyword", - "type": "string" - } - }, - { - "columnId": "c_state_sort", - "customLabel": true, - "fieldName": "c_state_sort", - "inMetricDimension": true, - "label": "State order", - "meta": { - "esType": "integer", - "type": "number" - } - }, - { - "columnId": "c_state", - "customLabel": true, - "fieldName": "c_state", - "inMetricDimension": true, - "label": "State", - "meta": { - "esType": "keyword", - "type": "string" - } - }, - { - "columnId": "c_account", - "customLabel": true, - "fieldName": "c_account", - "label": "Account", - "meta": { - "esType": "keyword", - "type": "string" - } - }, - { - "columnId": "c_region", - "customLabel": true, - "fieldName": "c_region", - "label": "Region", - "meta": { - "esType": "keyword", - "type": "string" - } - }, - { - "columnId": "c_cpu", - "customLabel": true, - "fieldName": "c_cpu", - "inMetricDimension": true, - "label": "Avg CPU (%)", - "meta": { - "esType": "double", - "type": "number" - }, - "params": { - "format": { - "id": "percent", - "params": { - "decimals": 1 - } + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "layer-kpi-low-storage": { + "columns": [ + { + "columnId": "col-kpi-low-storage", + "customLabel": true, + "fieldName": "low_storage", + "inMetricDimension": true, + "label": "Low storage", + "meta": { + "esType": "long", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS low_storage = COUNT(*) WHERE state == \"low-storage\"\n| KEEP low_storage" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS low_storage = COUNT(*) WHERE state == \"low-storage\"\n| KEEP low_storage" + }, + "visualization": { + "applyColorTo": "value", + "color": "#61a2ff00", + "colorMode": "background", + "layerId": "layer-kpi-low-storage", + "layerType": "data", + "metricAccessor": "col-kpi-low-storage", + "palette": { + "name": "custom", + "params": { + "colorStops": [ + { + "color": "#24C292", + "stop": 0 + }, + { + "color": "#D6BF57", + "stop": 1 + } + ], + "continuity": "above", + "maxSteps": 5, + "name": "custom", + "progression": "fixed", + "rangeMax": null, + "rangeMin": 0, + "rangeType": "number", + "reverse": false, + "steps": 3, + "stops": [ + { + "color": "#24C292", + "stop": 1 + }, + { + "color": "#D6BF57", + "stop": 2 + } + ] + }, + "type": "palette" + }, + "primaryAlign": "left", + "primaryPosition": "top", + "showBar": false, + "titlesTextAlign": "left" } - } }, - { - "columnId": "c_conn", - "customLabel": true, - "fieldName": "c_conn", - "inMetricDimension": true, - "label": "Current connections", - "meta": { - "esType": "double", - "type": "number" - } - }, - { - "columnId": "c_mem", - "customLabel": true, - "fieldName": "c_mem", - "inMetricDimension": true, - "label": "Current free memory", - "meta": { - "esType": "double", - "type": "number" - }, - "params": { - "format": { - "id": "bytes", - "params": { - "decimals": 2 - } + "title": "", + "version": 2, + "visualizationType": "lnsMetric" + }, + "description": "Number of low-storage RDS databases — those whose free storage dropped below 5 GiB, within a 5-minute freshness window. At risk of running out of disk. (Aurora instances are excluded — their storage auto-scales.)", + "hide_title": true, + "title": "" + }, + "gridData": { + "h": 6, + "i": "kpi-low-storage", + "sectionId": "aws-rds-overview-section", + "w": 4, + "x": 0, + "y": 6 + }, + "panelIndex": "kpi-low-storage", + "type": "vis" + }, + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "layer-kpi-healthy": { + "columns": [ + { + "columnId": "col-kpi-healthy", + "customLabel": true, + "fieldName": "healthy", + "inMetricDimension": true, + "label": "Healthy", + "meta": { + "esType": "long", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS healthy = COUNT(*) WHERE state == \"healthy\"\n| KEEP healthy" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS healthy = COUNT(*) WHERE state == \"healthy\"\n| KEEP healthy" + }, + "visualization": { + "applyColorTo": "background", + "color": "#61a2ff00", + "colorMode": "background", + "layerId": "layer-kpi-healthy", + "layerType": "data", + "metricAccessor": "col-kpi-healthy", + "primaryAlign": "left", + "primaryPosition": "top", + "showBar": false, + "titlesTextAlign": "left" } - } }, - { - "columnId": "c_storage", - "customLabel": true, - "fieldName": "c_storage", - "inMetricDimension": true, - "label": "Current free storage", - "meta": { - "esType": "double", - "type": "number" - }, - "params": { - "format": { - "id": "bytes", - "params": { - "decimals": 2 - } + "title": "", + "version": 2, + "visualizationType": "lnsMetric" + }, + "description": "Number of healthy RDS databases — with active connections and CPU at or below 80%, within a 5-minute freshness window.", + "hide_title": true, + "title": "" + }, + "gridData": { + "h": 6, + "i": "kpi-healthy", + "sectionId": "aws-rds-overview-section", + "w": 4, + "x": 4, + "y": 6 + }, + "panelIndex": "kpi-healthy", + "type": "vis" + }, + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "ff67c6af-1965-4a2a-9048-45188451659a": { + "columns": [ + { + "columnId": "saturated", + "customLabel": true, + "fieldName": "saturated", + "inMetricDimension": true, + "label": "Saturated", + "meta": { + "esType": "long", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS saturated = COUNT(*) WHERE state == \"saturated\"\n| KEEP saturated" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS cpu_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n conn_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n storage_cur = AVG(AVG_OVER_TIME(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_global = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_global) \u003c= 5\n| EVAL state = CASE(\n cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\",\n cpu_cur \u003e 80, \"saturated\",\n storage_cur \u003c 10737418240, \"low-storage\",\n \"healthy\")\n| STATS saturated = COUNT(*) WHERE state == \"saturated\"\n| KEEP saturated" + }, + "visualization": { + "applyColorTo": "value", + "color": "#61a2ff00", + "colorMode": "background", + "layerId": "ff67c6af-1965-4a2a-9048-45188451659a", + "layerType": "data", + "metricAccessor": "saturated", + "palette": { + "name": "custom", + "params": { + "colorStops": [ + { + "color": "#24C292", + "stop": 0 + }, + { + "color": "#F6726A", + "stop": 1 + } + ], + "continuity": "above", + "maxSteps": 5, + "name": "custom", + "progression": "fixed", + "rangeMax": null, + "rangeMin": 0, + "rangeType": "number", + "reverse": false, + "steps": 3, + "stops": [ + { + "color": "#24C292", + "stop": 1 + }, + { + "color": "#F6726A", + "stop": 2 + } + ] + }, + "type": "palette" + }, + "primaryAlign": "left", + "primaryPosition": "top", + "showBar": false, + "titlesTextAlign": "left" } - } }, - { - "columnId": "c_read_iops", - "customLabel": true, - "fieldName": "c_read_iops", - "inMetricDimension": true, - "label": "Avg read IOPS", - "meta": { - "esType": "double", - "type": "number" - } + "title": "", + "version": 2, + "visualizationType": "lnsMetric" + }, + "description": "Number of saturated RDS databases — those whose latest CPU utilization exceeds 80%, within a 5-minute freshness window. Indicates CPU-bound databases that may slow queries.", + "hide_title": true + }, + "gridData": { + "h": 6, + "i": "kpi-saturated", + "sectionId": "aws-rds-overview-section", + "w": 4, + "x": 4, + "y": 0 + }, + "panelIndex": "kpi-saturated", + "type": "vis" + }, + { + "embeddableConfig": { + "description": "One hexagon per RDS database, ordered worst-first with CPU-saturated or low-storage databases first. Toggle Color by between Status, CPU utilization, or Free Storage; metric views support Min, Max, Avg, and Last over the dashboard time range. Click any hexagon to filter the dashboard or open metrics for that database.", + "hide_title": false, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "projectRouting": "_alias:*", + "query": { + "language": "kuery", + "query": "" + } + } }, - { - "columnId": "c_write_iops", - "customLabel": true, - "fieldName": "c_write_iops", - "inMetricDimension": true, - "label": "Avg write IOPS", - "meta": { - "esType": "double", - "type": "number" - } + "description": "One hexagon per RDS database, ordered worst-first with CPU-saturated or low-storage databases first. Toggle Color by between Status, CPU utilization, or Free Storage; metric views support Min, Max, Avg, and Last over the dashboard time range. Click any hexagon to filter the dashboard or open metrics for that database.", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"One hexagon per RDS database, ordered worst-first with CPU-saturated or low-storage databases first. States: saturated (CPU \u003e 80%), low-storage (\u003c 10 GB free), healthy (passing all checks), Unknown (no metric data). Toggle Color by between Status, CPU utilization, or Free Storage; metric views support Min, Max, Avg, and Last over the dashboard time range. Click any hexagon to filter the dashboard or open metrics for that database.\",\n \"usermeta\": {\n \"x_rds_hexmap\": true\n },\n \"padding\": {\n \"top\": 10,\n \"left\": 10,\n \"right\": 10,\n \"bottom\": 15\n },\n \"data\": [\n {\n \"name\": \"ts_probe\",\n \"url\": {\n \"%type%\": \"esql\",\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"query\": \"ROW round_key = CONCAT(TO_STRING(?_tstart), \\\"|\\\", TO_STRING(?_tend)), fetched_at = NOW()\"\n }\n },\n {\n \"name\": \"raw_all\",\n \"url\": {\n \"%type%\": \"esql\",\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"query\": \"SET unmapped_fields = \\\"nullify\\\";\\nFROM metrics-aws.rds.otel-* | WHERE @timestamp \u003e= ?_tstart AND @timestamp \u003c= ?_tend\\n AND DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \\\"\\\"\\n AND stat == \\\"Average\\\" | STATS cpu_min = MIN(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n cpu_max = MAX(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n cpu_avg = AVG(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n cpu_last = LAST(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`, @timestamp)\\n WHERE `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL,\\n st_min = MIN(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL,\\n st_max = MAX(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL,\\n st_avg = AVG(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL,\\n st_last = LAST(`metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, @timestamp)\\n WHERE `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace` IS NOT NULL,\\n last_seen = MAX(@timestamp)\\n ,\\n conn_max = MAX(`metrics.amazonaws.com/AWS/RDS/DatabaseConnections`)\\n WHERE `metrics.amazonaws.com/AWS/RDS/DatabaseConnections` IS NOT NULL,\\n eng_binlog = MAX(`metrics.amazonaws.com/AWS/RDS/BinLogDiskUsage`),\\n eng_txid = MAX(`metrics.amazonaws.com/AWS/RDS/MaximumUsedTransactionIDs`),\\n eng_txlog = MAX(`metrics.amazonaws.com/AWS/RDS/TransactionLogsGeneration`),\\n eng_replslot = MAX(`metrics.amazonaws.com/AWS/RDS/ReplicationSlotDiskUsage`),\\n eng_failedjobs = MAX(`metrics.amazonaws.com/AWS/RDS/FailedSQLServerAgentJobsCount`),\\n eng_tempdb = MAX(`metrics.amazonaws.com/AWS/RDS/TempDbDataFileUsage`),\\n eng_swap = MAX(`metrics.amazonaws.com/AWS/RDS/SwapUsage`)\\n BY entity_id = DBInstanceIdentifier\\n, cloud.region\\n| INLINE STATS latest_global = MAX(last_seen)\\n| WHERE DATE_DIFF(\\\"minutes\\\", last_seen, latest_global) \u003c= 5\\n| EVAL storage_min = st_min / 1073741824,\\n storage_max = st_max / 1073741824,\\n storage_avg = st_avg / 1073741824,\\n storage_last = st_last / 1073741824,\\n engine = CASE(\\n eng_failedjobs IS NOT NULL OR eng_tempdb IS NOT NULL, \\\"SQL Server\\\",\\n eng_txid IS NOT NULL OR eng_txlog IS NOT NULL OR eng_replslot IS NOT NULL, \\\"PostgreSQL\\\",\\n eng_binlog IS NOT NULL, \\\"MySQL / MariaDB\\\",\\n eng_swap IS NOT NULL, \\\"Oracle\\\",\\n \\\"Other\\\"),\\n status_num = CASE(\\n cpu_last IS NULL AND st_last IS NULL, 3,\\n cpu_last \u003e 80, 0,\\n st_last \u003c 10737418240, 1,\\n 2),\\n status_label = CASE(\\n cpu_last IS NULL AND st_last IS NULL, \\\"Unknown\\\",\\n cpu_last \u003e 80, \\\"saturated\\\",\\n st_last \u003c 10737418240, \\\"low-storage\\\",\\n \\\"healthy\\\"),\\n severity_rank = status_num,\\n round_key = CONCAT(TO_STRING(?_tstart), \\\"|\\\", TO_STRING(?_tend)),\\n fetched_at = NOW()\\n| KEEP entity_id, engine, status_num, status_label, severity_rank,\\n cpu_min, cpu_max, cpu_avg, cpu_last,\\n storage_min, storage_max, storage_avg, storage_last,\\n round_key, fetched_at\\n| LIMIT 10000\"\n }\n },\n {\n \"name\": \"ranked_status\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"severity_rank\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_min\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_min == null ? 1e12 : -datum.cpu_min * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_max\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_max == null ? 1e12 : -datum.cpu_max * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_avg\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_avg == null ? 1e12 : -datum.cpu_avg * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_cpu_last\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.cpu_last == null ? 1e12 : -datum.cpu_last * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_min\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_min == null ? 1e12 : datum.storage_min * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_max\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_max == null ? 1e12 : datum.storage_max * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_avg\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_avg == null ? 1e12 : datum.storage_avg * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"ranked_storage_last\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"sort_key\",\n \"expr\": \"datum.storage_last == null ? 1e12 : datum.storage_last * 1000000\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": [\n \"sort_key\",\n \"entity_id\"\n ],\n \"order\": [\n \"ascending\",\n \"ascending\"\n ]\n }\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"active_rank\"\n ]\n }\n ]\n },\n {\n \"name\": \"active\",\n \"values\": [],\n \"on\": [\n {\n \"trigger\": \"ts_round !== '' \u0026\u0026 active_round !== '' \u0026\u0026 active_round !== ts_round\",\n \"remove\": \"true\"\n },\n {\n \"trigger\": \"metric === 'status' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_status')\"\n },\n {\n \"trigger\": \"metric === 'cpu' \u0026\u0026 effective_agg === 'min' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_min')\"\n },\n {\n \"trigger\": \"metric === 'cpu' \u0026\u0026 effective_agg === 'max' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_max')\"\n },\n {\n \"trigger\": \"metric === 'cpu' \u0026\u0026 effective_agg === 'avg' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_avg')\"\n },\n {\n \"trigger\": \"metric === 'cpu' \u0026\u0026 effective_agg === 'last' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_cpu_last')\"\n },\n {\n \"trigger\": \"metric === 'storage' \u0026\u0026 effective_agg === 'min' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_min')\"\n },\n {\n \"trigger\": \"metric === 'storage' \u0026\u0026 effective_agg === 'max' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_max')\"\n },\n {\n \"trigger\": \"metric === 'storage' \u0026\u0026 effective_agg === 'avg' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_avg')\"\n },\n {\n \"trigger\": \"metric === 'storage' \u0026\u0026 effective_agg === 'last' \u0026\u0026 len_raw \u003e 0 \u0026\u0026 raw_round === ts_round \u0026\u0026 ts_round !== ''\",\n \"remove\": \"true\",\n \"insert\": \"data('ranked_storage_last')\"\n }\n ]\n },\n {\n \"name\": \"entities\",\n \"source\": \"active\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"active_val\",\n \"expr\": \"metric=='status' ? null : (metric=='cpu' ? (effective_agg=='min' ? datum.cpu_min : effective_agg=='max' ? datum.cpu_max : effective_agg=='avg' ? datum.cpu_avg : effective_agg=='last' ? datum.cpu_last : null) : (metric=='storage' ? (effective_agg=='min' ? datum.storage_min : effective_agg=='max' ? datum.storage_max : effective_agg=='avg' ? datum.storage_avg : effective_agg=='last' ? datum.storage_last : null) : null))\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"index0\",\n \"expr\": \"datum.active_rank - 1\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"col\",\n \"expr\": \"datum.index0 % gridCols\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"row\",\n \"expr\": \"floor(datum.index0 / gridCols)\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"x\",\n \"expr\": \"datum.col * gapX + (datum.row % 2 == 1 ? gapX / 2 : 0) + hexR + 5\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"y\",\n \"expr\": \"datum.row * gapY + hexR + 5 + hexOffsetY\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"hexSize\",\n \"expr\": \"hexR * hexR * 3.46\"\n }\n ]\n },\n {\n \"name\": \"status_counts\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"groupby\": [\n \"status_num\"\n ],\n \"ops\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ]\n }\n ]\n },\n {\n \"name\": \"status_legend\",\n \"values\": [\n {\n \"label\": \"Saturated\",\n \"val\": 0\n },\n {\n \"label\": \"Low storage\",\n \"val\": 1\n },\n {\n \"label\": \"Healthy\",\n \"val\": 2\n },\n {\n \"label\": \"Unknown\",\n \"val\": 3\n }\n ],\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"status_counts\",\n \"key\": \"status_num\",\n \"fields\": [\n \"val\"\n ],\n \"values\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ],\n \"default\": 0\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"idx\"\n ]\n }\n ]\n },\n {\n \"name\": \"cpu_counts\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"v\",\n \"expr\": \"agg == 'min' ? datum.cpu_min : agg == 'max' ? datum.cpu_max : agg == 'avg' ? datum.cpu_avg : agg == 'last' ? datum.cpu_last : null\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"bucket\",\n \"expr\": \"datum.v == null ? 3 : (datum.v \u003e= 80 ? 2 : datum.v \u003e= 60 ? 1 : 0)\"\n },\n {\n \"type\": \"aggregate\",\n \"groupby\": [\n \"bucket\"\n ],\n \"ops\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ]\n }\n ]\n },\n {\n \"name\": \"storage_counts\",\n \"source\": \"raw_all\",\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"v\",\n \"expr\": \"agg == 'min' ? datum.storage_min : agg == 'max' ? datum.storage_max : agg == 'avg' ? datum.storage_avg : agg == 'last' ? datum.storage_last : null\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"bucket\",\n \"expr\": \"datum.v == null ? 3 : (datum.v \u003e= 20 ? 2 : datum.v \u003e= 10 ? 1 : 0)\"\n },\n {\n \"type\": \"aggregate\",\n \"groupby\": [\n \"bucket\"\n ],\n \"ops\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ]\n }\n ]\n },\n {\n \"name\": \"cpu_legend_stops\",\n \"values\": [\n {\n \"label\": \"≥ 80%\",\n \"val\": 90,\n \"bucket\": 2,\n \"is_nodata\": false\n },\n {\n \"label\": \"60 – 79%\",\n \"val\": 70,\n \"bucket\": 1,\n \"is_nodata\": false\n },\n {\n \"label\": \"\u003c 60%\",\n \"val\": 0,\n \"bucket\": 0,\n \"is_nodata\": false\n },\n {\n \"label\": \"Unknown\",\n \"val\": null,\n \"bucket\": 3,\n \"is_nodata\": true\n }\n ],\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"cpu_counts\",\n \"key\": \"bucket\",\n \"fields\": [\n \"bucket\"\n ],\n \"values\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ],\n \"default\": 0\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"idx\"\n ]\n }\n ]\n },\n {\n \"name\": \"storage_legend_stops\",\n \"values\": [\n {\n \"label\": \"\u003c 10 GB\",\n \"val\": 2,\n \"bucket\": 0,\n \"is_nodata\": false\n },\n {\n \"label\": \"10 – 19 GB\",\n \"val\": 15,\n \"bucket\": 1,\n \"is_nodata\": false\n },\n {\n \"label\": \"≥ 20 GB\",\n \"val\": 50,\n \"bucket\": 2,\n \"is_nodata\": false\n },\n {\n \"label\": \"Unknown\",\n \"val\": null,\n \"bucket\": 3,\n \"is_nodata\": true\n }\n ],\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"storage_counts\",\n \"key\": \"bucket\",\n \"fields\": [\n \"bucket\"\n ],\n \"values\": [\n \"count\"\n ],\n \"as\": [\n \"count\"\n ],\n \"default\": 0\n },\n {\n \"type\": \"window\",\n \"ops\": [\n \"row_number\"\n ],\n \"as\": [\n \"idx\"\n ]\n }\n ]\n },\n {\n \"name\": \"spinner_dots\",\n \"values\": [\n {\n \"i\": 0\n },\n {\n \"i\": 1\n },\n {\n \"i\": 2\n },\n {\n \"i\": 3\n },\n {\n \"i\": 4\n },\n {\n \"i\": 5\n },\n {\n \"i\": 6\n },\n {\n \"i\": 7\n }\n ]\n },\n {\n \"name\": \"pills\",\n \"values\": [\n {\n \"id\": \"status\",\n \"label\": \"Status\",\n \"group\": \"metric\",\n \"x\": 69,\n \"w\": 48,\n \"available_aggs\": [],\n \"default_agg\": \"last\"\n },\n {\n \"id\": \"cpu\",\n \"label\": \"CPU %\",\n \"group\": \"metric\",\n \"x\": 125,\n \"w\": 58,\n \"available_aggs\": [\n \"min\",\n \"max\",\n \"avg\",\n \"last\"\n ],\n \"default_agg\": \"last\"\n },\n {\n \"id\": \"storage\",\n \"label\": \"Free Storage (GB)\",\n \"group\": \"metric\",\n \"x\": 191,\n \"w\": 128,\n \"available_aggs\": [\n \"min\",\n \"max\",\n \"avg\",\n \"last\"\n ],\n \"default_agg\": \"last\"\n },\n {\n \"id\": \"min\",\n \"label\": \"Min\",\n \"group\": \"agg\",\n \"x\": 425,\n \"w\": 36,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"max\",\n \"label\": \"Max\",\n \"group\": \"agg\",\n \"x\": 465,\n \"w\": 36,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"avg\",\n \"label\": \"Avg\",\n \"group\": \"agg\",\n \"x\": 505,\n \"w\": 36,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"last\",\n \"label\": \"Last\",\n \"group\": \"agg\",\n \"x\": 545,\n \"w\": 40,\n \"valid_for\": [\n \"cpu\",\n \"storage\"\n ]\n },\n {\n \"id\": \"sum\",\n \"label\": \"Sum\",\n \"group\": \"agg\",\n \"x\": 589,\n \"w\": 40,\n \"valid_for\": []\n }\n ]\n },\n {\n \"name\": \"menu_items_data\",\n \"values\": [\n {\n \"id\": \"details\",\n \"label\": \"View details\",\n \"idx\": 0\n },\n {\n \"id\": \"metrics\",\n \"label\": \"View metrics in Discover\",\n \"idx\": 1\n }\n ]\n },\n {\n \"name\": \"menu_visible\",\n \"values\": [\n {\n \"_\": 0\n }\n ],\n \"transform\": [\n {\n \"type\": \"filter\",\n \"expr\": \"selected_entity != null\"\n }\n ]\n },\n {\n \"name\": \"menu_items_visible\",\n \"source\": \"menu_items_data\",\n \"transform\": [\n {\n \"type\": \"filter\",\n \"expr\": \"selected_entity != null\"\n }\n ]\n },\n {\n \"name\": \"spark_raw\",\n \"url\": {\n \"%type%\": \"esql\",\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"query\": \"SET unmapped_fields = \\\"nullify\\\";\\nFROM metrics-aws.rds.otel-* | WHERE @timestamp \u003e= ?_tstart AND @timestamp \u003c= ?_tend AND DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \\\"\\\" | STATS s_cpu = AVG(CASE(stat == \\\"Average\\\", `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL)), s_storage = AVG(CASE(stat == \\\"Average\\\", `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)) BY entity_id = DBInstanceIdentifier, t = BUCKET(@timestamp, 40, ?_tstart, ?_tend) | SORT entity_id, t | LIMIT 10000\"\n }\n },\n {\n \"name\": \"spark_series\",\n \"source\": \"spark_raw\",\n \"transform\": [\n {\n \"type\": \"filter\",\n \"expr\": \"tooltip \u0026\u0026 tooltip.entity_id \u0026\u0026 metric != 'status' \u0026\u0026 datum.entity_id === tooltip.entity_id\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"v\",\n \"expr\": \"metric == 'cpu' ? datum.s_cpu : metric == 'storage' ? datum.s_storage : datum.s_cpu\"\n },\n {\n \"type\": \"collect\",\n \"sort\": {\n \"field\": \"t\",\n \"order\": \"ascending\"\n }\n }\n ]\n },\n {\n \"name\": \"spark_stat\",\n \"source\": \"spark_series\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"fields\": [\n \"v\",\n \"v\",\n \"v\"\n ],\n \"ops\": [\n \"max\",\n \"mean\",\n \"valid\"\n ],\n \"as\": [\n \"vmax\",\n \"vavg\",\n \"vn\"\n ]\n }\n ]\n }\n ],\n \"signals\": [\n {\n \"name\": \"metric\",\n \"value\": \"status\",\n \"on\": [\n {\n \"events\": \"@pill_bg:click\",\n \"update\": \"datum.group === 'metric' ? datum.id : metric\"\n }\n ]\n },\n {\n \"name\": \"agg\",\n \"value\": \"last\",\n \"on\": [\n {\n \"events\": \"@pill_bg:click\",\n \"update\": \"datum.group === 'agg' \u0026\u0026 metric !== 'status' \u0026\u0026 indexof(datum.valid_for, metric) \u003e= 0 ? datum.id : ( datum.group === 'metric' \u0026\u0026 datum.id !== 'status' ? (indexof(datum.available_aggs, agg) \u003e= 0 ? agg : datum.default_agg) : agg )\"\n }\n ]\n },\n {\n \"name\": \"effective_agg\",\n \"update\": \"metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'\"\n },\n {\n \"name\": \"groupHeaderH\",\n \"value\": 20\n },\n {\n \"name\": \"groupGap\",\n \"value\": 10\n },\n {\n \"name\": \"group_by\",\n \"value\": \"none\"\n },\n {\n \"name\": \"len_raw\",\n \"update\": \"length(data('raw_all'))\"\n },\n {\n \"name\": \"len_active\",\n \"update\": \"length(data('active'))\"\n },\n {\n \"name\": \"ts_round\",\n \"update\": \"data('ts_probe')[0] ? data('ts_probe')[0].round_key : ''\"\n },\n {\n \"name\": \"time_from\",\n \"update\": \"ts_round !== '' \u0026\u0026 indexof(ts_round, '|') \u003e 0 ? slice(ts_round, 0, indexof(ts_round, '|')) : ''\"\n },\n {\n \"name\": \"time_to\",\n \"update\": \"ts_round !== '' \u0026\u0026 indexof(ts_round, '|') \u003e 0 ? slice(ts_round, indexof(ts_round, '|') + 1) : ''\"\n },\n {\n \"name\": \"g_param\",\n \"update\": \"time_from !== '' \u0026\u0026 time_to !== '' ? '_g=(time:(from:%27' + time_from + '%27,to:%27' + time_to + '%27))\u0026' : ''\"\n },\n {\n \"name\": \"raw_round\",\n \"update\": \"data('raw_all')[0] ? data('raw_all')[0].round_key : ''\"\n },\n {\n \"name\": \"active_round\",\n \"update\": \"raw_round\"\n },\n {\n \"name\": \"raw_fetched_str\",\n \"update\": \"data('raw_all')[0] ? data('raw_all')[0].fetched_at : ''\"\n },\n {\n \"name\": \"active_fetched\",\n \"update\": \"raw_fetched_str !== '' ? toDate(raw_fetched_str) : 0\"\n },\n {\n \"name\": \"tick\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": {\n \"type\": \"timer\",\n \"throttle\": 100\n },\n \"update\": \"now()\"\n }\n ]\n },\n {\n \"name\": \"url_change_at\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"hashchange\"\n },\n \"update\": \"now()\"\n },\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"popstate\"\n },\n \"update\": \"now()\"\n }\n ]\n },\n {\n \"name\": \"fetch_tracker\",\n \"init\": \"{seen: 0, arrived_at: 0}\",\n \"on\": [\n {\n \"events\": {\n \"signal\": \"tick\"\n },\n \"update\": \"active_fetched \u003e 0 \u0026\u0026 active_fetched !== fetch_tracker.seen ? {seen: active_fetched, arrived_at: tick} : fetch_tracker\"\n }\n ]\n },\n {\n \"name\": \"loading_raw\",\n \"update\": \"len_active === 0 || ts_round === '' || active_round === '' || active_round !== ts_round || (url_change_at \u003e 0 \u0026\u0026 fetch_tracker.arrived_at \u003c url_change_at)\"\n },\n {\n \"name\": \"loading_started_at\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": {\n \"signal\": \"tick\"\n },\n \"update\": \"loading_raw ? (loading_started_at === 0 ? tick : loading_started_at) : 0\"\n }\n ]\n },\n {\n \"name\": \"loading_elapsed\",\n \"update\": \"loading_started_at \u003e 0 ? tick - loading_started_at : 0\"\n },\n {\n \"name\": \"no_data\",\n \"update\": \"loading_raw \u0026\u0026 ts_round !== '' \u0026\u0026 len_raw === 0 \u0026\u0026 loading_elapsed \u003e 2000\"\n },\n {\n \"name\": \"loading\",\n \"update\": \"loading_raw \u0026\u0026 !no_data\"\n },\n {\n \"name\": \"loading_timeout\",\n \"update\": \"loading \u0026\u0026 loading_elapsed \u003e 15000\"\n },\n {\n \"name\": \"total_entities\",\n \"update\": \"len_raw\"\n },\n {\n \"name\": \"legendW\",\n \"value\": 138\n },\n {\n \"name\": \"buttonsH\",\n \"value\": 34\n },\n {\n \"name\": \"availW\",\n \"update\": \"width - 20 - legendW\"\n },\n {\n \"name\": \"n_groups\",\n \"value\": 0\n },\n {\n \"name\": \"availH\",\n \"update\": \"height - 20 - buttonsH - (group_by !== 'none' ? n_groups * (groupHeaderH + groupGap) : 0)\"\n },\n {\n \"name\": \"hexOffsetY\",\n \"update\": \"buttonsH\"\n },\n {\n \"name\": \"idealCols\",\n \"update\": \"total_entities \u003e 0 \u0026\u0026 availH \u003e 0 ? max(1, round(sqrt(total_entities * (availW / availH)))) : 1\"\n },\n {\n \"name\": \"idealRows\",\n \"update\": \"max(1, ceil(total_entities / idealCols))\"\n },\n {\n \"name\": \"hexRInitial\",\n \"update\": \"min(availW / (idealCols * 2 + 0), availH / (idealRows * 2 + 0))\"\n },\n {\n \"name\": \"maxColsAtHexR\",\n \"update\": \"max(idealCols, floor(availW / (max(3, hexRInitial) * 2)))\"\n },\n {\n \"name\": \"maxColsAtMinR\",\n \"update\": \"max(1, floor(availW / (3 * 2)))\"\n },\n {\n \"name\": \"gridCols\",\n \"update\": \"max(1, min(total_entities, min(maxColsAtHexR, maxColsAtMinR)))\"\n },\n {\n \"name\": \"gridRows\",\n \"update\": \"group_by === 'none' ? max(1, ceil(total_entities / gridCols)) : max(1, ceil(total_entities / gridCols) + max(0, n_groups - 1))\"\n },\n {\n \"name\": \"rByWidth\",\n \"update\": \"availW / (gridCols * 1.76 + 0.88)\"\n },\n {\n \"name\": \"rByHeight\",\n \"update\": \"availH / (gridRows * 1.54 + 0.92)\"\n },\n {\n \"name\": \"hexR\",\n \"update\": \"max(3, min(90, min(rByWidth, rByHeight)))\"\n },\n {\n \"name\": \"gapX\",\n \"update\": \"hexR * 1.76\"\n },\n {\n \"name\": \"gapY\",\n \"update\": \"hexR * 1.54\"\n },\n {\n \"name\": \"legendX\",\n \"update\": \"width - legendW + 4\"\n },\n {\n \"name\": \"tooltip\",\n \"value\": {},\n \"on\": [\n {\n \"events\": \"@hexagons:mouseover\",\n \"update\": \"datum\"\n },\n {\n \"events\": \"@hexagons:mouseout\",\n \"update\": \"{}\"\n }\n ]\n },\n {\n \"name\": \"selected_entity\",\n \"value\": null,\n \"on\": [\n {\n \"events\": \"@hexagons:click\",\n \"update\": \"{id: datum.entity_id, x: datum.x, y: datum.y}\"\n },\n {\n \"events\": \"@menu_backdrop:click\",\n \"update\": \"null\"\n },\n {\n \"events\": \"@menu_item_bg:click\",\n \"update\": \"null\"\n }\n ]\n },\n {\n \"name\": \"menu_x\",\n \"update\": \"selected_entity ? ((selected_entity.x + hexR + 4 + 248 \u003e width - legendW - 4) ? max(4, selected_entity.x - hexR - 248 - 4) : max(4, selected_entity.x + hexR + 4)) : 0\"\n },\n {\n \"name\": \"menu_y\",\n \"update\": \"selected_entity ? max(5, min(selected_entity.y - 30, height - (90 + menu_hoff) - 6)) : 0\"\n },\n {\n \"name\": \"tt_off\",\n \"update\": \"tooltip.entity_id ? (length(tooltip.entity_id) \u003c= 36 ? 0 : 14) : 0\"\n },\n {\n \"name\": \"spark_avg\",\n \"update\": \"length(data('spark_stat')) ? data('spark_stat')[0].vavg : null\"\n },\n {\n \"name\": \"spark_last\",\n \"update\": \"length(data('spark_series')) ? data('spark_series')[length(data('spark_series')) - 1].v : null\"\n },\n {\n \"name\": \"spark_delta\",\n \"update\": \"(spark_avg != null \u0026\u0026 spark_avg != 0 \u0026\u0026 spark_last != null) ? (spark_last - spark_avg) / spark_avg * 100 : null\"\n },\n {\n \"name\": \"spark_top\",\n \"update\": \"tt_off + 91\"\n },\n {\n \"name\": \"spark_bottom\",\n \"update\": \"tt_off + 121\"\n },\n {\n \"name\": \"menu_hoff\",\n \"update\": \"selected_entity ? (length(selected_entity.id) \u003e 36 ? 14 : 0) : 0\"\n }\n ],\n \"scales\": [\n {\n \"name\": \"status_color\",\n \"type\": \"ordinal\",\n \"domain\": [\n 0,\n 1,\n 2,\n 3\n ],\n \"range\": [\n \"#F6726A\",\n \"#FCD883\",\n \"#24C292\",\n \"#BFDBFF\"\n ]\n },\n {\n \"name\": \"cpu_color\",\n \"type\": \"threshold\",\n \"domain\": [\n 60,\n 80\n ],\n \"range\": [\n \"#24C292\",\n \"#FCD883\",\n \"#F6726A\"\n ]\n },\n {\n \"name\": \"storage_color\",\n \"type\": \"threshold\",\n \"domain\": [\n 10,\n 20\n ],\n \"range\": [\n \"#F6726A\",\n \"#FCD883\",\n \"#24C292\"\n ]\n },\n {\n \"name\": \"sparkX\",\n \"type\": \"point\",\n \"range\": [\n 14,\n 276\n ],\n \"domain\": {\n \"data\": \"spark_series\",\n \"field\": \"t\"\n }\n },\n {\n \"name\": \"sparkY\",\n \"type\": \"linear\",\n \"nice\": false,\n \"range\": [\n {\n \"signal\": \"spark_bottom\"\n },\n {\n \"signal\": \"spark_top\"\n }\n ],\n \"domain\": {\n \"signal\": \"[0, length(data('spark_stat')) \u0026\u0026 data('spark_stat')[0].vmax \u003e 0 ? data('spark_stat')[0].vmax : 1]\"\n }\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 5\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"value\": \"Color by:\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": 600\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 345\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"value\": \"Aggregation:\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": 600\n },\n \"fill\": {\n \"value\": \"#838C99\"\n },\n \"opacity\": {\n \"signal\": \"(metric === 'cpu' || metric === 'storage') ? 1 : 0.5\"\n }\n }\n }\n },\n {\n \"name\": \"pill_bg\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"pills\"\n },\n \"encode\": {\n \"enter\": {},\n \"update\": {\n \"x\": {\n \"field\": \"x\"\n },\n \"x2\": {\n \"signal\": \"datum.x + datum.w\"\n },\n \"y\": {\n \"value\": 6\n },\n \"y2\": {\n \"value\": 28\n },\n \"cornerRadius\": {\n \"value\": 4\n },\n \"fill\": {\n \"signal\": \"((datum.group === 'metric' \u0026\u0026 datum.id === metric) || (datum.group === 'agg' \u0026\u0026 datum.id === effective_agg)) ? '#0077CC' : 'transparent'\"\n },\n \"stroke\": {\n \"signal\": \"((datum.group === 'metric' \u0026\u0026 datum.id === metric) || (datum.group === 'agg' \u0026\u0026 datum.id === effective_agg)) ? '#0064B0' : '#838C99'\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"opacity\": {\n \"signal\": \"(datum.group === 'agg' \u0026\u0026 (!(metric === 'cpu' || metric === 'storage') || indexof(datum.valid_for, metric) \u003c 0)) ? 0.5 : 1\"\n },\n \"cursor\": {\n \"signal\": \"(datum.group === 'agg' \u0026\u0026 (!(metric === 'cpu' || metric === 'storage') || indexof(datum.valid_for, metric) \u003c 0)) ? 'default' : 'pointer'\"\n }\n }\n }\n },\n {\n \"name\": \"pill_label\",\n \"type\": \"text\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"pills\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"datum.x + datum.w / 2\"\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"field\": \"label\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"signal\": \"((datum.group === 'metric' \u0026\u0026 datum.id === metric) || (datum.group === 'agg' \u0026\u0026 datum.id === effective_agg)) ? '#FFFFFF' : '#838C99'\"\n },\n \"opacity\": {\n \"signal\": \"(datum.group === 'agg' \u0026\u0026 (!(metric === 'cpu' || metric === 'storage') || indexof(datum.valid_for, metric) \u003c 0)) ? 0.5 : 1\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"width - legendW - 4\"\n },\n \"y\": {\n \"value\": 17\n },\n \"text\": {\n \"signal\": \"total_entities === 0 ? '' : (total_entities \u003c 10000 ? 'Showing ' + total_entities + ' databases' : 'Showing top 10,000 databases (limit reached)')\"\n },\n \"align\": {\n \"value\": \"right\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n }\n }\n },\n {\n \"name\": \"hexagons\",\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"entities\"\n },\n \"encode\": {\n \"enter\": {\n \"cursor\": {\n \"value\": \"pointer\"\n }\n },\n \"update\": {\n \"x\": {\n \"field\": \"x\"\n },\n \"y\": {\n \"field\": \"y\"\n },\n \"size\": {\n \"field\": \"hexSize\"\n },\n \"fill\": [\n {\n \"test\": \"metric == 'status'\",\n \"scale\": \"status_color\",\n \"field\": \"status_num\"\n },\n {\n \"test\": \"datum.active_val == null\",\n \"value\": \"#BFDBFF\"\n },\n {\n \"test\": \"metric == 'cpu'\",\n \"scale\": \"cpu_color\",\n \"field\": \"active_val\"\n },\n {\n \"test\": \"metric == 'storage'\",\n \"scale\": \"storage_color\",\n \"field\": \"active_val\"\n },\n {\n \"value\": \"#BFDBFF\"\n }\n ],\n \"fillOpacity\": {\n \"value\": 0.92\n },\n \"shape\": {\n \"value\": \"M0,-1L0.866,-0.5L0.866,0.5L0,1L-0.866,0.5L-0.866,-0.5Z\"\n },\n \"strokeWidth\": [\n {\n \"test\": \"selected_entity \u0026\u0026 selected_entity.id === datum.entity_id\",\n \"value\": 3.5\n },\n {\n \"test\": \"tooltip.entity_id === datum.entity_id\",\n \"value\": 3\n },\n {\n \"value\": 1\n }\n ],\n \"stroke\": [\n {\n \"test\": \"selected_entity \u0026\u0026 selected_entity.id === datum.entity_id\",\n \"value\": \"#0077CC\"\n },\n {\n \"test\": \"tooltip.entity_id === datum.entity_id\",\n \"value\": \"#222\"\n },\n {\n \"value\": \"#FFFFFF\"\n }\n ],\n \"strokeOpacity\": [\n {\n \"test\": \"selected_entity \u0026\u0026 selected_entity.id === datum.entity_id\",\n \"value\": 1\n },\n {\n \"test\": \"tooltip.entity_id === datum.entity_id\",\n \"value\": 1\n },\n {\n \"value\": 0.3\n }\n ]\n }\n }\n },\n {\n \"name\": \"hex_hover\",\n \"type\": \"symbol\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"entities\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"field\": \"x\"\n },\n \"y\": {\n \"field\": \"y\"\n },\n \"size\": {\n \"field\": \"hexSize\"\n },\n \"shape\": {\n \"value\": \"M0,-1L0.866,-0.5L0.866,0.5L0,1L-0.866,0.5L-0.866,-0.5Z\"\n },\n \"fill\": {\n \"value\": \"#FFFFFF\"\n },\n \"fillOpacity\": {\n \"signal\": \"tooltip.entity_id === datum.entity_id ? 0.22 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"legendX\"\n },\n \"y\": {\n \"signal\": \"buttonsH + 8\"\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"text\": {\n \"value\": \"Status\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"opacity\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"status_legend\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 6\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"size\": {\n \"value\": 110\n },\n \"shape\": {\n \"value\": \"circle\"\n },\n \"fill\": {\n \"scale\": \"status_color\",\n \"field\": \"val\"\n }\n },\n \"update\": {\n \"opacity\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": {\n \"data\": \"status_legend\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 18\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"datum.label + ' (' + datum.count + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"legendX\"\n },\n \"y\": {\n \"signal\": \"buttonsH + 8\"\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"'CPU% (' + agg + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"cpu_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 6\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"size\": {\n \"value\": 110\n },\n \"shape\": {\n \"value\": \"circle\"\n }\n },\n \"update\": {\n \"fill\": [\n {\n \"test\": \"datum.is_nodata\",\n \"value\": \"#BFDBFF\"\n },\n {\n \"scale\": \"cpu_color\",\n \"field\": \"val\"\n }\n ],\n \"opacity\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": {\n \"data\": \"cpu_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 18\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"datum.label + ' (' + datum.count + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"legendX\"\n },\n \"y\": {\n \"signal\": \"buttonsH + 8\"\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"'Free storage (' + agg + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": {\n \"data\": \"storage_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 6\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"size\": {\n \"value\": 110\n },\n \"shape\": {\n \"value\": \"circle\"\n }\n },\n \"update\": {\n \"fill\": [\n {\n \"test\": \"datum.is_nodata\",\n \"value\": \"#BFDBFF\"\n },\n {\n \"scale\": \"storage_color\",\n \"field\": \"val\"\n }\n ],\n \"opacity\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": {\n \"data\": \"storage_legend_stops\"\n },\n \"encode\": {\n \"enter\": {\n \"x\": {\n \"value\": 18\n },\n \"y\": {\n \"signal\": \"28 + (datum.idx - 1) * 22\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 11\n },\n \"fill\": {\n \"value\": \"#838C99\"\n }\n },\n \"update\": {\n \"text\": {\n \"signal\": \"datum.label + ' (' + datum.count + ')'\"\n },\n \"opacity\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"type\": \"group\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"tooltip.x + 18 + 290 \u003e width - legendW - 10 ? max(tooltip.x - 18 - 290, 5) : tooltip.x + 18\"\n },\n \"y\": {\n \"signal\": \"max(5, min(tooltip.y - 30, height - (tooltip.entity_id ? ((length(tooltip.entity_id) \u003c= 36 ? 0 : 14) + (metric == 'status' ? 127 : 197)) : 110) - 6))\"\n },\n \"width\": {\n \"value\": 290\n },\n \"height\": {\n \"signal\": \"tooltip.entity_id ? ((length(tooltip.entity_id) \u003c= 36 ? 0 : 14) + (metric == 'status' ? 127 : 197)) : 110\"\n },\n \"opacity\": [\n {\n \"test\": \"(tooltip.entity_id) \u0026\u0026 !selected_entity\",\n \"value\": 1\n },\n {\n \"value\": 0\n }\n ],\n \"fill\": {\n \"value\": \"#0E1728\"\n },\n \"stroke\": {\n \"value\": \"#2A3144\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"cornerRadius\": {\n \"value\": 8\n }\n }\n },\n \"marks\": [\n {\n \"type\": \"rect\",\n \"name\": \"spark_hl\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 8\n },\n \"width\": {\n \"value\": 274\n },\n \"y\": {\n \"signal\": \"tt_off + 62\"\n },\n \"height\": {\n \"value\": 63\n },\n \"fill\": {\n \"value\": \"#5A6B8C\"\n },\n \"fillOpacity\": {\n \"value\": 0.16\n },\n \"cornerRadius\": {\n \"value\": 6\n },\n \"opacity\": {\n \"signal\": \"(tooltip.entity_id \u0026\u0026 metric != 'status') ? 1 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"value\": 12\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) \u003c= 36 ? [tooltip.entity_id] : [slice(tooltip.entity_id, 0, 36), slice(tooltip.entity_id, 36)]) : ['']\"\n },\n \"fontSize\": {\n \"value\": 13\n },\n \"lineHeight\": {\n \"value\": 15\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#fff\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) \u003c= 36 ? 30 : 44) : 30\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'Engine: ' + tooltip.engine : ''\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": {\n \"value\": \"normal\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"value\": \"#9da4b3\"\n }\n }\n }\n },\n {\n \"type\": \"rule\",\n \"name\": \"tooltip_divider\",\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"x2\": {\n \"value\": 278\n },\n \"y\": {\n \"signal\": \"tooltip.entity_id ? (length(tooltip.entity_id) \u003c= 36 ? 47 : 61) : 47\"\n },\n \"stroke\": {\n \"value\": \"#39415a\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"opacity\": {\n \"signal\": \"tooltip.entity_id ? 0.5 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tt_off + (metric == 'status' ? 56 : 133)\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'Status: ' + tooltip.status_label : ''\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": [\n {\n \"test\": \"metric == 'status'\",\n \"value\": \"bold\"\n },\n {\n \"value\": \"normal\"\n }\n ],\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"signal\": \"metric == 'status' ? (tooltip.status_num == 0 ? '#F6726A' : tooltip.status_num == 1 ? '#FCD883' : tooltip.status_num == 2 ? '#24C292' : '#BFDBFF') : '#9da4b3'\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tt_off + (metric == 'status' ? 73 : (metric == 'cpu' ? 67 : 150))\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'CPU% (' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last') + '): ' + (tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] != null ? format(tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))], '.1f') + '%' : 'no data') : ''\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": [\n {\n \"test\": \"metric == 'cpu'\",\n \"value\": \"bold\"\n },\n {\n \"value\": \"normal\"\n }\n ],\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"signal\": \"metric == 'cpu' ? (tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] == null ? '#9da4b3' : tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] \u003e= 80 ? '#F6726A' : tooltip[('cpu_' + (metric === 'cpu' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] \u003e= 60 ? '#FCD883' : '#24C292') : '#9da4b3'\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tt_off + (metric == 'status' ? 90 : (metric == 'storage' ? 67 : 150))\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'Free Storage (' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last') + '): ' + (tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] != null ? format(tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))], '.1f') + ' GB' : 'no data') : ''\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": [\n {\n \"test\": \"metric == 'storage'\",\n \"value\": \"bold\"\n },\n {\n \"value\": \"normal\"\n }\n ],\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"signal\": \"metric == 'storage' ? (tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] == null ? '#9da4b3' : tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] \u003e= 20 ? '#24C292' : tooltip[('storage_' + (metric === 'storage' ? ((agg === 'min' || agg === 'max' || agg === 'avg' || agg === 'last') ? agg : 'last') : 'last'))] \u003e= 10 ? '#FCD883' : '#F6726A') : '#9da4b3'\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"name\": \"click_row\",\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 12\n },\n \"y\": {\n \"signal\": \"tt_off + (metric == 'status' ? 110 : 178)\"\n },\n \"text\": {\n \"signal\": \"tooltip.entity_id ? 'Click an hexagon to drill down' : ''\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontStyle\": {\n \"value\": \"italic\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"value\": \"#9da4b3\"\n }\n }\n }\n },\n {\n \"type\": \"area\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"spark_series\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"scale\": \"sparkX\",\n \"field\": \"t\"\n },\n \"y\": {\n \"scale\": \"sparkY\",\n \"field\": \"v\"\n },\n \"y2\": {\n \"signal\": \"spark_bottom\"\n },\n \"fill\": {\n \"signal\": \"metric == 'cpu' ? scale('cpu_color', tooltip.active_val) : (metric == 'storage' ? scale('storage_color', tooltip.active_val) : '#61a2ff')\"\n },\n \"fillOpacity\": {\n \"signal\": \"length(data('spark_stat')) \u0026\u0026 data('spark_stat')[0].vmax \u003e 0 ? 0.18 : 0\"\n },\n \"interpolate\": {\n \"value\": \"monotone\"\n },\n \"defined\": {\n \"signal\": \"datum.v != null\"\n }\n }\n }\n },\n {\n \"type\": \"line\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"spark_series\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"scale\": \"sparkX\",\n \"field\": \"t\"\n },\n \"y\": {\n \"scale\": \"sparkY\",\n \"field\": \"v\"\n },\n \"stroke\": {\n \"signal\": \"metric == 'cpu' ? scale('cpu_color', tooltip.active_val) : (metric == 'storage' ? scale('storage_color', tooltip.active_val) : '#61a2ff')\"\n },\n \"strokeWidth\": {\n \"value\": 1.75\n },\n \"interpolate\": {\n \"value\": \"monotone\"\n },\n \"defined\": {\n \"signal\": \"datum.v != null\"\n }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"spark_series\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"scale\": \"sparkX\",\n \"field\": \"t\"\n },\n \"y\": {\n \"scale\": \"sparkY\",\n \"field\": \"v\"\n },\n \"size\": {\n \"value\": 18\n },\n \"fill\": {\n \"signal\": \"metric == 'cpu' ? scale('cpu_color', tooltip.active_val) : (metric == 'storage' ? scale('storage_color', tooltip.active_val) : '#61a2ff')\"\n },\n \"opacity\": {\n \"signal\": \"(length(data('spark_stat')) \u0026\u0026 data('spark_stat')[0].vn == 1 \u0026\u0026 datum.v != null) ? 1 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"value\": 276\n },\n \"y\": {\n \"signal\": \"tt_off + 67\"\n },\n \"align\": {\n \"value\": \"right\"\n },\n \"text\": {\n \"signal\": \"(tooltip.entity_id \u0026\u0026 metric != 'status' \u0026\u0026 spark_delta != null) ? ('last vs avg ' + (spark_delta \u003e= 0 ? '+' : '') + format(spark_delta, '.1f') + '%') : ''\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fill\": {\n \"value\": \"#c3c8d4\"\n }\n }\n }\n }\n ]\n },\n {\n \"type\": \"rect\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2 - 120\"\n },\n \"x2\": {\n \"signal\": \"(width - legendW) / 2 + 120\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 - 45\"\n },\n \"y2\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 + 45\"\n },\n \"fill\": {\n \"value\": \"#1A1C21\"\n },\n \"fillOpacity\": {\n \"signal\": \"(loading || loading_timeout) ? 0.92 : 0\"\n },\n \"stroke\": {\n \"value\": \"#838C99\"\n },\n \"strokeOpacity\": {\n \"signal\": \"(loading || loading_timeout) ? 0.4 : 0\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"cornerRadius\": {\n \"value\": 12\n }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"spinner_dots\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2 + 18 * cos(datum.i * PI / 4 - PI / 2)\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 - 8 + 18 * sin(datum.i * PI / 4 - PI / 2)\"\n },\n \"size\": {\n \"value\": 70\n },\n \"shape\": {\n \"value\": \"circle\"\n },\n \"fill\": {\n \"value\": \"#0077CC\"\n },\n \"opacity\": {\n \"signal\": \"loading ? 0.15 + 0.85 * (1 - (((floor(tick / 100) % 8) - datum.i + 8) % 8) / 7) : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 + 28\"\n },\n \"text\": {\n \"value\": \"Loading data…\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"value\": \"#FFFFFF\"\n },\n \"opacity\": {\n \"signal\": \"loading \u0026\u0026 !loading_timeout ? 1 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2 + 28\"\n },\n \"text\": {\n \"value\": \"Still loading… (taking longer than usual)\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"value\": \"#FFFFFF\"\n },\n \"opacity\": {\n \"signal\": \"loading_timeout ? 1 : 0\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"interactive\": false,\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"(width - legendW) / 2\"\n },\n \"y\": {\n \"signal\": \"buttonsH + (height - buttonsH) / 2\"\n },\n \"text\": {\n \"value\": \"No databases for the selected time range\"\n },\n \"align\": {\n \"value\": \"center\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 13\n },\n \"fontWeight\": {\n \"value\": 500\n },\n \"fill\": {\n \"value\": \"#838C99\"\n },\n \"opacity\": {\n \"signal\": \"no_data ? 1 : 0\"\n }\n }\n }\n },\n {\n \"name\": \"menu_backdrop\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"enter\": {\n \"cursor\": {\n \"value\": \"default\"\n }\n },\n \"update\": {\n \"x\": {\n \"value\": 0\n },\n \"y\": {\n \"value\": 0\n },\n \"x2\": {\n \"signal\": \"width\"\n },\n \"y2\": {\n \"signal\": \"height\"\n },\n \"fill\": {\n \"value\": \"#000000\"\n },\n \"fillOpacity\": {\n \"value\": 0\n }\n }\n }\n },\n {\n \"name\": \"menu_box\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x\"\n },\n \"y\": {\n \"signal\": \"menu_y\"\n },\n \"width\": {\n \"value\": 248\n },\n \"height\": {\n \"signal\": \"90 + menu_hoff\"\n },\n \"fill\": {\n \"value\": \"#0E1728\"\n },\n \"stroke\": {\n \"value\": \"#2A3144\"\n },\n \"strokeWidth\": {\n \"value\": 1\n },\n \"cornerRadius\": {\n \"value\": 6\n }\n }\n }\n },\n {\n \"name\": \"menu_header\",\n \"type\": \"text\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x + 12\"\n },\n \"y\": {\n \"signal\": \"menu_y + 8\"\n },\n \"text\": {\n \"signal\": \"selected_entity ? (length(selected_entity.id) \u003c= 36 ? [selected_entity.id] : [slice(selected_entity.id, 0, 36), slice(selected_entity.id, 36)]) : ['']\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"top\"\n },\n \"fontSize\": {\n \"value\": 13\n },\n \"fontWeight\": {\n \"value\": \"bold\"\n },\n \"fill\": {\n \"value\": \"#FFFFFF\"\n },\n \"lineHeight\": {\n \"value\": 15\n }\n }\n }\n },\n {\n \"name\": \"menu_separator\",\n \"type\": \"rule\",\n \"from\": {\n \"data\": \"menu_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x + 8\"\n },\n \"x2\": {\n \"signal\": \"menu_x + 240\"\n },\n \"y\": {\n \"signal\": \"menu_y + 26 + menu_hoff\"\n },\n \"stroke\": {\n \"value\": \"#2A3144\"\n },\n \"strokeWidth\": {\n \"value\": 1\n }\n }\n }\n },\n {\n \"name\": \"menu_item_bg\",\n \"type\": \"rect\",\n \"from\": {\n \"data\": \"menu_items_visible\"\n },\n \"encode\": {\n \"enter\": {\n \"cursor\": {\n \"value\": \"pointer\"\n }\n },\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x\"\n },\n \"y\": {\n \"signal\": \"menu_y + 30 + menu_hoff + datum.idx * 30\"\n },\n \"width\": {\n \"value\": 248\n },\n \"height\": {\n \"value\": 30\n },\n \"fill\": {\n \"value\": \"#0E1728\"\n },\n \"href\": {\n \"signal\": \"selected_entity ? (datum.id === 'details' ? ('/app/dashboards#/view/aws_rds_otel-36df60a8-6a6e-4f72-96ce-a3533d24901a?' + g_param + '_a=(filters:!((meta:(alias:!n,disabled:!f,index:%27metrics-*%27,key:DBInstanceIdentifier,negate:!f,params:(query:%27' + selected_entity.id + '%27),type:phrase),query:(match_phrase:(DBInstanceIdentifier:%27' + selected_entity.id + '%27)))),query:(language:kuery,query:%27%27))') : datum.id === 'metrics' ? ('/app/discover#/?_g=(time:(from:%27' + time_from + '%27,to:%27' + time_to + '%27))\u0026_a=(dataSource:(dataViewId:%27metrics-*%27,type:dataView),query:(language:kuery,query:%27' + 'DBInstanceIdentifier:%22' + selected_entity.id + '%22' + '%27))') : '') : ''\"\n },\n \"cornerRadiusBottomLeft\": {\n \"signal\": \"datum.idx === (length(data('menu_items_data')) - 1) ? 8 : 0\"\n },\n \"cornerRadiusBottomRight\": {\n \"signal\": \"datum.idx === (length(data('menu_items_data')) - 1) ? 8 : 0\"\n }\n },\n \"hover\": {\n \"fill\": {\n \"value\": \"#1A2640\"\n }\n }\n }\n },\n {\n \"name\": \"menu_item_label\",\n \"type\": \"text\",\n \"interactive\": false,\n \"from\": {\n \"data\": \"menu_items_visible\"\n },\n \"encode\": {\n \"update\": {\n \"x\": {\n \"signal\": \"menu_x + 14\"\n },\n \"y\": {\n \"signal\": \"menu_y + 30 + menu_hoff + datum.idx * 30 + 15.0\"\n },\n \"text\": {\n \"field\": \"label\"\n },\n \"align\": {\n \"value\": \"left\"\n },\n \"baseline\": {\n \"value\": \"middle\"\n },\n \"fontSize\": {\n \"value\": 12\n },\n \"fill\": {\n \"value\": \"#DFE5EF\"\n }\n }\n }\n }\n ],\n \"background\": \"transparent\",\n \"autosize\": {\n \"type\": \"fit\",\n \"contains\": \"padding\"\n }\n}" }, - { - "columnId": "c_read_lat", - "customLabel": true, - "fieldName": "c_read_lat", - "inMetricDimension": true, - "label": "Avg read latency (ms)", - "meta": { - "esType": "double", - "type": "number" - } + "title": "RDS databases — hexagon map", + "type": "vega", + "uiState": {} + }, + "title": "RDS databases — hexagon map (click an hex for actions)" + }, + "gridData": { + "h": 15, + "i": "rds-hexmap-0001-aaaa-bbbb-ccccdddd0000", + "sectionId": "aws-rds-list-section", + "w": 48, + "x": 0, + "y": 0 + }, + "panelIndex": "rds-hexmap-0001-aaaa-bbbb-ccccdddd0000", + "type": "legacy_vis" + }, + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "tbl-layer-tbl-instances": { + "columns": [ + { + "columnId": "DBInstanceIdentifier", + "customLabel": true, + "fieldName": "DBInstanceIdentifier", + "label": "DB instance", + "meta": { + "esType": "keyword", + "type": "string" + } + }, + { + "columnId": "c_engine", + "customLabel": true, + "fieldName": "c_engine", + "inMetricDimension": true, + "label": "Engine", + "meta": { + "esType": "keyword", + "type": "string" + } + }, + { + "columnId": "c_state_sort", + "customLabel": true, + "fieldName": "c_state_sort", + "inMetricDimension": true, + "label": "State order", + "meta": { + "esType": "integer", + "type": "number" + } + }, + { + "columnId": "c_state", + "customLabel": true, + "fieldName": "c_state", + "inMetricDimension": true, + "label": "State", + "meta": { + "esType": "keyword", + "type": "string" + } + }, + { + "columnId": "c_account", + "customLabel": true, + "fieldName": "c_account", + "label": "Account", + "meta": { + "esType": "keyword", + "type": "string" + } + }, + { + "columnId": "c_region", + "customLabel": true, + "fieldName": "c_region", + "label": "Region", + "meta": { + "esType": "keyword", + "type": "string" + } + }, + { + "columnId": "c_cpu", + "customLabel": true, + "fieldName": "c_cpu", + "inMetricDimension": true, + "label": "Avg CPU (%)", + "meta": { + "esType": "double", + "type": "number" + }, + "params": { + "format": { + "id": "percent", + "params": { + "decimals": 1 + } + } + } + }, + { + "columnId": "c_conn", + "customLabel": true, + "fieldName": "c_conn", + "inMetricDimension": true, + "label": "Current connections", + "meta": { + "esType": "double", + "type": "number" + } + }, + { + "columnId": "c_mem", + "customLabel": true, + "fieldName": "c_mem", + "inMetricDimension": true, + "label": "Current free memory", + "meta": { + "esType": "double", + "type": "number" + }, + "params": { + "format": { + "id": "bytes", + "params": { + "decimals": 2 + } + } + } + }, + { + "columnId": "c_storage", + "customLabel": true, + "fieldName": "c_storage", + "inMetricDimension": true, + "label": "Current free storage", + "meta": { + "esType": "double", + "type": "number" + }, + "params": { + "format": { + "id": "bytes", + "params": { + "decimals": 2 + } + } + } + }, + { + "columnId": "c_read_iops", + "customLabel": true, + "fieldName": "c_read_iops", + "inMetricDimension": true, + "label": "Avg read IOPS", + "meta": { + "esType": "double", + "type": "number" + } + }, + { + "columnId": "c_write_iops", + "customLabel": true, + "fieldName": "c_write_iops", + "inMetricDimension": true, + "label": "Avg write IOPS", + "meta": { + "esType": "double", + "type": "number" + } + }, + { + "columnId": "c_read_lat", + "customLabel": true, + "fieldName": "c_read_lat", + "inMetricDimension": true, + "label": "Avg read latency (ms)", + "meta": { + "esType": "double", + "type": "number" + } + }, + { + "columnId": "c_write_lat", + "customLabel": true, + "fieldName": "c_write_lat", + "inMetricDimension": true, + "label": "Avg write latency (ms)", + "meta": { + "esType": "double", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n AND cloud.account.id IS NOT NULL\n| STATS\n c_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))) / 100.0,\n c_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n c_mem = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeableMemory`, NULL))),\n c_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n c_read_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadIOPS`, NULL))),\n c_write_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteIOPS`, NULL))),\n c_read_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadLatency`, NULL))) * 1000,\n c_write_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteLatency`, NULL))) * 1000,\n state_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n state_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n c_binlog = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/BinLogDiskUsage`, NULL))),\n c_txid = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/MaximumUsedTransactionIDs`, NULL))),\n c_txlog = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/TransactionLogsGeneration`, NULL))),\n c_replslot = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReplicationSlotDiskUsage`, NULL))),\n c_failedjobs = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FailedSQLServerAgentJobsCount`, NULL))),\n c_tempdb = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/TempDbDataFileUsage`, NULL))),\n c_swap = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/SwapUsage`, NULL)))\n BY DBInstanceIdentifier, c_account = cloud.account.id, c_region = cloud.region\n| EVAL\n c_engine = CASE(\n c_failedjobs IS NOT NULL OR c_tempdb IS NOT NULL, \"SQL Server\",\n c_txid IS NOT NULL OR c_txlog IS NOT NULL OR c_replslot IS NOT NULL, \"PostgreSQL\",\n c_binlog IS NOT NULL, \"MySQL / MariaDB\",\n c_swap IS NOT NULL, \"Oracle\",\n \"Other\"),\n c_state_sort = CASE(\n state_cpu IS NULL AND state_storage IS NULL, 4,\n state_cpu \u003e 80, 1,\n state_storage \u003c 10737418240, 2,\n 3),\n c_state = CASE(\n state_cpu IS NULL AND state_storage IS NULL, \"Unknown\",\n state_cpu \u003e 80, \"Saturated\",\n state_storage \u003c 10737418240, \"Low storage\",\n \"Healthy\")\n| SORT c_state_sort ASC" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n AND cloud.account.id IS NOT NULL\n| STATS\n c_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))) / 100.0,\n c_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n c_mem = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeableMemory`, NULL))),\n c_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n c_read_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadIOPS`, NULL))),\n c_write_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteIOPS`, NULL))),\n c_read_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadLatency`, NULL))) * 1000,\n c_write_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteLatency`, NULL))) * 1000,\n state_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n state_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n c_binlog = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/BinLogDiskUsage`, NULL))),\n c_txid = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/MaximumUsedTransactionIDs`, NULL))),\n c_txlog = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/TransactionLogsGeneration`, NULL))),\n c_replslot = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReplicationSlotDiskUsage`, NULL))),\n c_failedjobs = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FailedSQLServerAgentJobsCount`, NULL))),\n c_tempdb = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/TempDbDataFileUsage`, NULL))),\n c_swap = MAX(max_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/SwapUsage`, NULL)))\n BY DBInstanceIdentifier, c_account = cloud.account.id, c_region = cloud.region\n| EVAL\n c_engine = CASE(\n c_failedjobs IS NOT NULL OR c_tempdb IS NOT NULL, \"SQL Server\",\n c_txid IS NOT NULL OR c_txlog IS NOT NULL OR c_replslot IS NOT NULL, \"PostgreSQL\",\n c_binlog IS NOT NULL, \"MySQL / MariaDB\",\n c_swap IS NOT NULL, \"Oracle\",\n \"Other\"),\n c_state_sort = CASE(\n state_cpu IS NULL AND state_storage IS NULL, 4,\n state_cpu \u003e 80, 1,\n state_storage \u003c 10737418240, 2,\n 3),\n c_state = CASE(\n state_cpu IS NULL AND state_storage IS NULL, \"Unknown\",\n state_cpu \u003e 80, \"Saturated\",\n state_storage \u003c 10737418240, \"Low storage\",\n \"Healthy\")\n| SORT c_state_sort ASC" + }, + "visualization": { + "columns": [ + { + "columnId": "DBInstanceIdentifier", + "isMetric": false, + "isTransposed": false, + "oneClickFilter": true, + "width": 220 + }, + { + "columnId": "c_engine", + "isMetric": true, + "isTransposed": false, + "oneClickFilter": true, + "width": 140 + }, + { + "columnId": "c_state_sort", + "hidden": true, + "isMetric": true, + "isTransposed": false + }, + { + "colorMapping": { + "assignments": [ + { + "color": { + "colorCode": "#ffc9c2", + "type": "colorCode" + }, + "rules": [ + { + "matchCase": true, + "matchEntireWord": true, + "pattern": "Saturated", + "type": "match" + } + ], + "touched": true + }, + { + "color": { + "colorCode": "#FFF3C2", + "type": "colorCode" + }, + "rules": [ + { + "matchCase": true, + "matchEntireWord": true, + "pattern": "Low storage", + "type": "match" + } + ], + "touched": true + }, + { + "color": { + "colorCode": "#BFDBFF", + "type": "colorCode" + }, + "rules": [ + { + "type": "raw", + "value": "Unknown" + } + ], + "touched": true + }, + { + "color": { + "colorCode": "#AEE8D2", + "type": "colorCode" + }, + "rules": [ + { + "type": "raw", + "value": "Healthy" + } + ], + "touched": true + } + ], + "colorMode": { + "type": "categorical" + }, + "paletteId": "default", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rules": [ + { + "type": "other" + } + ], + "touched": false + } + ] + }, + "colorMode": "badge", + "columnId": "c_state", + "isTransposed": false, + "width": 120 + }, + { + "columnId": "c_account", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "c_region", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "c_cpu", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "c_conn", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "c_mem", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "c_storage", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "c_read_iops", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "c_write_iops", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "c_read_lat", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "c_write_lat", + "isMetric": true, + "isTransposed": false + } + ], + "fitRowToContent": false, + "headerRowHeight": "single", + "headerRowHeightLines": 1, + "layerId": "tbl-layer-tbl-instances", + "layerType": "data", + "paging": { + "enabled": true, + "size": 25 + }, + "rowHeight": "single", + "rowHeightLines": 1, + "showRowNumbers": true, + "sorting": { + "columnId": "c_state_sort", + "direction": "asc" + } + } }, + "title": "", + "version": 2, + "visualizationType": "lnsDatatable" + }, + "description": "All RDS databases, ranked worst-first by state. Click a database to drill into its metrics. State reflects the latest values within a 5-minute freshness window. Avg CPU, read/write latency, and IOPS are averaged over the selected time range; free memory, free storage, and connections are current (last) values.", + "drilldowns": [ { - "columnId": "c_write_lat", - "customLabel": true, - "fieldName": "c_write_lat", - "inMetricDimension": true, - "label": "Avg write latency (ms)", - "meta": { - "esType": "double", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n AND cloud.account.id IS NOT NULL\n| STATS\n c_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))) / 100.0,\n c_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n c_mem = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeableMemory`, NULL))),\n c_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n c_read_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadIOPS`, NULL))),\n c_write_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteIOPS`, NULL))),\n c_read_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadLatency`, NULL))) * 1000,\n c_write_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteLatency`, NULL))) * 1000,\n state_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n state_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)))\n BY DBInstanceIdentifier, c_account = cloud.account.id, c_region = cloud.region\n| EVAL\n c_state_sort = CASE(\n state_cpu IS NULL AND state_storage IS NULL, 4,\n state_cpu > 80, 1,\n state_storage < 5368709120, 2,\n 3),\n c_state = CASE(\n state_cpu IS NULL AND state_storage IS NULL, \"Unknown\",\n state_cpu > 80, \"saturated\",\n state_storage < 5368709120, \"low-storage\",\n \"healthy\")\n| SORT c_state_sort ASC" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n AND cloud.account.id IS NOT NULL\n| STATS\n c_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))) / 100.0,\n c_conn = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL))),\n c_mem = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeableMemory`, NULL))),\n c_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL))),\n c_read_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadIOPS`, NULL))),\n c_write_iops = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteIOPS`, NULL))),\n c_read_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/ReadLatency`, NULL))) * 1000,\n c_write_lat = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/WriteLatency`, NULL))) * 1000,\n state_cpu = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL))),\n state_storage = AVG(avg_over_time(CASE(stat == \"Average\",\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)))\n BY DBInstanceIdentifier, c_account = cloud.account.id, c_region = cloud.region\n| EVAL\n c_state_sort = CASE(\n state_cpu IS NULL AND state_storage IS NULL, 4,\n state_cpu > 80, 1,\n state_storage < 5368709120, 2,\n 3),\n c_state = CASE(\n state_cpu IS NULL AND state_storage IS NULL, \"Unknown\",\n state_cpu > 80, \"saturated\",\n state_storage < 5368709120, \"low-storage\",\n \"healthy\")\n| SORT c_state_sort ASC" - }, - "visualization": { - "columns": [ - { - "columnId": "DBInstanceIdentifier", - "isMetric": false, - "isTransposed": false, - "oneClickFilter": true, - "width": 220 - }, - { - "columnId": "c_state_sort", - "hidden": true, - "isMetric": true, - "isTransposed": false - }, - { - "colorMapping": { - "assignments": [ - { - "color": { - "colorCode": "#ffc9c2", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "saturated" - } - ], - "touched": true + "dashboardRefName": "dashboard_drilldown_aws_rds_otel-36df60a8-6a6e-4f72-96ce-a3533d24901a", + "label": "1. View details", + "open_in_new_tab": false, + "trigger": "on_apply_filter", + "type": "dashboard_drilldown", + "use_filters": false, + "use_time_range": true }, { - "color": { - "colorCode": "#FFF3C2", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "low-storage" - } - ], - "touched": true + "encode_url": true, + "label": "2. View metrics in Discover", + "open_in_new_tab": true, + "trigger": "on_click_value", + "type": "url_drilldown", + "url": "{{kibanaUrl}}/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:60000),time:(from:'{{context.panel.timeRange.from}}',to:'{{context.panel.timeRange.to}}'))\u0026_a=(dataSource:(dataViewId:'metrics-*',type:dataView),filters:!((meta:(alias:!n,disabled:!f,index:'metrics-*',key:DBInstanceIdentifier,negate:!f,params:(query:'{{event.value}}'),type:phrase),query:(match_phrase:(DBInstanceIdentifier:'{{event.value}}')))),interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))" }, { - "color": { - "colorCode": "#BFDBFF", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "Unknown" - } - ], - "touched": true + "encode_url": false, + "label": "3. View in AWS console", + "open_in_new_tab": true, + "trigger": "on_click_value", + "type": "url_drilldown", + "url": "https://console.aws.amazon.com/rds/home#database:id={{event.value}};is-cluster=false" }, { - "color": { - "colorCode": "#AEE8D2", - "type": "colorCode" - }, - "rules": [ - { - "type": "raw", - "value": "healthy" - } - ], - "touched": true + "encode_url": false, + "label": "4. View Performance Insights in AWS", + "open_in_new_tab": true, + "trigger": "on_click_value", + "type": "url_drilldown", + "url": "https://console.aws.amazon.com/rds/home#performance-insights-v20206:/resourceId/{{event.value}}" } - ], - "colorMode": { - "type": "categorical" - }, - "paletteId": "default", - "specialAssignments": [ - { - "color": { - "type": "loop" - }, - "rules": [ - { - "type": "other" + ], + "title": "Databases" + }, + "gridData": { + "h": 16, + "i": "tbl-instances", + "sectionId": "aws-rds-list-section", + "w": 48, + "x": 0, + "y": 15 + }, + "panelIndex": "tbl-instances", + "type": "vis" + }, + { + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "layer-kpi-net-in": { + "columns": [ + { + "columnId": "col-kpi-net-in", + "customLabel": true, + "fieldName": "total_conn", + "inMetricDimension": true, + "label": "Max connections", + "meta": { + "esType": "long", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS\n peak_conn = MAX(max_over_time(\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`)) WHERE stat == \"Maximum\",\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_ts = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_ts) \u003c= 5\n| STATS total_conn = MAX(peak_conn)\n| KEEP total_conn" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS\n peak_conn = MAX(max_over_time(\n `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`)) WHERE stat == \"Maximum\",\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_ts = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_ts) \u003c= 5\n| STATS total_conn = MAX(peak_conn)\n| KEEP total_conn" + }, + "visualization": { + "applyColorTo": "background", + "color": "#61a2ff00", + "colorMode": "background", + "layerId": "layer-kpi-net-in", + "layerType": "data", + "metricAccessor": "col-kpi-net-in", + "primaryAlign": "left", + "primaryPosition": "top", + "showBar": false, + "titlesTextAlign": "left", + "titlesTextSize": "xs", + "valueFontMode": "default", + "valuesTextSize": "s" } - ], - "touched": false - } - ] + }, + "title": "", + "version": 2, + "visualizationType": "lnsMetric" }, - "colorMode": "badge", - "columnId": "c_state", - "isTransposed": false, - "width": 120 - }, - { - "columnId": "c_account", - "isMetric": false, - "isTransposed": false - }, - { - "columnId": "c_region", - "isMetric": false, - "isTransposed": false - }, - { - "columnId": "c_cpu", - "isMetric": true, - "isTransposed": false - }, - { - "columnId": "c_conn", - "isMetric": true, - "isTransposed": false - }, - { - "columnId": "c_mem", - "isMetric": true, - "isTransposed": false - }, - { - "columnId": "c_storage", - "isMetric": true, - "isTransposed": false - }, - { - "columnId": "c_read_iops", - "isMetric": true, - "isTransposed": false - }, - { - "columnId": "c_write_iops", - "isMetric": true, - "isTransposed": false - }, - { - "columnId": "c_read_lat", - "isMetric": true, - "isTransposed": false - }, - { - "columnId": "c_write_lat", - "isMetric": true, - "isTransposed": false - } - ], - "fitRowToContent": false, - "headerRowHeight": "single", - "headerRowHeightLines": 1, - "layerId": "tbl-layer-tbl-instances", - "layerType": "data", - "paging": { - "enabled": true, - "size": 25 + "description": "Highest concurrent connections observed on any single database — peak over the selected time range. Approaching an instance's connection limit can reject new clients.", + "hide_title": true, + "title": "" }, - "rowHeight": "single", - "rowHeightLines": 1, - "showRowNumbers": true, - "sorting": { - "columnId": "c_state_sort", - "direction": "asc" - } - } + "gridData": { + "h": 6, + "i": "kpi-net-in", + "sectionId": "aws-rds-per-database-section", + "w": 6, + "x": 0, + "y": 24 + }, + "panelIndex": "kpi-net-in", + "type": "vis" }, - "title": "", - "version": 2, - "visualizationType": "lnsDatatable" - }, - "description": "All RDS databases, ranked worst-first by state. Click a database to drill into its metrics. State reflects the latest values within a 5-minute freshness window. Avg CPU, read/write latency, and IOPS are averaged over the selected time range; free memory, free storage, and connections are current (last) values.", - "drilldowns": [ { - "encode_url": false, - "label": "View Performance Insights in AWS", - "open_in_new_tab": true, - "trigger": "on_click_value", - "type": "url_drilldown", - "url": "https://console.aws.amazon.com/rds/home#performance-insights-v20206:/resourceId/{{event.value}}" + "embeddableConfig": { + "attributes": { + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "indexPatternRefs": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "timeField": "@timestamp", + "title": "metrics-aws.rds.otel-*" + } + ], + "layers": { + "layer-kpi-net-out": { + "columns": [ + { + "columnId": "col-kpi-net-out", + "customLabel": true, + "fieldName": "total_storage", + "inMetricDimension": true, + "label": "Total free storage", + "meta": { + "esType": "long", + "type": "number" + }, + "params": { + "format": { + "id": "bytes", + "params": { + "decimals": 2 + } + } + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS\n storage_cur = AVG(avg_over_time(\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)) WHERE stat == \"Average\",\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_ts = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_ts) \u003c= 5\n| STATS total_storage = SUM(storage_cur)\n| KEEP total_storage" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "needsRefresh": false, + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-*\n| WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\"\n| STATS\n storage_cur = AVG(avg_over_time(\n `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`)) WHERE stat == \"Average\",\n last_seen = MAX(@timestamp)\n BY DBInstanceIdentifier, cloud.region\n| INLINE STATS latest_ts = MAX(last_seen)\n| WHERE DATE_DIFF(\"minute\", last_seen, latest_ts) \u003c= 5\n| STATS total_storage = SUM(storage_cur)\n| KEEP total_storage" + }, + "visualization": { + "applyColorTo": "background", + "color": "#61a2ff00", + "colorMode": "background", + "layerId": "layer-kpi-net-out", + "layerType": "data", + "metricAccessor": "col-kpi-net-out", + "primaryAlign": "left", + "primaryPosition": "top", + "showBar": false, + "titlesTextAlign": "left", + "titlesTextSize": "xs", + "valueFontMode": "default", + "valuesTextSize": "s" + } + }, + "title": "", + "version": 2, + "visualizationType": "lnsMetric" + }, + "description": "Total free storage across all non-Aurora databases — the sum of each database's lowest observed free storage (bytes) over the selected time range. Falling values indicate cluster-wide disk pressure.", + "hide_title": true, + "title": "" + }, + "gridData": { + "h": 6, + "i": "kpi-net-out", + "sectionId": "aws-rds-per-database-section", + "w": 6, + "x": 0, + "y": 30 + }, + "panelIndex": "kpi-net-out", + "type": "vis" }, { - "encode_url": false, - "label": "View in AWS", - "open_in_new_tab": true, - "trigger": "on_click_value", - "type": "url_drilldown", - "url": "https://console.aws.amazon.com/rds/home#database:id={{event.value}};is-cluster=false" - } - ], - "title": "Databases" - }, - "gridData": { - "x": 0, - "y": 15, - "w": 48, - "h": 16, - "i": "tbl-instances", - "sectionId": "aws-rds-list-section" - }, - "panelIndex": "tbl-instances", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Highest concurrent connections observed on any single database — peak over the selected time range. Approaching an instance's connection limit can reject new clients.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "layer-kpi-net-in": { - "columns": [ - { - "columnId": "col-kpi-net-in", - "customLabel": true, - "fieldName": "total_conn", - "inMetricDimension": true, - "label": "Max connections", - "meta": { - "esType": "long", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat IN (\"Maximum\", \"Minimum\") | INLINE STATS latest_global = MAX(@timestamp) | WHERE DATE_DIFF(\"minutes\", @timestamp, latest_global) <= 5 | STATS cpu_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL)), conn_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)), storage_cur = MIN(CASE(stat == \"Minimum\", `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)) BY DBInstanceIdentifier, cloud.region | EVAL state = CASE(cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\", cpu_cur > 80, \"saturated\", storage_cur < 5368709120, \"low-storage\", \"healthy\") | STATS total_conn = SUM(conn_cur) | KEEP total_conn" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "textBasedLanguages-datasource-layer-layer-kpi-net-in", - "type": "index-pattern" - } - ], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat IN (\"Maximum\", \"Minimum\") | INLINE STATS latest_global = MAX(@timestamp) | WHERE DATE_DIFF(\"minutes\", @timestamp, latest_global) <= 5 | STATS cpu_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL)), conn_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)), storage_cur = MIN(CASE(stat == \"Minimum\", `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)) BY DBInstanceIdentifier, cloud.region | EVAL state = CASE(cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\", cpu_cur > 80, \"saturated\", storage_cur < 5368709120, \"low-storage\", \"healthy\") | STATS total_conn = SUM(conn_cur) | KEEP total_conn" - }, - "visualization": { - "applyColorTo": "background", - "color": "#61a2ff00", - "colorMode": "background", - "layerId": "layer-kpi-net-in", - "layerType": "data", - "metricAccessor": "col-kpi-net-in", - "primaryAlign": "left", - "primaryPosition": "top", - "showBar": false, - "titlesTextAlign": "left", - "titlesTextSize": "xs", - "valueFontMode": "default", - "valuesTextSize": "s" - } - }, - "title": "", - "version": 2, - "visualizationType": "lnsMetric" - }, - "description": "Highest concurrent connections observed on any single database — peak over the selected time range. Approaching an instance's connection limit can reject new clients.", - "hide_title": true, - "title": "" - }, - "gridData": { - "h": 6, - "i": "kpi-net-in", - "sectionId": "aws-rds-per-database-section", - "w": 6, - "x": 0, - "y": 24 - }, - "panelIndex": "kpi-net-in", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Total free storage across all non-Aurora databases — the sum of each database's lowest observed free storage (bytes) over the selected time range. Falling values indicate cluster-wide disk pressure.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "indexPatternRefs": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "timeField": "@timestamp", - "title": "metrics-aws.rds.otel-*" - } - ], - "layers": { - "layer-kpi-net-out": { - "columns": [ - { - "columnId": "col-kpi-net-out", - "customLabel": true, - "fieldName": "total_storage", - "inMetricDimension": true, - "label": "Total free storage", - "meta": { - "esType": "long", - "type": "number" - }, - "params": { - "format": { - "id": "bytes", - "params": { - "decimals": 2 - } + "embeddableConfig": { + "attributes": { + "description": "Top 10 RDS databases by peak CPU utilization (%) over the selected time range. Reference line at 80% marks the high-CPU threshold; bars crossing it indicate CPU-bound databases.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-top10-cpu": { + "columns": [ + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "peak_cpu", + "customLabel": true, + "fieldName": "peak_cpu", + "inMetricDimension": true, + "label": "Max CPU", + "meta": { + "esType": "double", + "type": "number" + }, + "params": { + "format": { + "id": "percent", + "params": { + "decimals": 1 + } + } + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | STATS peak_cpu = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY DBInstanceIdentifier, cloud.region | SORT peak_cpu DESC | LIMIT 10" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-top10-cpu", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | STATS peak_cpu = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY DBInstanceIdentifier, cloud.region | SORT peak_cpu DESC | LIMIT 10" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "peak_cpu" + ], + "layerId": "xy-layer-top10-cpu", + "layerType": "data", + "seriesType": "bar_horizontal", + "showGridlines": false, + "xAccessor": "DBInstanceIdentifier" + } + ], + "legend": { + "isVisible": false, + "position": "bottom" + }, + "preferredSeriesType": "bar_horizontal", + "valueLabels": "show" } - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat IN (\"Maximum\", \"Minimum\") | INLINE STATS latest_global = MAX(@timestamp) | WHERE DATE_DIFF(\"minutes\", @timestamp, latest_global) <= 5 | STATS cpu_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL)), conn_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)), storage_cur = MIN(CASE(stat == \"Minimum\", `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)) BY DBInstanceIdentifier, cloud.region | EVAL state = CASE(cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\", cpu_cur > 80, \"saturated\", storage_cur < 5368709120, \"low-storage\", \"healthy\") | STATS total_storage = SUM(storage_cur) | KEEP total_storage" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "textBasedLanguages-datasource-layer-layer-kpi-net-out", - "type": "index-pattern" - } - ], - "needsRefresh": false, - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nFROM metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat IN (\"Maximum\", \"Minimum\") | INLINE STATS latest_global = MAX(@timestamp) | WHERE DATE_DIFF(\"minutes\", @timestamp, latest_global) <= 5 | STATS cpu_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/CPUUtilization`, NULL)), conn_cur = MAX(CASE(stat == \"Maximum\", `metrics.amazonaws.com/AWS/RDS/DatabaseConnections`, NULL)), storage_cur = MIN(CASE(stat == \"Minimum\", `metrics.amazonaws.com/AWS/RDS/FreeStorageSpace`, NULL)) BY DBInstanceIdentifier, cloud.region | EVAL state = CASE(cpu_cur IS NULL AND conn_cur IS NULL AND storage_cur IS NULL, \"Unknown\", cpu_cur > 80, \"saturated\", storage_cur < 5368709120, \"low-storage\", \"healthy\") | STATS total_storage = SUM(storage_cur) | KEEP total_storage" - }, - "visualization": { - "applyColorTo": "background", - "color": "#61a2ff00", - "colorMode": "background", - "layerId": "layer-kpi-net-out", - "layerType": "data", - "metricAccessor": "col-kpi-net-out", - "primaryAlign": "left", - "primaryPosition": "top", - "showBar": false, - "titlesTextAlign": "left", - "titlesTextSize": "xs", - "valueFontMode": "default", - "valuesTextSize": "s" - } - }, - "title": "", - "version": 2, - "visualizationType": "lnsMetric" - }, - "description": "Total free storage across all non-Aurora databases — the sum of each database's lowest observed free storage (bytes) over the selected time range. Falling values indicate cluster-wide disk pressure.", - "hide_title": true, - "title": "" - }, - "gridData": { - "h": 6, - "i": "kpi-net-out", - "sectionId": "aws-rds-per-database-section", - "w": 6, - "x": 0, - "y": 30 - }, - "panelIndex": "kpi-net-out", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Top 10 RDS databases by peak CPU utilization (%) over the selected time range. Reference line at 80% marks the high-CPU threshold; bars crossing it indicate CPU-bound databases.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-top10-cpu": { - "columns": [ - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } }, - { - "columnId": "peak_cpu", - "customLabel": true, - "fieldName": "peak_cpu", - "inMetricDimension": true, - "label": "Max CPU", - "meta": { - "esType": "double", - "type": "number" - }, - "params": { - "format": { - "id": "percent", - "params": { - "decimals": 1 - } - } - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | STATS peak_cpu = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY DBInstanceIdentifier, cloud.region | SORT peak_cpu DESC | LIMIT 10" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-top10-cpu", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | STATS peak_cpu = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY DBInstanceIdentifier, cloud.region | SORT peak_cpu DESC | LIMIT 10" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + "title": "Top 10 RDS databases by CPU utilization", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Top 10 RDS databases by peak CPU utilization (%) over the selected time range.", + "title": "Top 10 RDS databases by CPU utilization" }, - "layers": [ - { - "accessors": [ - "peak_cpu" - ], - "layerId": "xy-layer-top10-cpu", - "layerType": "data", - "seriesType": "bar_horizontal", - "showGridlines": false, - "xAccessor": "DBInstanceIdentifier" - } - ], - "legend": { - "isVisible": false, - "position": "bottom" + "gridData": { + "h": 12, + "i": "top10-cpu", + "sectionId": "aws-rds-per-database-section", + "w": 14, + "x": 6, + "y": 24 }, - "preferredSeriesType": "bar_horizontal", - "valueLabels": "show" - } + "panelIndex": "top10-cpu", + "type": "vis" }, - "title": "Top 10 RDS databases by CPU utilization", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Top 10 RDS databases by peak CPU utilization (%) over the selected time range. Reference line at 80% marks the high-CPU threshold; bars crossing it indicate CPU-bound databases.", - "title": "Top 10 RDS databases by CPU utilization" - }, - "gridData": { - "h": 12, - "i": "top10-cpu", - "sectionId": "aws-rds-per-database-section", - "w": 14, - "x": 6, - "y": 24 - }, - "panelIndex": "top10-cpu", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Top 10 RDS databases by peak concurrent connections over the selected time range. Approaching the instance connection limit can reject new clients.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-top10-connections": { - "columns": [ - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } + { + "embeddableConfig": { + "attributes": { + "description": "Top 10 RDS databases by peak concurrent connections over the selected time range. Approaching the instance connection limit can reject new clients.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-top10-connections": { + "columns": [ + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "peak_conn", + "customLabel": true, + "fieldName": "peak_conn", + "inMetricDimension": true, + "label": "Max connections", + "meta": { + "esType": "double", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/DatabaseConnections` IS NOT NULL | STATS peak_conn = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/DatabaseConnections`)) BY DBInstanceIdentifier, cloud.region | SORT peak_conn DESC | LIMIT 10" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-top10-connections", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/DatabaseConnections` IS NOT NULL | STATS peak_conn = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/DatabaseConnections`)) BY DBInstanceIdentifier, cloud.region | SORT peak_conn DESC | LIMIT 10" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "peak_conn" + ], + "layerId": "xy-layer-top10-connections", + "layerType": "data", + "seriesType": "bar_horizontal", + "showGridlines": false, + "xAccessor": "DBInstanceIdentifier" + } + ], + "legend": { + "isVisible": false, + "position": "bottom" + }, + "preferredSeriesType": "bar_horizontal", + "valueLabels": "show" + } }, - { - "columnId": "peak_conn", - "customLabel": true, - "fieldName": "peak_conn", - "inMetricDimension": true, - "label": "Max connections", - "meta": { - "esType": "double", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/DatabaseConnections` IS NOT NULL | STATS peak_conn = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/DatabaseConnections`)) BY DBInstanceIdentifier, cloud.region | SORT peak_conn DESC | LIMIT 10" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-top10-connections", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/DatabaseConnections` IS NOT NULL | STATS peak_conn = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/DatabaseConnections`)) BY DBInstanceIdentifier, cloud.region | SORT peak_conn DESC | LIMIT 10" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + "title": "Top 10 RDS databases by connections", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Top 10 RDS databases by peak concurrent connections over the selected time range. Approaching the instance connection limit can reject new clients.", + "title": "Top 10 RDS databases by connections" }, - "layers": [ - { - "accessors": [ - "peak_conn" - ], - "layerId": "xy-layer-top10-connections", - "layerType": "data", - "seriesType": "bar_horizontal", - "showGridlines": false, - "xAccessor": "DBInstanceIdentifier" - } - ], - "legend": { - "isVisible": false, - "position": "bottom" + "gridData": { + "h": 12, + "i": "top10-connections", + "sectionId": "aws-rds-per-database-section", + "w": 14, + "x": 20, + "y": 24 }, - "preferredSeriesType": "bar_horizontal", - "valueLabels": "show" - } + "panelIndex": "top10-connections", + "type": "vis" }, - "title": "Top 10 RDS databases by connections", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Top 10 RDS databases by peak concurrent connections over the selected time range. Approaching the instance connection limit can reject new clients.", - "title": "Top 10 RDS databases by connections" - }, - "gridData": { - "h": 12, - "i": "top10-connections", - "sectionId": "aws-rds-per-database-section", - "w": 14, - "x": 20, - "y": 24 - }, - "panelIndex": "top10-connections", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Top 10 RDS databases by peak read IOPS over the selected time range. High values flag read-heavy databases that may saturate storage throughput.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-top10-readiops": { - "columns": [ - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } + { + "embeddableConfig": { + "attributes": { + "description": "Top 10 RDS databases by peak read IOPS over the selected time range. High values flag read-heavy databases that may saturate storage throughput.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-top10-readiops": { + "columns": [ + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "peak_read_iops", + "customLabel": true, + "fieldName": "peak_read_iops", + "inMetricDimension": true, + "label": "Max read IOPS", + "meta": { + "esType": "double", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL | STATS peak_read_iops = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY DBInstanceIdentifier, cloud.region | SORT peak_read_iops DESC | LIMIT 10" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-top10-readiops", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL | STATS peak_read_iops = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY DBInstanceIdentifier, cloud.region | SORT peak_read_iops DESC | LIMIT 10" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "peak_read_iops" + ], + "layerId": "xy-layer-top10-readiops", + "layerType": "data", + "seriesType": "bar_horizontal", + "showGridlines": false, + "xAccessor": "DBInstanceIdentifier" + } + ], + "legend": { + "isVisible": false, + "position": "bottom" + }, + "preferredSeriesType": "bar_horizontal", + "valueLabels": "show" + } }, - { - "columnId": "peak_read_iops", - "customLabel": true, - "fieldName": "peak_read_iops", - "inMetricDimension": true, - "label": "Max read IOPS", - "meta": { - "esType": "double", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL | STATS peak_read_iops = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY DBInstanceIdentifier, cloud.region | SORT peak_read_iops DESC | LIMIT 10" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-top10-readiops", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Maximum\" AND `metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL | STATS peak_read_iops = MAX(max_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY DBInstanceIdentifier, cloud.region | SORT peak_read_iops DESC | LIMIT 10" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + "title": "Top 10 RDS databases by read IOPS", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Top 10 RDS databases by peak read IOPS over the selected time range. High values flag read-heavy databases that may saturate storage throughput.", + "title": "Top 10 RDS databases by read IOPS" }, - "layers": [ - { - "accessors": [ - "peak_read_iops" - ], - "layerId": "xy-layer-top10-readiops", - "layerType": "data", - "seriesType": "bar_horizontal", - "showGridlines": false, - "xAccessor": "DBInstanceIdentifier" - } - ], - "legend": { - "isVisible": false, - "position": "bottom" + "gridData": { + "h": 12, + "i": "top10-readiops", + "sectionId": "aws-rds-per-database-section", + "w": 14, + "x": 34, + "y": 24 }, - "preferredSeriesType": "bar_horizontal", - "valueLabels": "show" - } + "panelIndex": "top10-readiops", + "type": "vis" }, - "title": "Top 10 RDS databases by read IOPS", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Top 10 RDS databases by peak read IOPS over the selected time range. High values flag read-heavy databases that may saturate storage throughput.", - "title": "Top 10 RDS databases by read IOPS" - }, - "gridData": { - "h": 12, - "i": "top10-readiops", - "sectionId": "aws-rds-per-database-section", - "w": 14, - "x": 34, - "y": 24 - }, - "panelIndex": "top10-readiops", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Average freeable memory per database over time (bytes, averaged per bucket). Top 10 databases by freeable memory per bucket. Low or falling values indicate memory pressure.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-chart-memory": { - "columns": [ - { - "columnId": "timestamp", - "fieldName": "timestamp", - "meta": { - "esType": "date", - "type": "date" - } - }, - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } - }, - { - "columnId": "metric", - "customLabel": true, - "fieldName": "metric", - "inMetricDimension": true, - "label": "Freeable memory", - "meta": { - "esType": "double", - "type": "number" - }, - "params": { - "format": { - "id": "bytes", - "params": { - "decimals": 2 - } + { + "embeddableConfig": { + "attributes": { + "description": "Average freeable memory per database over time (bytes, averaged per bucket). Top 10 databases by freeable memory per bucket. Low or falling values indicate memory pressure.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-chart-memory": { + "columns": [ + { + "columnId": "timestamp", + "fieldName": "timestamp", + "meta": { + "esType": "date", + "type": "date" + } + }, + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "metric", + "customLabel": true, + "fieldName": "metric", + "inMetricDimension": true, + "label": "Freeable memory", + "meta": { + "esType": "double", + "type": "number" + }, + "params": { + "format": { + "id": "bytes", + "params": { + "decimals": 2 + } + } + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/FreeableMemory` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/FreeableMemory`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric ASC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-chart-memory", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/FreeableMemory` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/FreeableMemory`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric ASC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "metric" + ], + "layerId": "xy-layer-chart-memory", + "layerType": "data", + "seriesType": "line", + "showGridlines": false, + "splitAccessors": [ + "DBInstanceIdentifier" + ], + "xAccessor": "timestamp" + } + ], + "legend": { + "isVisible": true, + "position": "bottom" + }, + "preferredSeriesType": "line", + "valueLabels": "hide" } - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/FreeableMemory` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/FreeableMemory`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric ASC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-chart-memory", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/FreeableMemory` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/FreeableMemory`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric ASC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + }, + "title": "Top 10 RDS databases by freeable memory", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Average freeable memory per database over time (bytes, averaged per bucket). Top 10 databases by freeable memory per bucket. Low or falling values indicate memory pressure.", + "title": "Top 10 RDS databases by freeable memory" }, - "layers": [ - { - "accessors": [ - "metric" - ], - "layerId": "xy-layer-chart-memory", - "layerType": "data", - "seriesType": "line", - "showGridlines": false, - "splitAccessors": [ - "DBInstanceIdentifier" - ], - "xAccessor": "timestamp" - } - ], - "legend": { - "isVisible": true, - "position": "bottom" + "gridData": { + "h": 12, + "i": "chart-memory", + "sectionId": "aws-rds-per-database-section", + "w": 16, + "x": 32, + "y": 12 }, - "preferredSeriesType": "line", - "valueLabels": "hide" - } + "panelIndex": "chart-memory", + "type": "vis" }, - "title": "Top 10 RDS databases by freeable memory", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Average freeable memory per database over time (bytes, averaged per bucket). Top 10 databases by freeable memory per bucket. Low or falling values indicate memory pressure.", - "title": "Top 10 RDS databases by freeable memory" - }, - "gridData": { - "h": 12, - "i": "chart-memory", - "sectionId": "aws-rds-per-database-section", - "w": 16, - "x": 32, - "y": 12 - }, - "panelIndex": "chart-memory", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Average CPU utilization (%) per database over time (averaged per bucket). Reference line at 80% marks the high-CPU threshold. Top 10 databases by CPU per bucket.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "ref-cpu-80": { - "columns": [ - { - "columnId": "alert_threshold", - "customLabel": true, - "fieldName": "alert_threshold", - "inMetricDimension": true, - "label": "High CPU (80%)", - "meta": { - "esType": "integer", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nROW alert_threshold = 0.8" - }, - "timeField": "@timestamp" - }, - "xy-layer-chart-cpu": { - "columns": [ - { - "columnId": "timestamp", - "fieldName": "timestamp", - "meta": { - "esType": "date", - "type": "date" - } - }, - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } - }, - { - "columnId": "metric", - "customLabel": true, - "fieldName": "metric", - "inMetricDimension": true, - "label": "CPU utilization", - "meta": { - "esType": "double", - "type": "number" - }, - "params": { - "format": { - "id": "percent", - "params": { - "decimals": 1 - } + { + "embeddableConfig": { + "attributes": { + "description": "Average CPU utilization (%) per database over time (averaged per bucket). Reference line at 80% marks the high-CPU threshold. Top 10 databases by CPU per bucket.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-chart-cpu": { + "columns": [ + { + "columnId": "timestamp", + "fieldName": "timestamp", + "meta": { + "esType": "date", + "type": "date" + } + }, + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "metric", + "customLabel": true, + "fieldName": "metric", + "inMetricDimension": true, + "label": "CPU utilization", + "meta": { + "esType": "double", + "type": "number" + }, + "params": { + "format": { + "id": "percent", + "params": { + "decimals": 1 + } + } + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-chart-cpu", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "metric" + ], + "layerId": "xy-layer-chart-cpu", + "layerType": "data", + "seriesType": "line", + "showGridlines": false, + "splitAccessors": [ + "DBInstanceIdentifier" + ], + "xAccessor": "timestamp" + } + ], + "legend": { + "isVisible": true, + "position": "bottom" + }, + "preferredSeriesType": "line", + "valueLabels": "hide" } - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-chart-cpu", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" AND `metrics.amazonaws.com/AWS/RDS/CPUUtilization` IS NOT NULL | WHERE stat == \"Average\" | STATS metric = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/CPUUtilization`)) / 100.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | SORT timestamp ASC, metric DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + }, + "title": "Top 10 RDS databases by CPU utilization", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Average CPU utilization (%) per database over time (averaged per bucket). Top 10 databases by CPU per bucket.", + "title": "Top 10 RDS databases by CPU utilization" }, - "layers": [ - { - "accessors": [ - "metric" - ], - "layerId": "xy-layer-chart-cpu", - "layerType": "data", - "seriesType": "line", - "showGridlines": false, - "splitAccessors": [ - "DBInstanceIdentifier" - ], - "xAccessor": "timestamp" - }, - { - "accessors": [ - "alert_threshold" - ], - "layerId": "ref-cpu-80", - "layerType": "referenceLine", - "yConfig": [ - { - "axisMode": "left", - "color": "#bd271e", - "fill": "none", - "forAccessor": "alert_threshold", - "icon": "alert", - "iconPosition": "right", - "lineStyle": "dashed", - "lineWidth": 2 - } - ] - } - ], - "legend": { - "isVisible": true, - "position": "bottom" + "gridData": { + "h": 12, + "i": "chart-cpu", + "sectionId": "aws-rds-per-database-section", + "w": 16, + "x": 0, + "y": 0 }, - "preferredSeriesType": "line", - "valueLabels": "hide" - } + "panelIndex": "chart-cpu", + "type": "vis" }, - "title": "Top 10 RDS databases by CPU utilization", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Average CPU utilization (%) per database over time (averaged per bucket). Reference line at 80% marks the high-CPU threshold. Top 10 databases by CPU per bucket.", - "title": "Top 10 RDS databases by CPU utilization" - }, - "gridData": { - "h": 12, - "i": "chart-cpu", - "sectionId": "aws-rds-per-database-section", - "w": 16, - "x": 0, - "y": 0 - }, - "panelIndex": "chart-cpu", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Read IOPS per database over time — averaged per bucket. Top 10 databases by read IOPS per bucket.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-chart-iops-read": { - "columns": [ - { - "columnId": "timestamp", - "fieldName": "timestamp", - "meta": { - "esType": "date", - "type": "date" - } - }, - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } + { + "embeddableConfig": { + "attributes": { + "description": "Read IOPS per database over time — averaged per bucket. Top 10 databases by read IOPS per bucket.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-chart-iops-read": { + "columns": [ + { + "columnId": "timestamp", + "fieldName": "timestamp", + "meta": { + "esType": "date", + "type": "date" + } + }, + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "col_dr", + "customLabel": true, + "fieldName": "col_dr", + "inMetricDimension": true, + "label": "Read IOPS", + "meta": { + "esType": "double", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dr = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dr IS NOT NULL | SORT timestamp ASC, col_dr DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-chart-iops-read", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dr = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dr IS NOT NULL | SORT timestamp ASC, col_dr DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "col_dr" + ], + "layerId": "xy-layer-chart-iops-read", + "layerType": "data", + "seriesType": "line", + "showGridlines": false, + "splitAccessors": [ + "DBInstanceIdentifier" + ], + "xAccessor": "timestamp", + "yConfig": null + } + ], + "legend": { + "isVisible": true, + "position": "bottom" + }, + "preferredSeriesType": "line", + "valueLabels": "hide" + } }, - { - "columnId": "col_dr", - "customLabel": true, - "fieldName": "col_dr", - "inMetricDimension": true, - "label": "Read IOPS", - "meta": { - "esType": "double", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dr = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dr IS NOT NULL | SORT timestamp ASC, col_dr DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-chart-iops-read", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dr = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/ReadIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dr IS NOT NULL | SORT timestamp ASC, col_dr DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + "title": "Top 10 RDS databases by read IOPS", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Read IOPS per database over time — averaged per bucket. Top 10 databases by read IOPS per bucket.", + "title": "Top 10 RDS databases by read IOPS" }, - "layers": [ - { - "accessors": [ - "col_dr" - ], - "layerId": "xy-layer-chart-iops-read", - "layerType": "data", - "seriesType": "line", - "showGridlines": false, - "splitAccessors": [ - "DBInstanceIdentifier" - ], - "xAccessor": "timestamp", - "yConfig": null - } - ], - "legend": { - "isVisible": true, - "position": "bottom" + "gridData": { + "h": 12, + "i": "chart-iops-read", + "sectionId": "aws-rds-per-database-section", + "w": 16, + "x": 16, + "y": 0 }, - "preferredSeriesType": "line", - "valueLabels": "hide" - } + "panelIndex": "chart-iops-read", + "type": "vis" }, - "title": "Top 10 RDS databases by read IOPS", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Read IOPS per database over time — averaged per bucket. Top 10 databases by read IOPS per bucket.", - "title": "Top 10 RDS databases by read IOPS" - }, - "gridData": { - "h": 12, - "i": "chart-iops-read", - "sectionId": "aws-rds-per-database-section", - "w": 16, - "x": 16, - "y": 0 - }, - "panelIndex": "chart-iops-read", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Write IOPS per database over time — averaged per bucket. Top 10 databases by write IOPS per bucket.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-chart-iops-write": { - "columns": [ - { - "columnId": "timestamp", - "fieldName": "timestamp", - "meta": { - "esType": "date", - "type": "date" - } - }, - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } + { + "embeddableConfig": { + "attributes": { + "description": "Write IOPS per database over time — averaged per bucket. Top 10 databases by write IOPS per bucket.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-chart-iops-write": { + "columns": [ + { + "columnId": "timestamp", + "fieldName": "timestamp", + "meta": { + "esType": "date", + "type": "date" + } + }, + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "col_dw", + "customLabel": true, + "fieldName": "col_dw", + "inMetricDimension": true, + "label": "Write IOPS", + "meta": { + "esType": "double", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dw = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/WriteIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dw IS NOT NULL | SORT timestamp ASC, col_dw DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-chart-iops-write", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dw = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/WriteIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dw IS NOT NULL | SORT timestamp ASC, col_dw DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "col_dw" + ], + "layerId": "xy-layer-chart-iops-write", + "layerType": "data", + "seriesType": "line", + "showGridlines": false, + "splitAccessors": [ + "DBInstanceIdentifier" + ], + "xAccessor": "timestamp", + "yConfig": null + } + ], + "legend": { + "isVisible": true, + "position": "bottom" + }, + "preferredSeriesType": "line", + "valueLabels": "hide" + } }, - { - "columnId": "col_dw", - "customLabel": true, - "fieldName": "col_dw", - "inMetricDimension": true, - "label": "Write IOPS", - "meta": { - "esType": "double", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dw = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/WriteIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dw IS NOT NULL | SORT timestamp ASC, col_dw DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-chart-iops-write", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/ReadIOPS` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/WriteIOPS` IS NOT NULL) | STATS col_dw = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/WriteIOPS`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_dw IS NOT NULL | SORT timestamp ASC, col_dw DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + "title": "Top 10 RDS databases by write IOPS", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Write IOPS per database over time — averaged per bucket. Top 10 databases by write IOPS per bucket.", + "title": "Top 10 RDS databases by write IOPS" }, - "layers": [ - { - "accessors": [ - "col_dw" - ], - "layerId": "xy-layer-chart-iops-write", - "layerType": "data", - "seriesType": "line", - "showGridlines": false, - "splitAccessors": [ - "DBInstanceIdentifier" - ], - "xAccessor": "timestamp", - "yConfig": null - } - ], - "legend": { - "isVisible": true, - "position": "bottom" + "gridData": { + "h": 12, + "i": "chart-iops-write", + "sectionId": "aws-rds-per-database-section", + "w": 16, + "x": 32, + "y": 0 }, - "preferredSeriesType": "line", - "valueLabels": "hide" - } + "panelIndex": "chart-iops-write", + "type": "vis" }, - "title": "Top 10 RDS databases by write IOPS", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Write IOPS per database over time — averaged per bucket. Top 10 databases by write IOPS per bucket.", - "title": "Top 10 RDS databases by write IOPS" - }, - "gridData": { - "h": 12, - "i": "chart-iops-write", - "sectionId": "aws-rds-per-database-section", - "w": 16, - "x": 32, - "y": 0 - }, - "panelIndex": "chart-iops-write", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Network receive throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by receive throughput per bucket.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-chart-net-rx": { - "columns": [ - { - "columnId": "timestamp", - "fieldName": "timestamp", - "meta": { - "esType": "date", - "type": "date" - } - }, - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } + { + "embeddableConfig": { + "attributes": { + "description": "Network receive throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by receive throughput per bucket.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-chart-net-rx": { + "columns": [ + { + "columnId": "timestamp", + "fieldName": "timestamp", + "meta": { + "esType": "date", + "type": "date" + } + }, + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "col_ni", + "customLabel": true, + "fieldName": "col_ni", + "inMetricDimension": true, + "label": "Rx", + "meta": { + "esType": "double", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_ni = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_ni IS NOT NULL | SORT timestamp ASC, col_ni DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-chart-net-rx", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_ni = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_ni IS NOT NULL | SORT timestamp ASC, col_ni DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "col_ni" + ], + "layerId": "xy-layer-chart-net-rx", + "layerType": "data", + "seriesType": "line", + "showGridlines": false, + "splitAccessors": [ + "DBInstanceIdentifier" + ], + "xAccessor": "timestamp", + "yConfig": null + } + ], + "legend": { + "isVisible": true, + "position": "bottom" + }, + "preferredSeriesType": "line", + "valueLabels": "hide" + } }, - { - "columnId": "col_ni", - "customLabel": true, - "fieldName": "col_ni", - "inMetricDimension": true, - "label": "Rx", - "meta": { - "esType": "double", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_ni = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_ni IS NOT NULL | SORT timestamp ASC, col_ni DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-chart-net-rx", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_ni = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_ni IS NOT NULL | SORT timestamp ASC, col_ni DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + "title": "Top 10 RDS databases by network rx", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Network receive throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by receive throughput per bucket.", + "title": "Top 10 RDS databases by network rx" }, - "layers": [ - { - "accessors": [ - "col_ni" - ], - "layerId": "xy-layer-chart-net-rx", - "layerType": "data", - "seriesType": "line", - "showGridlines": false, - "splitAccessors": [ - "DBInstanceIdentifier" - ], - "xAccessor": "timestamp", - "yConfig": null - } - ], - "legend": { - "isVisible": true, - "position": "bottom" + "gridData": { + "h": 12, + "i": "chart-net-rx", + "sectionId": "aws-rds-per-database-section", + "w": 16, + "x": 0, + "y": 12 }, - "preferredSeriesType": "line", - "valueLabels": "hide" - } + "panelIndex": "chart-net-rx", + "type": "vis" }, - "title": "Top 10 RDS databases by network rx", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Network receive throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by receive throughput per bucket.", - "title": "Top 10 RDS databases by network rx" - }, - "gridData": { - "h": 12, - "i": "chart-net-rx", - "sectionId": "aws-rds-per-database-section", - "w": 16, - "x": 0, - "y": 12 - }, - "panelIndex": "chart-net-rx", - "type": "vis" - }, - { - "embeddableConfig": { - "attributes": { - "description": "Network transmit throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by transmit throughput per bucket.", - "references": [], - "state": { - "adHocDataViews": { - "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { - "allowHidden": false, - "allowNoIndex": true, - "fieldFormats": {}, - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "managed": false, - "name": "metrics-aws.rds.otel-*", - "runtimeFieldMap": {}, - "sourceFilters": [], - "timeFieldName": "@timestamp", - "title": "metrics-aws.rds.otel-*", - "type": "esql" - } - }, - "datasourceStates": { - "textBased": { - "layers": { - "xy-layer-chart-net-tx": { - "columns": [ - { - "columnId": "timestamp", - "fieldName": "timestamp", - "meta": { - "esType": "date", - "type": "date" - } + { + "embeddableConfig": { + "attributes": { + "description": "Network transmit throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by transmit throughput per bucket.", + "references": [], + "state": { + "adHocDataViews": { + "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf": { + "allowHidden": false, + "allowNoIndex": true, + "fieldFormats": {}, + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "managed": false, + "name": "metrics-aws.rds.otel-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "metrics-aws.rds.otel-*", + "type": "esql" + } + }, + "datasourceStates": { + "textBased": { + "layers": { + "xy-layer-chart-net-tx": { + "columns": [ + { + "columnId": "timestamp", + "fieldName": "timestamp", + "meta": { + "esType": "date", + "type": "date" + } + }, + { + "columnId": "DBInstanceIdentifier", + "fieldName": "DBInstanceIdentifier", + "meta": { + "type": "string" + } + }, + { + "columnId": "col_no", + "customLabel": true, + "fieldName": "col_no", + "inMetricDimension": true, + "label": "Tx", + "meta": { + "esType": "double", + "type": "number" + } + } + ], + "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_no = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_no IS NOT NULL | SORT timestamp ASC, col_no DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "timeField": "@timestamp" + } + } + } + }, + "filters": [], + "internalReferences": [ + { + "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", + "name": "indexpattern-datasource-layer-xy-layer-chart-net-tx", + "type": "index-pattern" + } + ], + "query": { + "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_no = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_no IS NOT NULL | SORT timestamp ASC, col_no DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": false, + "yLeft": false, + "yRight": false + }, + "layers": [ + { + "accessors": [ + "col_no" + ], + "layerId": "xy-layer-chart-net-tx", + "layerType": "data", + "seriesType": "line", + "showGridlines": false, + "splitAccessors": [ + "DBInstanceIdentifier" + ], + "xAccessor": "timestamp", + "yConfig": null + } + ], + "legend": { + "isVisible": true, + "position": "bottom" + }, + "preferredSeriesType": "line", + "valueLabels": "hide" + } }, - { - "columnId": "DBInstanceIdentifier", - "fieldName": "DBInstanceIdentifier", - "meta": { - "type": "string" - } + "title": "Top 10 RDS databases by network tx", + "version": 2, + "visualizationType": "lnsXY" + }, + "description": "Network transmit throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by transmit throughput per bucket.", + "title": "Top 10 RDS databases by network tx" + }, + "gridData": { + "h": 12, + "i": "chart-net-tx", + "sectionId": "aws-rds-per-database-section", + "w": 16, + "x": 16, + "y": 12 + }, + "panelIndex": "chart-net-tx", + "type": "vis" + } + ], + "pinned_panels": { + "panels": { + "ctrl-rds-account": { + "config": { + "dataViewRefName": "ctrl-rds-account:optionsListDataView", + "exclude": false, + "exists_selected": false, + "field_name": "cloud.account.id", + "ignore_validations": false, + "run_past_timeout": false, + "search_technique": "wildcard", + "selected_options": [], + "single_select": false, + "sort": { + "by": "_count", + "direction": "desc" }, - { - "columnId": "col_no", - "customLabel": true, - "fieldName": "col_no", - "inMetricDimension": true, - "label": "Tx", - "meta": { - "esType": "double", - "type": "number" - } - } - ], - "index": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_no = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_no IS NOT NULL | SORT timestamp ASC, col_no DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "timeField": "@timestamp" - } - } - } - }, - "filters": [], - "internalReferences": [ - { - "id": "ccad7b1133a69c9f7e6e7e01f7a7937f158273890dea0030f085bad62093bfcf", - "name": "indexpattern-datasource-layer-xy-layer-chart-net-tx", - "type": "index-pattern" - } - ], - "query": { - "esql": "SET unmapped_fields = \"nullify\";\nTS metrics-aws.rds.otel-* | WHERE DBInstanceIdentifier IS NOT NULL AND DBInstanceIdentifier != \"\" | WHERE stat == \"Average\" AND (`metrics.amazonaws.com/AWS/RDS/NetworkReceiveThroughput` IS NOT NULL OR `metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput` IS NOT NULL) | STATS col_no = AVG(avg_over_time(`metrics.amazonaws.com/AWS/RDS/NetworkTransmitThroughput`)) / 1048576.0 BY timestamp = TBUCKET(50, ?_tstart, ?_tend), DBInstanceIdentifier, cloud.region | WHERE col_no IS NOT NULL | SORT timestamp ASC, col_no DESC, DBInstanceIdentifier ASC | LIMIT 10 BY timestamp" - }, - "visualization": { - "axisTitlesVisibilitySettings": { - "x": false, - "yLeft": false, - "yRight": false + "title": "Account", + "use_global_filters": true, + "values_source": "field" + }, + "grow": true, + "order": 0, + "type": "options_list_control", + "width": "medium" }, - "layers": [ - { - "accessors": [ - "col_no" - ], - "layerId": "xy-layer-chart-net-tx", - "layerType": "data", - "seriesType": "line", - "showGridlines": false, - "splitAccessors": [ - "DBInstanceIdentifier" - ], - "xAccessor": "timestamp", - "yConfig": null - } - ], - "legend": { - "isVisible": true, - "position": "bottom" + "ctrl-rds-db-instance-id": { + "config": { + "dataViewRefName": "ctrl-rds-db-instance-id:optionsListDataView", + "exclude": false, + "exists_selected": false, + "field_name": "DBInstanceIdentifier", + "ignore_validations": false, + "run_past_timeout": false, + "search_technique": "wildcard", + "selected_options": [], + "single_select": false, + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "DB instance", + "use_global_filters": true, + "values_source": "field" + }, + "grow": true, + "order": 2, + "type": "options_list_control", + "width": "medium" }, - "preferredSeriesType": "line", - "valueLabels": "hide" - } - }, - "title": "Top 10 RDS databases by network tx", - "version": 2, - "visualizationType": "lnsXY" - }, - "description": "Network transmit throughput per database over time (MiB/s, averaged per bucket). Top 10 databases by transmit throughput per bucket.", - "title": "Top 10 RDS databases by network tx" - }, - "gridData": { - "h": 12, - "i": "chart-net-tx", - "sectionId": "aws-rds-per-database-section", - "w": 16, - "x": 16, - "y": 12 - }, - "panelIndex": "chart-net-tx", - "type": "vis" - } - ], - "pinned_panels": { - "panels": { - "ctrl-rds-account": { - "config": { - "dataViewRefName": "ctrl-rds-account:optionsListDataView", - "exclude": false, - "exists_selected": false, - "field_name": "cloud.account.id", - "ignore_validations": false, - "run_past_timeout": false, - "search_technique": "wildcard", - "selected_options": [], - "single_select": false, - "sort": { - "by": "_count", - "direction": "desc" - }, - "title": "Account", - "use_global_filters": true, - "values_source": "field" - }, - "grow": true, - "order": 0, - "type": "options_list_control", - "width": "medium" + "ctrl-rds-region": { + "config": { + "dataViewRefName": "ctrl-rds-region:optionsListDataView", + "exclude": false, + "exists_selected": false, + "field_name": "cloud.region", + "ignore_validations": false, + "run_past_timeout": false, + "search_technique": "wildcard", + "selected_options": [], + "single_select": false, + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "Region", + "use_global_filters": true, + "values_source": "field" + }, + "grow": true, + "order": 1, + "type": "options_list_control", + "width": "medium" + } + } }, - "ctrl-rds-db-instance-id": { - "config": { - "dataViewRefName": "ctrl-rds-db-instance-id:optionsListDataView", - "exclude": false, - "exists_selected": false, - "field_name": "DBInstanceIdentifier", - "ignore_validations": false, - "run_past_timeout": false, - "search_technique": "wildcard", - "selected_options": [], - "single_select": false, - "sort": { - "by": "_count", - "direction": "desc" + "sections": [ + { + "collapsed": false, + "gridData": { + "i": "aws-rds-overview-section", + "y": 2 + }, + "title": "Overview (Current status)" }, - "title": "DB instance", - "use_global_filters": true, - "values_source": "field" - }, - "grow": true, - "order": 2, - "type": "options_list_control", - "width": "medium" - }, - "ctrl-rds-region": { - "config": { - "dataViewRefName": "ctrl-rds-region:optionsListDataView", - "exclude": false, - "exists_selected": false, - "field_name": "cloud.region", - "ignore_validations": false, - "run_past_timeout": false, - "search_technique": "wildcard", - "selected_options": [], - "single_select": false, - "sort": { - "by": "_count", - "direction": "desc" + { + "collapsed": false, + "gridData": { + "i": "aws-rds-list-section", + "y": 3 + }, + "title": "List of RDS databases in the selected time range" }, - "title": "Region", - "use_global_filters": true, - "values_source": "field" - }, - "grow": true, - "order": 1, - "type": "options_list_control", - "width": "medium" - } - } + { + "collapsed": false, + "gridData": { + "i": "aws-rds-per-database-section", + "y": 4 + }, + "title": "Per database metrics" + } + ], + "timeFrom": "now-1h/h", + "timeRestore": true, + "timeTo": "now", + "title": "[AWS RDS OTel] Overview" }, - "sections": [ - { - "collapsed": false, - "gridData": { - "i": "aws-rds-overview-section", - "y": 2 + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-10T10:08:14.193Z", + "id": "aws_rds_otel-c92e1216-83f6-4de7-9d7f-1bcb42d5988a", + "references": [ + { + "id": "aws_rds_otel-36df60a8-6a6e-4f72-96ce-a3533d24901a", + "name": "tbl-instances:dashboard_drilldown_aws_rds_otel-36df60a8-6a6e-4f72-96ce-a3533d24901a", + "type": "dashboard" }, - "title": "Overview (Current status)" - }, - { - "collapsed": false, - "gridData": { - "i": "aws-rds-list-section", - "y": 3 + { + "id": "metrics-*", + "name": "ctrl-rds-account:optionsListDataView", + "type": "index-pattern" }, - "title": "List of RDS databases in the selected time range" - }, - { - "collapsed": false, - "gridData": { - "i": "aws-rds-per-database-section", - "y": 4 + { + "id": "metrics-*", + "name": "ctrl-rds-region:optionsListDataView", + "type": "index-pattern" }, - "title": "Per database metrics" - } + { + "id": "metrics-*", + "name": "ctrl-rds-db-instance-id:optionsListDataView", + "type": "index-pattern" + } ], - "timeRestore": false, - "title": "[AWS RDS OTel] Metrics" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-30T08:50:52.757Z", - "created_by": "u_LQY3UOHdVkYrbjy8PgOCQKR-fROZ1M0Vh7DvpOH6S40_0", - "id": "aws_rds_otel-c92e1216-83f6-4de7-9d7f-1bcb42d5988a", - "references": [ - { - "id": "metrics-*", - "name": "ctrl-rds-account:optionsListDataView", - "type": "index-pattern" - }, - { - "id": "metrics-*", - "name": "ctrl-rds-region:optionsListDataView", - "type": "index-pattern" - }, - { - "id": "metrics-*", - "name": "ctrl-rds-db-instance-id:optionsListDataView", - "type": "index-pattern" - } - ], - "type": "dashboard", - "typeMigrationVersion": "10.3.0", - "updated_by": "u_LQY3UOHdVkYrbjy8PgOCQKR-fROZ1M0Vh7DvpOH6S40_0" -} + "type": "dashboard", + "typeMigrationVersion": "10.3.0" +} \ No newline at end of file diff --git a/packages/aws_rds_otel/manifest.yml b/packages/aws_rds_otel/manifest.yml index ced15063131..f0d8e1a8b9a 100644 --- a/packages/aws_rds_otel/manifest.yml +++ b/packages/aws_rds_otel/manifest.yml @@ -1,7 +1,7 @@ format_version: 3.6.0 name: aws_rds_otel title: "AWS RDS Metrics OpenTelemetry Assets" -version: 0.9.0 +version: 0.10.0 source: license: "Elastic-2.0" description: "AWS RDS Metrics OpenTelemetry Assets" @@ -22,9 +22,13 @@ discovery: datasets: - name: aws.rds.otel screenshots: - - src: /img/dashboard.png - title: Dashboard screenshot - size: 600x600 + - src: /img/aws_rds_overview_dashboard.png + title: AWS RDS Metrics OpenTelemetry Overview Dashboard + size: 3524x5306 + type: image/png + - src: /img/aws_rds_detail_dashboard.png + title: AWS RDS Metrics OpenTelemetry Drilldown Dashboard + size: 3524x4506 type: image/png icons: - src: /img/logo.svg diff --git a/packages/azure_frontdoor/_dev/build/docs/README.md b/packages/azure_frontdoor/_dev/build/docs/README.md index 8fb57e8ac9f..3498714e9d1 100644 --- a/packages/azure_frontdoor/_dev/build/docs/README.md +++ b/packages/azure_frontdoor/_dev/build/docs/README.md @@ -11,15 +11,17 @@ The Azure Frontdoor logs integration retrieves the following types of log data f - **Access Logs**: Logs categorized as `FrontDoorAccessLog`. - **Web Application Firewall (WAF) Logs**: Logs categorized as `FrontDoorWebApplicationFirewallLog`. +- **Health Probe Logs**: Logs categorized as `FrontDoorHealthProbeLog`. -Currently, the integration does not support **Activity Logs** or **Health Probe logs**. +Currently, the integration does not support **Activity Logs**. ## Data streams -This integration collects two types of data streams: +This integration collects three types of data streams: - access log - waf logs +- health probe logs ## Requirements @@ -141,3 +143,7 @@ Users can also use this in case of a Hybrid Cloud model, where one may define th ## WAF Logs {{fields "waf"}} + +## Health Probe Logs + +{{fields "health_probe"}} \ No newline at end of file diff --git a/packages/azure_frontdoor/changelog.yml b/packages/azure_frontdoor/changelog.yml index 2b6841c3bbf..226ddfd3320 100644 --- a/packages/azure_frontdoor/changelog.yml +++ b/packages/azure_frontdoor/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "2.4.0" + changes: + - description: Add Health Probe dataset + type: enhancement + link: https://github.com/elastic/integrations/pull/20016 - version: "2.3.0" changes: - description: Add client secret authentication support for Azure Event Hub with RBAC. diff --git a/packages/azure_frontdoor/docs/README.md b/packages/azure_frontdoor/docs/README.md index 756bdfde5a8..430836efd58 100644 --- a/packages/azure_frontdoor/docs/README.md +++ b/packages/azure_frontdoor/docs/README.md @@ -11,15 +11,17 @@ The Azure Frontdoor logs integration retrieves the following types of log data f - **Access Logs**: Logs categorized as `FrontDoorAccessLog`. - **Web Application Firewall (WAF) Logs**: Logs categorized as `FrontDoorWebApplicationFirewallLog`. +- **Health Probe Logs**: Logs categorized as `FrontDoorHealthProbeLog`. -Currently, the integration does not support **Activity Logs** or **Health Probe logs**. +Currently, the integration does not support **Activity Logs**. ## Data streams -This integration collects two types of data streams: +This integration collects three types of data streams: - access log - waf logs +- health probe logs ## Requirements @@ -220,3 +222,30 @@ Users can also use this in case of a Hybrid Cloud model, where one may define th | input.type | Input type. | keyword | | log.offset | Log offset. | long | + +## Health Probe Logs + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Event timestamp. | date | +| azure.frontdoor.category | Azure Frontdoor category name. | keyword | +| azure.frontdoor.health_probe.connection_latency_milliseconds | TCP connection latency of the health probe in milliseconds. | long | +| azure.frontdoor.health_probe.dns_latency_microseconds | DNS resolution latency of the health probe in microseconds. | long | +| azure.frontdoor.health_probe.health_probe_id | Unique identifier for the health probe request. | keyword | +| azure.frontdoor.health_probe.origin_name | The hostname of the origin that was probed. | keyword | +| azure.frontdoor.health_probe.pop | The edge PoP (Point of Presence) that issued the health probe. | keyword | +| azure.frontdoor.health_probe.result | Result of the health probe (examples: OriginError, Success). | keyword | +| azure.frontdoor.health_probe.total_latency_milliseconds | Total latency of the health probe in milliseconds. | long | +| azure.frontdoor.operation_name | Azure operation name. | keyword | +| azure.frontdoor.resource_id | Azure Resource ID. | keyword | +| cloud.image.id | Image ID for the cloud instance. | keyword | +| data_stream.dataset | Data stream dataset. | constant_keyword | +| data_stream.namespace | Data stream namespace. | constant_keyword | +| data_stream.type | Data stream type. | constant_keyword | +| host.containerized | If the host is a container. | boolean | +| host.os.build | OS build information. | keyword | +| host.os.codename | OS codename, if any. | keyword | +| input.type | Input type. | keyword | +| log.offset | Log offset. | long | diff --git a/packages/azure_frontdoor/manifest.yml b/packages/azure_frontdoor/manifest.yml index 5e36842e958..e914e9cbffd 100644 --- a/packages/azure_frontdoor/manifest.yml +++ b/packages/azure_frontdoor/manifest.yml @@ -1,7 +1,7 @@ format_version: "3.0.2" name: azure_frontdoor title: "Azure Frontdoor" -version: "2.3.0" +version: "2.4.0" description: "This Elastic integration collects logs from Azure Frontdoor." type: integration categories: diff --git a/packages/checkpoint/changelog.yml b/packages/checkpoint/changelog.yml index 3409fc9584d..15325d26f2c 100644 --- a/packages/checkpoint/changelog.yml +++ b/packages/checkpoint/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "1.48.0" + changes: + - description: Improve handling of different user formats in logs. + type: enhancement + link: https://github.com/elastic/integrations/pull/20183 - version: "1.47.0" changes: - description: Populate observer.ip with the Check Point gateway IP from the origin field, and add observer.hostname from the CN of originsicname, in the firewall data stream. diff --git a/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log b/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log index 62ed659396e..f6103ba2845 100644 --- a/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log +++ b/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log @@ -36,3 +36,14 @@ <134>1 2020-03-30T07:20:35Z gw-da58d3 CheckPoint 8363 - [action:"Reject"; flags:"44676"; ifdir:"inbound"; ifname:"daemon"; loguid:"{0x5e8148f5,0x0,0x6401a8c0,0x108620ab}"; origin:"192.168.0.1"; originsicname:"CN=cp_mgmt,O=gw-da58d3..tmn8s8"; sequencenum:"22"; time:"1746521905"; version:"5"; dst:"0.0.0.0"; encryption_failure::"no response from peer."; fw_subproduct:"VPN-1"; peer_gateway:"192.168.10.1"; proto:"0"; reject_category:"IKE failure"; rule:"0"; s_port:"0"; scheme::"IKE"; service:"0"; src:"0.0.0.0"; vpn_feature_name:"IKE"] <134>1 2020-03-30T07:20:35Z gw-da58d3 CheckPoint 8363 - [action:"Detect"; flags:"44676"; ifdir:"inbound"; ifname:"eth0"; loguid:"{0x5e8148f5,0x0,0x6401a8c0,0x108620ab}"; origin:"192.168.0.1"; originsicname:"CN=cp_mgmt,O=gw-da58d3..tmn8s8"; sequencenum:"22"; time:"1746491278"; version:"5"; __policy_id_tag:"product=VPN-1 & FireWall-1[db_tag={880771B0-FD92-2C4F-82FC-B96FC3DE5A07};mgmt=gw-da58d3;date=1746456871;policy_name=Standard\]"; attack:"Port Scan"; attack_info:"Host Port Scan"; confidence_level:"5"; dst:"192.168.10.1"; performance_impact:"2"; product:"SmartDefense"; protection_id:"HostPortScan"; protection_name:"Host Port Scan"; protection_type:"anomaly"; proto:"4294967295"; s_port:"0"; service:"4294967295"; severity:"1"; smartdefense_profile:"Standard"; source:"Distinct"; src:"192.168.12.1"] <134>1 2020-03-30T07:20:35Z gw-da58d3 CheckPoint 8363 - [action:"Accept"; flags:"444676"; ifdir:"outbound"; ifname:"eth0"; logid:"0"; loguid:"{0x5e819dc3,0x0,0x353707c7,0xee78a1dc}"; origin:"192.168.1.100"; originsicname:"cn=cp_mgmt,o=gw-da58d3..tmn8s8"; sequencenum:"1"; time:"1759720844"; version:"5"; arrival_time:"1759720844"; attachments_num:"1"; delivery_time:"1759720852"; dst:"192.168.1.100"; email_content:"Attachments"; email_headers:"X-IronPort-AV: E=Sophos;i=\"4.20,319,1751234400\"; d=\"png'150?scan'150,208,217,150\";a=\"13313487\" X-IronPort-AV: E=McAfee;i=\"6800,10657,11573\"; a=\"290145815\" "; email_queue_id:"abcdefghijklm"; email_queue_name:"N/A"; lastupdatetime:"1759720852"; links_num:"0"; original_queue_id:"lmnopqrstuvw"; product:"MTA"; s_port:"12345"; scan_ended:"1759720844"; scan_started:"1759720844"; service:"25"; src:"192.168.2.100"; status_update:"1759720852"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; user:" Test User (test_user@test.local) "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; user:" test_user@test.local "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; src_user_name:" Test User (test_user@test.local) "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; src_user_name:" test_user@test.local "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; src_user_name:" Test User "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; dst_user_name:" Test User (test_user@test.local) "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; dst_user_name:" test_user@test.local "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; dst_user_name:" Test User "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; administrator:" Test User (test_user@test.local) "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; administrator:" test_user@test.local "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] +<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:"Log In"; flags:"18688"; ifdir:"inbound"; loguid:"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}"; origin:"192.168.1.102"; originsicname:"CN=TESTWA022B001,O=TESTWM002001..t2z5yx"; sequencenum:"270"; time:"1739872901"; version:"5"; auth_method:"Password"; auth_method2:"DynamicID"; client_build:"986102607"; client_name:"Test Client"; client_version:"E123.123"; cvpn_category:"Session"; device_identification:"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}"; domain_name:"EXAMPLE.LOCAL"; event_type:"Login"; failed_login_factor_num:"0"; host_ip:"10.1.1.1"; host_type:"PC"; hostname:"TEST_HOSTNAME"; lastupdatetime:"1739872901"; login_option:"two-way"; login_timestamp:"1739872901"; mac_address:"ab:cd:ef:01:23:45"; more:"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)"; office_mode_ip:"192.168.1.1"; os_bits:"64bit"; os_build:"19045"; os_edition:"Enterprise"; os_name:"Windows"; os_version:"10"; product:"Test Product"; proto:"6"; proxy_src_ip:"0.0.0.0"; s_port:"0"; service:"443"; session_timeout:"43174"; session_uid:"{31A46FFD-A526-4318-BA17-49CBCDC38A14}"; src:"192.168.211.208"; status:"Success"; suppressed_logs:"0"; tunnel_protocol:"IPSec"; administrator:" Test User "; user_dn:"CN=Test User,OU=Users,DC=test,DC=local"; user_group:"Users"] diff --git a/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log-expected.json b/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log-expected.json index cefd75aa19e..d6a567e6b17 100644 --- a/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log-expected.json +++ b/packages/checkpoint/data_stream/firewall/_dev/test/pipeline/test-checkpoint.log-expected.json @@ -2736,6 +2736,1278 @@ "tags": [ "preserve_original_event" ] + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user": "Test User (test_user@test.local)", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; user:\" Test User (test_user@test.local) \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "Test User", + "test_user@test.local" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0 + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "full_name": "Test User", + "name": "test_user" + } + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user": "test_user@test.local", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; user:\" test_user@test.local \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "test_user@test.local" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0 + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "name": "test_user" + } + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "src_user_name": "Test User (test_user@test.local)", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; src_user_name:\" Test User (test_user@test.local) \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "Test User", + "test_user@test.local" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0, + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "full_name": "Test User", + "name": "test_user" + } + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "full_name": "Test User", + "name": "test_user" + } + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "src_user_name": "test_user@test.local", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; src_user_name:\" test_user@test.local \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "test_user@test.local" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0, + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "name": "test_user" + } + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "name": "test_user" + } + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "src_user_name": "Test User", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; src_user_name:\" Test User \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test user" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0, + "user": { + "name": "test user" + } + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "name": "test user" + } + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "dst_user_name": "Test User (test_user@test.local)", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443, + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "full_name": "Test User", + "name": "test_user" + } + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "email": { + "from": { + "address": [ + "test_user@test.local" + ] + }, + "to": { + "address": [ + "test_user@test.local" + ] + } + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; dst_user_name:\" Test User (test_user@test.local) \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "test_user@test.local", + "Test User" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0 + }, + "tags": [ + "preserve_original_event" + ] + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "dst_user_name": "test_user@test.local", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443, + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "name": "test_user" + } + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "email": { + "from": { + "address": [ + "test_user@test.local" + ] + }, + "to": { + "address": [ + "test_user@test.local" + ] + } + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; dst_user_name:\" test_user@test.local \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "test_user@test.local" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0 + }, + "tags": [ + "preserve_original_event" + ] + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "dst_user_name": "Test User", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443, + "user": { + "name": "test user" + } + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; dst_user_name:\" Test User \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test user" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0 + }, + "tags": [ + "preserve_original_event" + ] + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "administrator": "Test User (test_user@test.local)", + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; administrator:\" Test User (test_user@test.local) \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "Test User", + "test_user@test.local" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0, + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "full_name": "Test User", + "name": "test_user" + } + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "full_name": "Test User", + "name": "test_user" + } + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "administrator": "test_user@test.local", + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; administrator:\" test_user@test.local \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test_user", + "test_user@test.local" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0, + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "name": "test_user" + } + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "domain": "test.local", + "email": "test_user@test.local", + "name": "test_user" + } + }, + { + "@timestamp": "2025-02-18T10:01:41.000Z", + "checkpoint": { + "administrator": "Test User", + "auth_method": "Password", + "auth_method2": "DynamicID", + "client_build": "986102607", + "client_name": "Test Client", + "client_version": "E123.123", + "cvpn_category": "Session", + "device_identification": "{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}", + "event_type": "Login", + "failed_login_factor_num": 0, + "host_ip": "10.1.1.1", + "host_type": "PC", + "hostname": "TEST_HOSTNAME", + "login_option": "two-way", + "login_timestamp": "2025-02-18T10:01:41.000Z", + "more": "authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)", + "office_mode_ip": "192.168.1.1", + "origin_sic_name": "CN=TESTWA022B001,O=TESTWM002001..t2z5yx", + "os_bits": "64bit", + "os_build": "19045", + "os_edition": "Enterprise", + "proxy_src_ip": "0.0.0.0", + "session_timeout": 43174, + "session_uid": "{31A46FFD-A526-4318-BA17-49CBCDC38A14}", + "status": "Success", + "suppressed_logs": "0", + "tunnel_protocol": "IPSec", + "user_dn": "CN=Test User,OU=Users,DC=test,DC=local" + }, + "destination": { + "port": 443 + }, + "dns": { + "question": { + "name": "EXAMPLE.LOCAL" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "action": "logged-in", + "category": [ + "authentication" + ], + "end": "2025-02-18T10:01:41.000Z", + "id": "{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}", + "kind": "event", + "original": "<134>1 2025-02-18T10:01:41Z TEST_HOSTNAME CheckPoint 10038 - [action:\"Log In\"; flags:\"18688\"; ifdir:\"inbound\"; loguid:\"{0xae027eed,0xef89f5a0,0x5b806530,0x8b665bef}\"; origin:\"192.168.1.102\"; originsicname:\"CN=TESTWA022B001,O=TESTWM002001..t2z5yx\"; sequencenum:\"270\"; time:\"1739872901\"; version:\"5\"; auth_method:\"Password\"; auth_method2:\"DynamicID\"; client_build:\"986102607\"; client_name:\"Test Client\"; client_version:\"E123.123\"; cvpn_category:\"Session\"; device_identification:\"{313A7B1F-5FB8-4608-B0F8-05A2311B6FFF}\"; domain_name:\"EXAMPLE.LOCAL\"; event_type:\"Login\"; failed_login_factor_num:\"0\"; host_ip:\"10.1.1.1\"; host_type:\"PC\"; hostname:\"TEST_HOSTNAME\"; lastupdatetime:\"1739872901\"; login_option:\"two-way\"; login_timestamp:\"1739872901\"; mac_address:\"ab:cd:ef:01:23:45\"; more:\"authenticated_machine= (CN=TESTHOST1,OU=Test 2.0,OU=Testcomputers,DC=TEST,DC=LOCAL)\"; office_mode_ip:\"192.168.1.1\"; os_bits:\"64bit\"; os_build:\"19045\"; os_edition:\"Enterprise\"; os_name:\"Windows\"; os_version:\"10\"; product:\"Test Product\"; proto:\"6\"; proxy_src_ip:\"0.0.0.0\"; s_port:\"0\"; service:\"443\"; session_timeout:\"43174\"; session_uid:\"{31A46FFD-A526-4318-BA17-49CBCDC38A14}\"; src:\"192.168.211.208\"; status:\"Success\"; suppressed_logs:\"0\"; tunnel_protocol:\"IPSec\"; administrator:\" Test User \"; user_dn:\"CN=Test User,OU=Users,DC=test,DC=local\"; user_group:\"Users\"]", + "outcome": "success", + "sequence": 270, + "timezone": "UTC", + "type": [ + "start" + ] + }, + "group": { + "name": "Users" + }, + "host": { + "hostname": "TEST_HOSTNAME", + "ip": "10.1.1.1", + "os": { + "name": "Windows", + "version": "10" + } + }, + "network": { + "direction": "inbound", + "iana_number": "6", + "transport": "tcp" + }, + "observer": { + "hostname": "TESTWA022B001", + "ip": [ + "192.168.1.102" + ], + "mac": [ + "AB-CD-EF-01-23-45" + ], + "name": "192.168.1.102", + "product": "Test Product", + "type": "firewall", + "vendor": "Checkpoint" + }, + "related": { + "ip": [ + "192.168.211.208", + "192.168.1.102" + ], + "user": [ + "test user" + ] + }, + "source": { + "ip": "192.168.211.208", + "port": 0, + "user": { + "name": "test user" + } + }, + "tags": [ + "preserve_original_event" + ], + "user": { + "name": "test user" + } } ] } diff --git a/packages/checkpoint/data_stream/firewall/elasticsearch/ingest_pipeline/default.yml b/packages/checkpoint/data_stream/firewall/elasticsearch/ingest_pipeline/default.yml index 68e0d83d8e3..a20b52bd309 100644 --- a/packages/checkpoint/data_stream/firewall/elasticsearch/ingest_pipeline/default.yml +++ b/packages/checkpoint/data_stream/firewall/elasticsearch/ingest_pipeline/default.yml @@ -255,23 +255,30 @@ processors: field: checkpoint.uid target_field: source.user.id ignore_missing: true - - set: - tag: set_source_user_name_276eacf0 - field: source.user.name - copy_from: checkpoint.src_user_name - ignore_empty_value: true - - set: - tag: set_source_user_name_d2cd1e3b - field: source.user.name - copy_from: checkpoint.administrator - if: ctx.source?.user?.name == null - ignore_empty_value: true - - set: - tag: set_user_name_9961f466 - field: user.name - copy_from: checkpoint.user - if: ctx.user?.name == null - ignore_empty_value: true + - grok: + tag: grok_src_user_name + field: checkpoint.src_user_name + if: ctx.checkpoint?.src_user_name != null + patterns: + - "^%{DATA:source.user.full_name} \\(%{EMAILADDRESS:source.user.email}\\)$" + - "^%{EMAILADDRESS:source.user.email}$" + - "^%{DATA:source.user.name}$" + - grok: + tag: grok_administrator + field: checkpoint.administrator + if: ctx.checkpoint?.administrator != null && ctx.source?.user?.name == null && ctx.source?.user?.email == null + patterns: + - "^%{DATA:source.user.full_name} \\(%{EMAILADDRESS:source.user.email}\\)$" + - "^%{EMAILADDRESS:source.user.email}$" + - "^%{DATA:source.user.name}$" + - grok: + tag: grok_user + field: checkpoint.user + if: ctx.checkpoint?.user != null && ctx.user?.name == null + patterns: + - "^%{DATA:user.full_name} \\(%{EMAILADDRESS:user.email}\\)$" + - "^%{EMAILADDRESS:user.email}$" + - "^%{DATA:user.name}$" - convert: tag: convert_checkpoint_failed_login_factor_num_919842ca field: checkpoint.failed_login_factor_num @@ -374,11 +381,14 @@ processors: target_field: destination.domain if: ctx.server?.domain == null ignore_missing: true - - set: - tag: set_destination_user_name_ccf3ca27 - field: destination.user.name - copy_from: checkpoint.dst_user_name + - grok: + tag: grok_dst_user_name + field: checkpoint.dst_user_name if: ctx.checkpoint?.dst_user_name != null + patterns: + - "^%{DATA:destination.user.full_name} \\(%{EMAILADDRESS:destination.user.email}\\)$" + - "^%{EMAILADDRESS:destination.user.email}$" + - "^%{DATA:destination.user.name}$" - set: tag: set_destination_user_domain_d38bee06 field: destination.user.domain @@ -794,6 +804,12 @@ processors: value: '{{{ source.user.name }}}' override: false ignore_empty_value: true + - set: + tag: set_user_full_name_4f1523ba + field: user.full_name + value: '{{{ source.user.full_name }}}' + override: false + ignore_empty_value: true - set: tag: set_user_id_cc07e8aa field: user.id @@ -1498,11 +1514,6 @@ processors: replacement: "" if: ctx.checkpoint?.sys_message != null # Standardize user fields - - rename: - target_field: user.email - field: user.name - tag: rename_user_email - if: ctx.user?.email == null && ctx.user?.name != null && ctx.user.name.indexOf("@") > 0 - dissect: field: user.email pattern: '%{user.name}@%{user.domain}' @@ -1522,17 +1533,18 @@ processors: value: "{{{user.name}}}" allow_duplicates: false if: ctx.user?.name != null + - append: + tag: append_related_user_7021abb5 + field: related.user + value: "{{{user.full_name}}}" + allow_duplicates: false + if: ctx.user?.full_name != null - append: tag: append_related_user_34fcf415 field: related.user value: "{{{user.email}}}" allow_duplicates: false if: ctx.user?.email != null - - rename: - target_field: source.user.email - field: source.user.name - tag: rename_source_user_email - if: ctx.source?.user?.email == null && ctx.source?.user?.name != null && ctx.source.user.name.indexOf("@") > 0 - dissect: field: source.user.email pattern: '%{source.user.name}@%{source.user.domain}' @@ -1558,11 +1570,12 @@ processors: value: "{{{source.user.email}}}" allow_duplicates: false if: ctx.source?.user?.email != null - - rename: - target_field: destination.user.email - field: destination.user.name - tag: rename_destination_user_email - if: ctx.destination?.user?.email == null && ctx.destination?.user?.name != null && ctx.destination.user.name.indexOf("@") > 0 + - append: + tag: append_related_user_18471188 + field: related.user + value: "{{{source.user.full_name}}}" + allow_duplicates: false + if: ctx.source?.user?.full_name != null - dissect: field: destination.user.email pattern: '%{destination.user.name}@%{destination.user.domain}' @@ -1588,6 +1601,12 @@ processors: value: "{{{destination.user.email}}}" allow_duplicates: false if: ctx.destination?.user?.email != null + - append: + tag: append_related_user_7ec630c0 + field: related.user + value: "{{{destination.user.full_name}}}" + allow_duplicates: false + if: ctx.destination?.user?.full_name != null - script: tag: script_422800ed diff --git a/packages/checkpoint/data_stream/firewall/fields/ecs.yml b/packages/checkpoint/data_stream/firewall/fields/ecs.yml index e181d623366..584a7980b87 100644 --- a/packages/checkpoint/data_stream/firewall/fields/ecs.yml +++ b/packages/checkpoint/data_stream/firewall/fields/ecs.yml @@ -40,6 +40,8 @@ name: destination.user.email - external: ecs name: destination.user.id +- external: ecs + name: destination.user.full_name - external: ecs name: destination.user.name - external: ecs @@ -236,6 +238,8 @@ name: source.user.group.name - external: ecs name: source.user.id +- external: ecs + name: source.user.full_name - external: ecs name: source.user.name - external: ecs @@ -252,6 +256,8 @@ name: vulnerability.id - external: ecs name: log.file.path +- external: ecs + name: user.full_name - external: ecs name: user.name - external: ecs diff --git a/packages/checkpoint/docs/README.md b/packages/checkpoint/docs/README.md index a537ca79c27..e4d6c84d72b 100644 --- a/packages/checkpoint/docs/README.md +++ b/packages/checkpoint/docs/README.md @@ -732,6 +732,8 @@ The raw `originsicname` value is preserved in `checkpoint.origin_sic_name`. Beca | destination.service.name | Name of the service data is collected from. | keyword | | destination.user.domain | Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name. | keyword | | destination.user.email | User email address. | keyword | +| destination.user.full_name | User's full name, if available. | keyword | +| destination.user.full_name.text | Multi-field of `destination.user.full_name`. | match_only_text | | destination.user.id | Unique identifier of the user. | keyword | | destination.user.name | Short name or login of the user. | keyword | | destination.user.name.text | Multi-field of `destination.user.name`. | match_only_text | @@ -857,6 +859,8 @@ The raw `originsicname` value is preserved in `checkpoint.origin_sic_name`. Beca | source.port | Port of the source. | long | | source.user.domain | Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name. | keyword | | source.user.email | User email address. | keyword | +| source.user.full_name | User's full name, if available. | keyword | +| source.user.full_name.text | Multi-field of `source.user.full_name`. | match_only_text | | source.user.group.name | Name of the group. | keyword | | source.user.id | Unique identifier of the user. | keyword | | source.user.name | Short name or login of the user. | keyword | @@ -867,6 +871,8 @@ The raw `originsicname` value is preserved in `checkpoint.origin_sic_name`. Beca | url.original.text | Multi-field of `url.original`. | match_only_text | | user.domain | Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name. | keyword | | user.email | User email address. | keyword | +| user.full_name | User's full name, if available. | keyword | +| user.full_name.text | Multi-field of `user.full_name`. | match_only_text | | user.group.name | Name of the group. | keyword | | user.id | Unique identifier of the user. | keyword | | user.name | Short name or login of the user. | keyword | diff --git a/packages/checkpoint/manifest.yml b/packages/checkpoint/manifest.yml index cae179da89c..135aa9d3f79 100644 --- a/packages/checkpoint/manifest.yml +++ b/packages/checkpoint/manifest.yml @@ -1,6 +1,6 @@ name: checkpoint title: Check Point -version: "1.47.0" +version: "1.48.0" description: Collect logs from Check Point with Elastic Agent. type: integration format_version: "3.0.3" diff --git a/packages/cyberark_epm/_dev/deploy/docker/files/config.yml b/packages/cyberark_epm/_dev/deploy/docker/files/config.yml index b74e3ed1a61..c6e96974a36 100644 --- a/packages/cyberark_epm/_dev/deploy/docker/files/config.yml +++ b/packages/cyberark_epm/_dev/deploy/docker/files/config.yml @@ -4,7 +4,7 @@ rules: request_headers: Content-Type: - "application/json" - request_body: '{"ApplicationID":"Elastic Integration CyberArk EPM","Password":"password","Username":"username"}' + request_body: '{"ApplicationID":"Elastic Integration CyberArk EPM","Password":"p@ss\"w/ord\\test","Username":"user\"name"}' responses: - status_code: 200 headers: diff --git a/packages/cyberark_epm/changelog.yml b/packages/cyberark_epm/changelog.yml index 425110140b9..e05dc02f27a 100644 --- a/packages/cyberark_epm/changelog.yml +++ b/packages/cyberark_epm/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "1.5.1" + changes: + - description: Fix login failure when username or password contains quotes, slashes, or backslashes. + type: bugfix + link: https://github.com/elastic/integrations/pull/20118 - version: "1.5.0" changes: - description: Use new `release` field for agentless deployment mode to establish as beta. diff --git a/packages/cyberark_epm/data_stream/admin_audit/_dev/test/system/test-default-config.yml b/packages/cyberark_epm/data_stream/admin_audit/_dev/test/system/test-default-config.yml index 01e94ed10d5..066560904a6 100644 --- a/packages/cyberark_epm/data_stream/admin_audit/_dev/test/system/test-default-config.yml +++ b/packages/cyberark_epm/data_stream/admin_audit/_dev/test/system/test-default-config.yml @@ -2,8 +2,8 @@ input: cel service: cyberark_epm vars: url: http://{{Hostname}}:{{Port}} - username: username - password: password + username: 'user"name' + password: 'p@ss"w/ord\test' session_timeout: 30m data_stream: vars: diff --git a/packages/cyberark_epm/data_stream/admin_audit/agent/stream/cel.yml.hbs b/packages/cyberark_epm/data_stream/admin_audit/agent/stream/cel.yml.hbs index d431080ce8c..470569b2975 100644 --- a/packages/cyberark_epm/data_stream/admin_audit/agent/stream/cel.yml.hbs +++ b/packages/cyberark_epm/data_stream/admin_audit/agent/stream/cel.yml.hbs @@ -15,8 +15,8 @@ resource.timeout: {{http_client_timeout}} {{/if}} resource.url: {{url}} state: - username: {{username}} - password: {{password}} + username: {{escape_string username}} + password: {{escape_string password}} initial_interval: {{initial_interval}} session_timeout: {{session_timeout}} limit: {{page_size}} diff --git a/packages/cyberark_epm/data_stream/admin_audit/sample_event.json b/packages/cyberark_epm/data_stream/admin_audit/sample_event.json index 92bb2ec461d..c03b9ce99c9 100644 --- a/packages/cyberark_epm/data_stream/admin_audit/sample_event.json +++ b/packages/cyberark_epm/data_stream/admin_audit/sample_event.json @@ -1,11 +1,11 @@ { "@timestamp": "2024-11-25T05:37:28.373Z", "agent": { - "ephemeral_id": "1948d980-9bbf-4bc6-b1fe-333a4b03ce3d", - "id": "1002d46a-e45c-4ff8-8460-b561d81b207e", - "name": "elastic-agent-83261", + "ephemeral_id": "4b45a5c1-7b38-434f-8f17-a8d605c63e7d", + "id": "75ccfaff-309d-4cc7-aad7-4b2e4a3e99ef", + "name": "elastic-agent-41944", "type": "filebeat", - "version": "8.18.1" + "version": "8.19.2" }, "cyberark_epm": { "admin_audit": { @@ -23,16 +23,16 @@ }, "data_stream": { "dataset": "cyberark_epm.admin_audit", - "namespace": "54477", + "namespace": "32767", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "1002d46a-e45c-4ff8-8460-b561d81b207e", + "id": "75ccfaff-309d-4cc7-aad7-4b2e4a3e99ef", "snapshot": false, - "version": "8.18.1" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -40,7 +40,7 @@ "iam" ], "dataset": "cyberark_epm.admin_audit", - "ingested": "2025-06-03T11:24:52Z", + "ingested": "2026-07-06T11:49:47Z", "kind": "event", "original": "{\"Administrator\":\"bob@example.com\",\"Description\":\"Enter Set Elastic/test\",\"EventTime\":\"2024-11-25T05:37:28.373Z\",\"Feature\":\"Sets\",\"InternalSessionId\":876,\"LoggedAt\":\"2024-11-25T05:25:13.167Z\",\"LoggedFrom\":\"175.16.199.1\",\"PermissionDescription\":\"None\",\"Role\":\"SetAdmin\",\"SetName\":\"Elastic/test\"}", "type": [ diff --git a/packages/cyberark_epm/data_stream/aggregated_event/_dev/test/system/test-default-config.yml b/packages/cyberark_epm/data_stream/aggregated_event/_dev/test/system/test-default-config.yml index 7a48d5fc233..352339f83bc 100644 --- a/packages/cyberark_epm/data_stream/aggregated_event/_dev/test/system/test-default-config.yml +++ b/packages/cyberark_epm/data_stream/aggregated_event/_dev/test/system/test-default-config.yml @@ -2,8 +2,8 @@ input: cel service: cyberark_epm vars: url: http://{{Hostname}}:{{Port}} - username: username - password: password + username: 'user"name' + password: 'p@ss"w/ord\test' session_timeout: 30m data_stream: vars: diff --git a/packages/cyberark_epm/data_stream/aggregated_event/agent/stream/cel.yml.hbs b/packages/cyberark_epm/data_stream/aggregated_event/agent/stream/cel.yml.hbs index e1cd8551ee0..035abae23b5 100644 --- a/packages/cyberark_epm/data_stream/aggregated_event/agent/stream/cel.yml.hbs +++ b/packages/cyberark_epm/data_stream/aggregated_event/agent/stream/cel.yml.hbs @@ -15,8 +15,8 @@ resource.timeout: {{http_client_timeout}} {{/if}} resource.url: {{url}} state: - username: {{username}} - password: {{password}} + username: {{escape_string username}} + password: {{escape_string password}} initial_interval: {{initial_interval}} session_timeout: {{session_timeout}} limit: {{page_size}} diff --git a/packages/cyberark_epm/data_stream/aggregated_event/sample_event.json b/packages/cyberark_epm/data_stream/aggregated_event/sample_event.json index 91498a0ae3d..3af7e398149 100644 --- a/packages/cyberark_epm/data_stream/aggregated_event/sample_event.json +++ b/packages/cyberark_epm/data_stream/aggregated_event/sample_event.json @@ -1,11 +1,11 @@ { "@timestamp": "2024-11-25T11:25:18.712Z", "agent": { - "ephemeral_id": "41121a9e-2b78-42e1-b4ee-97279ee58824", - "id": "497e924b-d605-4c9d-a197-8e5804077321", - "name": "elastic-agent-46395", + "ephemeral_id": "d7ea9f7e-3c32-4ab5-95c9-3a466e728db9", + "id": "2706ecc4-8a14-4ae7-ab62-4e01d6315282", + "name": "elastic-agent-81923", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "aggregated_event": { @@ -50,16 +50,16 @@ }, "data_stream": { "dataset": "cyberark_epm.aggregated_event", - "namespace": "99704", + "namespace": "10671", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "497e924b-d605-4c9d-a197-8e5804077321", + "id": "2706ecc4-8a14-4ae7-ab62-4e01d6315282", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -68,7 +68,7 @@ ], "dataset": "cyberark_epm.aggregated_event", "end": "2024-11-25T11:25:17.114Z", - "ingested": "2025-01-06T05:25:15Z", + "ingested": "2026-07-06T11:50:56Z", "kind": "event", "original": "{\"CLSID\":\"\",\"affectedComputers\":1,\"affectedUsers\":1,\"agentId\":\"109f521d-2ee1-450b-9f71-3cc56d8ebf37\",\"aggregatedBy\":\"0E4B8652719D84B66BFBFCF195C43513AF8459D8,2048\",\"appPackageDisplayName\":\"\",\"applicationType\":\"Executable\",\"applicationTypeId\":3,\"arrivalTime\":\"2024-11-25T11:25:18.712Z\",\"deceptionType\":0,\"defenceActionId\":0,\"eventType\":\"Launch\",\"eventTypeId\":2048,\"exposedUsers\":0,\"fileLocation\":\"C:\\\\Oracle\\\\oemmw\\\\oracle_common\\\\ccr\\\\bin\\\\\",\"fileQualifier\":\"-1035712369269809536\",\"fileSize\":13312,\"firstEventComputerName\":\"TEST\",\"firstEventDate\":\"2024-11-25T11:25:17.114Z\",\"firstEventUserName\":\"TEST\\\\Administrator\",\"hash\":\"SHA1##0E4B8652719D84B66BFBFCF195C43513AF8459D8\",\"lastAgentId\":\"109f521d-2ee1-450b-9f71-3cc56d8ebf37\",\"lastEventAccessTargetName\":\"\",\"lastEventAccessTargetType\":null,\"lastEventAgentId\":null,\"lastEventAuthorizationRights\":\"\",\"lastEventComputerName\":\"TEST\",\"lastEventDate\":\"2024-11-25T11:25:17.114Z\",\"lastEventDisplayName\":\"setupCCR.exe -a -d -S...\",\"lastEventExposedUsers\":null,\"lastEventExposedUsersCount\":0,\"lastEventFileName\":\"setupCCR.exe\",\"lastEventId\":\"ZpURY5MBdDBWucfdnK1j\",\"lastEventInitiatedProcess\":null,\"lastEventInitiatedProcessLocation\":null,\"lastEventJustification\":\"\",\"lastEventOriginalFileName\":\"\",\"lastEventPackageName\":null,\"lastEventSourceName\":\"ouiSFX (setup_em13200p1_win64.exe)\",\"lastEventSourceType\":\"LocalDisk\",\"lastEventSymLink\":\"\",\"lastEventUserName\":\"TEST\\\\Administrator\",\"mimeType\":\"\",\"operatingSystemType\":\"Windows\",\"packageName\":\"ouiSFX (setup_em13200p1_win64.exe)\",\"productCode\":null,\"publisher\":\"\",\"skipped\":false,\"skippedCount\":0,\"threatDetectionAction\":\"\",\"totalEvents\":1,\"upgradeCode\":null,\"url\":\"\"}", "start": "2024-11-25T11:25:17.114Z", diff --git a/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/_dev/test/system/test-default-config.yml b/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/_dev/test/system/test-default-config.yml index 7a48d5fc233..352339f83bc 100644 --- a/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/_dev/test/system/test-default-config.yml +++ b/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/_dev/test/system/test-default-config.yml @@ -2,8 +2,8 @@ input: cel service: cyberark_epm vars: url: http://{{Hostname}}:{{Port}} - username: username - password: password + username: 'user"name' + password: 'p@ss"w/ord\test' session_timeout: 30m data_stream: vars: diff --git a/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/agent/stream/cel.yml.hbs b/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/agent/stream/cel.yml.hbs index a2d80762675..7bc358f01a3 100644 --- a/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/agent/stream/cel.yml.hbs +++ b/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/agent/stream/cel.yml.hbs @@ -15,8 +15,8 @@ resource.timeout: {{http_client_timeout}} {{/if}} resource.url: {{url}} state: - username: {{username}} - password: {{password}} + username: {{escape_string username}} + password: {{escape_string password}} initial_interval: {{initial_interval}} session_timeout: {{session_timeout}} limit: {{page_size}} diff --git a/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/sample_event.json b/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/sample_event.json index eb0fe335de3..df3f09c109a 100644 --- a/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/sample_event.json +++ b/packages/cyberark_epm/data_stream/policyaudit_aggregated_event/sample_event.json @@ -1,11 +1,11 @@ { "@timestamp": "2022-12-19T05:51:06.024Z", "agent": { - "ephemeral_id": "4a9c2d55-8e03-42ee-9d25-55164bff9092", - "id": "f1613af9-3456-4b63-b774-f20eda58a491", - "name": "elastic-agent-46379", + "ephemeral_id": "8cbdbba2-9c50-4854-9c2a-075ebcae2e70", + "id": "b6227a62-bc3a-4a3d-8a4c-e2ea82486928", + "name": "elastic-agent-56821", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "policyaudit_aggregated_event": { @@ -46,16 +46,16 @@ }, "data_stream": { "dataset": "cyberark_epm.policyaudit_aggregated_event", - "namespace": "90464", + "namespace": "33531", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "f1613af9-3456-4b63-b774-f20eda58a491", + "id": "b6227a62-bc3a-4a3d-8a4c-e2ea82486928", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -64,7 +64,7 @@ ], "dataset": "cyberark_epm.policyaudit_aggregated_event", "end": "2022-12-19T01:04:47.284Z", - "ingested": "2025-01-06T05:26:14Z", + "ingested": "2026-07-06T11:51:54Z", "kind": "event", "original": "{\"CLSID\":\"\",\"adminTaskId\":\"\",\"affectedComputers\":1,\"affectedUsers\":1,\"aggregatedBy\":\"C340EFFBAED989E7F8FFC6F7574856CD8ED0D18B,QQQ\",\"appPackageDisplayName\":\"\",\"applicationType\":\"Executable\",\"arrivalTime\":\"2022-12-19T05:51:06.024Z\",\"authorizationRight\":\"com.apple.AOSNotification.FindMyMac.modify\",\"eventType\":\"Launch\",\"fileLocation\":\"C:\\\\Program Files (x86)\\\\Google\\\\Update\\\\1.3.36.152\\\\\",\"fileQualifier\":\"-5566271857083130002\",\"fileSize\":408536,\"firstEventAgentId\":\"b074b7d4-664a-40d1-b929-69e89bbd254c\",\"firstEventDate\":\"2022-12-14T21:06:44.756Z\",\"firstEventUserName\":\"NT AUTHORITY\\\\SYSTEM\",\"hash\":\"SHA1##C340EFFBAED989E7F8FFC6F7574856CD8ED0D18B\",\"lastEventAccessTarget\":null,\"lastEventAccessTargetType\":\"Registry\",\"lastEventAgentId\":\"b074b7d4-664a-40d1-b929-69e89bbd254c\",\"lastEventDate\":\"2022-12-19T01:04:47.284Z\",\"lastEventDisplayName\":\"Google Crash Handler (GoogleCrashHandler64.exe)\",\"lastEventFileName\":\"GoogleCrashHandler64.exe\",\"lastEventId\":\"QtvvKIUB8k35oa3KjVf7\",\"lastEventJustification\":\"\",\"lastEventPackageName\":\"Google Update (GoogleUpdate.exe)\",\"lastEventSourceName\":\"Updater (Google Updater)\",\"lastEventSourceType\":\"Updater\",\"lastEventSymlink\":\"\",\"lastEventUserName\":\"NT AUTHORITY\\\\SYSTEM\",\"mimeType\":\"\",\"operatingSystemType\":\"Windows\",\"policyAction\":null,\"policyId\":11161,\"policyName\":\"QQQ\",\"productCode\":null,\"publisher\":\"Google LLC\",\"skipped\":false,\"skippedCount\":0,\"totalEvents\":8,\"upgradeCode\":null,\"url\":\"\"}", "start": "2022-12-14T21:06:44.756Z", diff --git a/packages/cyberark_epm/data_stream/policyaudit_raw_event/_dev/test/system/test-default-config.yml b/packages/cyberark_epm/data_stream/policyaudit_raw_event/_dev/test/system/test-default-config.yml index 7fc0ea17ad4..83140f9dfd4 100644 --- a/packages/cyberark_epm/data_stream/policyaudit_raw_event/_dev/test/system/test-default-config.yml +++ b/packages/cyberark_epm/data_stream/policyaudit_raw_event/_dev/test/system/test-default-config.yml @@ -2,8 +2,8 @@ input: cel service: cyberark_epm vars: url: http://{{Hostname}}:{{Port}} - username: username - password: password + username: 'user"name' + password: 'p@ss"w/ord\test' session_timeout: 30m data_stream: vars: diff --git a/packages/cyberark_epm/data_stream/policyaudit_raw_event/agent/stream/cel.yml.hbs b/packages/cyberark_epm/data_stream/policyaudit_raw_event/agent/stream/cel.yml.hbs index 1300adc4548..132573b6d99 100644 --- a/packages/cyberark_epm/data_stream/policyaudit_raw_event/agent/stream/cel.yml.hbs +++ b/packages/cyberark_epm/data_stream/policyaudit_raw_event/agent/stream/cel.yml.hbs @@ -15,8 +15,8 @@ resource.timeout: {{http_client_timeout}} {{/if}} resource.url: {{url}} state: - username: {{username}} - password: {{password}} + username: {{escape_string username}} + password: {{escape_string password}} initial_interval: {{initial_interval}} session_timeout: {{session_timeout}} limit: {{page_size}} diff --git a/packages/cyberark_epm/data_stream/policyaudit_raw_event/sample_event.json b/packages/cyberark_epm/data_stream/policyaudit_raw_event/sample_event.json index a9e363feba7..bf86f031dc5 100644 --- a/packages/cyberark_epm/data_stream/policyaudit_raw_event/sample_event.json +++ b/packages/cyberark_epm/data_stream/policyaudit_raw_event/sample_event.json @@ -1,11 +1,11 @@ { "@timestamp": "2024-11-25T14:27:54.054Z", "agent": { - "ephemeral_id": "1a61d14a-fd5a-4285-8fa6-044656c01031", - "id": "204b047e-1c2d-4330-9821-2d3b668edf6b", - "name": "elastic-agent-60258", + "ephemeral_id": "b433f865-1940-4642-a125-41c29ecae6bb", + "id": "5a493f2c-7eeb-4ab6-83c7-1aa1fd9f0c6c", + "name": "elastic-agent-87286", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "policyaudit_raw_event": { @@ -46,16 +46,16 @@ }, "data_stream": { "dataset": "cyberark_epm.policyaudit_raw_event", - "namespace": "49746", + "namespace": "33261", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "204b047e-1c2d-4330-9821-2d3b668edf6b", + "id": "5a493f2c-7eeb-4ab6-83c7-1aa1fd9f0c6c", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -64,7 +64,7 @@ ], "dataset": "cyberark_epm.policyaudit_raw_event", "end": "2024-11-25T10:37:58.431Z", - "ingested": "2025-01-06T05:27:15Z", + "ingested": "2026-07-06T11:52:53Z", "kind": "event", "original": "{\"accessTargetName\":\"C:\\\\Oracle\\\\oemmw\\\\OPatch\\\\version.txt\",\"accessTargetType\":\"ransomware\",\"agentEventCount\":2,\"agentId\":\"48b4bf28-5257-4460-a384-9aac70fb7db2\",\"applicationSubType\":null,\"arguments\":\"status sshd\",\"arrivalTime\":\"2024-11-25T14:27:54.054Z\",\"authorizationRights\":null,\"bundleName\":\"\",\"bundleVersion\":\"\",\"codeURL\":\"\",\"commandInfo\":\"\",\"company\":\"\",\"computerName\":\"k8sworker1-50-2-19\",\"displayName\":\"systemctl\",\"eventType\":\"StartElevated\",\"fileAccessPermission\":\"-rwxr-xr-x\",\"fileDescription\":\"systemctl\",\"fileName\":\"systemctl\",\"filePath\":\"/usr/bin/systemctl\",\"fileQualifier\":\"2375697114193346955\",\"fileSize\":1115760,\"fileVersion\":\"\",\"firstEventDate\":\"2024-11-25T10:31:12.018Z\",\"hash\":\"5f344897632b50114a8ff649054599c6f7fa8a69\",\"interpreter\":\"\",\"justification\":\"\",\"justificationEmail\":\"\",\"lastEventDate\":\"2024-11-25T10:37:58.431Z\",\"mimeType\":\"\",\"modificationTime\":\"2024-10-26T14:27:54.041Z\",\"operatingSystemType\":\"Linux\",\"originUserUID\":\"0\",\"originalFileName\":\"\",\"owner\":\"root\",\"packageName\":\"systemctl\",\"parentProcess\":\"\",\"policyAction\":\"Elevate\",\"policyName\":\"Test-elastic\",\"productCode\":\"\",\"productName\":\"SQL*PLUS\",\"productVersion\":\"\",\"publisher\":\"\",\"runAsUsername\":\"root\",\"skippedCount\":0,\"sourceName\":\"/usr/bin/systemctl\",\"sourceType\":\"LocalDisk\",\"symLink\":\"\",\"upgradeCode\":\"\",\"userIsAdmin\":true,\"userName\":\"root\",\"workingDirectory\":\"/home/serviceuser\"}", "start": "2024-11-25T10:31:12.018Z", diff --git a/packages/cyberark_epm/data_stream/raw_event/_dev/test/system/test-default-config.yml b/packages/cyberark_epm/data_stream/raw_event/_dev/test/system/test-default-config.yml index 01e94ed10d5..066560904a6 100644 --- a/packages/cyberark_epm/data_stream/raw_event/_dev/test/system/test-default-config.yml +++ b/packages/cyberark_epm/data_stream/raw_event/_dev/test/system/test-default-config.yml @@ -2,8 +2,8 @@ input: cel service: cyberark_epm vars: url: http://{{Hostname}}:{{Port}} - username: username - password: password + username: 'user"name' + password: 'p@ss"w/ord\test' session_timeout: 30m data_stream: vars: diff --git a/packages/cyberark_epm/data_stream/raw_event/agent/stream/cel.yml.hbs b/packages/cyberark_epm/data_stream/raw_event/agent/stream/cel.yml.hbs index 36707bce93e..dcacc20fbc2 100644 --- a/packages/cyberark_epm/data_stream/raw_event/agent/stream/cel.yml.hbs +++ b/packages/cyberark_epm/data_stream/raw_event/agent/stream/cel.yml.hbs @@ -15,8 +15,8 @@ resource.timeout: {{http_client_timeout}} {{/if}} resource.url: {{url}} state: - username: {{username}} - password: {{password}} + username: {{escape_string username}} + password: {{escape_string password}} initial_interval: {{initial_interval}} session_timeout: {{session_timeout}} limit: {{page_size}} diff --git a/packages/cyberark_epm/data_stream/raw_event/sample_event.json b/packages/cyberark_epm/data_stream/raw_event/sample_event.json index d56f8d9c8e9..654be8595b6 100644 --- a/packages/cyberark_epm/data_stream/raw_event/sample_event.json +++ b/packages/cyberark_epm/data_stream/raw_event/sample_event.json @@ -1,11 +1,11 @@ { "@timestamp": "2024-11-28T05:24:15.693Z", "agent": { - "ephemeral_id": "b2114da7-4d06-4236-a161-456e590812c4", - "id": "ffd91dcb-1e39-4e3d-a0ca-06e5b5d75873", - "name": "elastic-agent-96710", + "ephemeral_id": "7ea3fe76-e396-467a-9306-9275e62581cb", + "id": "40c0cba3-776f-463a-a365-f3fe72c61452", + "name": "elastic-agent-95612", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "raw_event": { @@ -59,16 +59,16 @@ }, "data_stream": { "dataset": "cyberark_epm.raw_event", - "namespace": "33414", + "namespace": "46289", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "ffd91dcb-1e39-4e3d-a0ca-06e5b5d75873", + "id": "40c0cba3-776f-463a-a365-f3fe72c61452", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "action": "all", @@ -78,7 +78,7 @@ ], "dataset": "cyberark_epm.raw_event", "end": "2024-11-28T05:03:10.094Z", - "ingested": "2025-01-06T05:28:21Z", + "ingested": "2026-07-06T11:53:54Z", "kind": "event", "original": "{\"accessAction\":\"false\",\"accessTargetName\":null,\"accessTargetType\":\"Internet\",\"agentEventCount\":1,\"agentId\":\"109f521d-2ee1-450b-9f71-3cc56d8ebf37\",\"applicationSubType\":null,\"arrivalTime\":\"2024-11-28T05:24:15.693Z\",\"authorizationRights\":null,\"bundleId\":null,\"bundleName\":null,\"bundleVersion\":null,\"company\":\"Microsoft Corporation\",\"computerName\":\"TEST-PC\",\"deceptionType\":0,\"displayName\":\"Windows host process (Rundll32) (rundll32.exe)\",\"eventCount\":1,\"eventType\":\"Launch\",\"evidences\":null,\"exposedUsers\":null,\"fatherProcess\":null,\"fileAccessPermission\":null,\"fileDescription\":\"Windows host process (Rundll32)\",\"fileName\":\"rundll32.exe\",\"filePath\":\"C:\\\\Windows\\\\System32\\\\rundll32.exe\",\"filePathWithoutFilename\":\"C:\\\\Windows\\\\System32\\\\\",\"fileQualifier\":\"-6929158130464282036\",\"fileSize\":71168,\"fileVersion\":\"10.0.17763.1697\",\"firstEventDate\":\"2024-11-28T05:03:10.094Z\",\"hash\":\"A40886F98905F3D9DBDD61DA1D59CCB4F4854758\",\"interpreter\":null,\"justification\":null,\"justificationEmail\":null,\"lastEventDate\":\"2024-11-28T05:03:10.094Z\",\"logonAttemptTypeId\":5,\"logonStatusId\":3221225779,\"lureUser\":null,\"modificationTime\":\"2024-10-29T05:24:15.618Z\",\"operatingSystemType\":\"Windows\",\"originUserUID\":null,\"originalFileName\":\"RUNDLL32.EXE\",\"owner\":\"NT SERVICE\\\\TrustedInstaller\",\"packageName\":\"Windows host process (Rundll32) (rundll32.exe)\",\"policyCategory\":null,\"policyName\":\"test-rule2\",\"processCertificateIssuer\":null,\"processCommandLine\":\"Startupscan.dll,SusRunTask\",\"productCode\":null,\"productName\":\"Microsoft® Windows® Operating System\",\"productVersion\":\"10.0.17763.1697\",\"publisher\":\"Microsoft Windows\",\"runAsUsername\":null,\"skippedCount\":0,\"sourceName\":\"Microsoft Windows\",\"sourceProcessCertificateIssuer\":null,\"sourceProcessCommandLine\":null,\"sourceProcessHash\":null,\"sourceProcessPublisher\":null,\"sourceProcessSigner\":null,\"sourceProcessUsername\":null,\"sourceType\":\"Windows\",\"sourceWSIp\":null,\"sourceWSName\":null,\"symLink\":null,\"threatProtectionAction\":\"ALL\",\"threatProtectionActionId\":0,\"upgradeCode\":null,\"userIsAdmin\":true,\"userName\":\"TEST-PC\\\\Administrator\",\"winEventRecordId\":0,\"winEventType\":0,\"workingDirectory\":null}", "start": "2024-11-28T05:03:10.094Z", diff --git a/packages/cyberark_epm/docs/README.md b/packages/cyberark_epm/docs/README.md index 7468691e0b8..c6fe95543dd 100644 --- a/packages/cyberark_epm/docs/README.md +++ b/packages/cyberark_epm/docs/README.md @@ -63,11 +63,11 @@ An example event for `raw_event` looks as following: { "@timestamp": "2024-11-28T05:24:15.693Z", "agent": { - "ephemeral_id": "b2114da7-4d06-4236-a161-456e590812c4", - "id": "ffd91dcb-1e39-4e3d-a0ca-06e5b5d75873", - "name": "elastic-agent-96710", + "ephemeral_id": "7ea3fe76-e396-467a-9306-9275e62581cb", + "id": "40c0cba3-776f-463a-a365-f3fe72c61452", + "name": "elastic-agent-95612", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "raw_event": { @@ -121,16 +121,16 @@ An example event for `raw_event` looks as following: }, "data_stream": { "dataset": "cyberark_epm.raw_event", - "namespace": "33414", + "namespace": "46289", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "ffd91dcb-1e39-4e3d-a0ca-06e5b5d75873", + "id": "40c0cba3-776f-463a-a365-f3fe72c61452", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "action": "all", @@ -140,7 +140,7 @@ An example event for `raw_event` looks as following: ], "dataset": "cyberark_epm.raw_event", "end": "2024-11-28T05:03:10.094Z", - "ingested": "2025-01-06T05:28:21Z", + "ingested": "2026-07-06T11:53:54Z", "kind": "event", "original": "{\"accessAction\":\"false\",\"accessTargetName\":null,\"accessTargetType\":\"Internet\",\"agentEventCount\":1,\"agentId\":\"109f521d-2ee1-450b-9f71-3cc56d8ebf37\",\"applicationSubType\":null,\"arrivalTime\":\"2024-11-28T05:24:15.693Z\",\"authorizationRights\":null,\"bundleId\":null,\"bundleName\":null,\"bundleVersion\":null,\"company\":\"Microsoft Corporation\",\"computerName\":\"TEST-PC\",\"deceptionType\":0,\"displayName\":\"Windows host process (Rundll32) (rundll32.exe)\",\"eventCount\":1,\"eventType\":\"Launch\",\"evidences\":null,\"exposedUsers\":null,\"fatherProcess\":null,\"fileAccessPermission\":null,\"fileDescription\":\"Windows host process (Rundll32)\",\"fileName\":\"rundll32.exe\",\"filePath\":\"C:\\\\Windows\\\\System32\\\\rundll32.exe\",\"filePathWithoutFilename\":\"C:\\\\Windows\\\\System32\\\\\",\"fileQualifier\":\"-6929158130464282036\",\"fileSize\":71168,\"fileVersion\":\"10.0.17763.1697\",\"firstEventDate\":\"2024-11-28T05:03:10.094Z\",\"hash\":\"A40886F98905F3D9DBDD61DA1D59CCB4F4854758\",\"interpreter\":null,\"justification\":null,\"justificationEmail\":null,\"lastEventDate\":\"2024-11-28T05:03:10.094Z\",\"logonAttemptTypeId\":5,\"logonStatusId\":3221225779,\"lureUser\":null,\"modificationTime\":\"2024-10-29T05:24:15.618Z\",\"operatingSystemType\":\"Windows\",\"originUserUID\":null,\"originalFileName\":\"RUNDLL32.EXE\",\"owner\":\"NT SERVICE\\\\TrustedInstaller\",\"packageName\":\"Windows host process (Rundll32) (rundll32.exe)\",\"policyCategory\":null,\"policyName\":\"test-rule2\",\"processCertificateIssuer\":null,\"processCommandLine\":\"Startupscan.dll,SusRunTask\",\"productCode\":null,\"productName\":\"Microsoft® Windows® Operating System\",\"productVersion\":\"10.0.17763.1697\",\"publisher\":\"Microsoft Windows\",\"runAsUsername\":null,\"skippedCount\":0,\"sourceName\":\"Microsoft Windows\",\"sourceProcessCertificateIssuer\":null,\"sourceProcessCommandLine\":null,\"sourceProcessHash\":null,\"sourceProcessPublisher\":null,\"sourceProcessSigner\":null,\"sourceProcessUsername\":null,\"sourceType\":\"Windows\",\"sourceWSIp\":null,\"sourceWSName\":null,\"symLink\":null,\"threatProtectionAction\":\"ALL\",\"threatProtectionActionId\":0,\"upgradeCode\":null,\"userIsAdmin\":true,\"userName\":\"TEST-PC\\\\Administrator\",\"winEventRecordId\":0,\"winEventType\":0,\"workingDirectory\":null}", "start": "2024-11-28T05:03:10.094Z", @@ -316,11 +316,11 @@ An example event for `policyaudit_raw_event` looks as following: { "@timestamp": "2024-11-25T14:27:54.054Z", "agent": { - "ephemeral_id": "1a61d14a-fd5a-4285-8fa6-044656c01031", - "id": "204b047e-1c2d-4330-9821-2d3b668edf6b", - "name": "elastic-agent-60258", + "ephemeral_id": "b433f865-1940-4642-a125-41c29ecae6bb", + "id": "5a493f2c-7eeb-4ab6-83c7-1aa1fd9f0c6c", + "name": "elastic-agent-87286", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "policyaudit_raw_event": { @@ -361,16 +361,16 @@ An example event for `policyaudit_raw_event` looks as following: }, "data_stream": { "dataset": "cyberark_epm.policyaudit_raw_event", - "namespace": "49746", + "namespace": "33261", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "204b047e-1c2d-4330-9821-2d3b668edf6b", + "id": "5a493f2c-7eeb-4ab6-83c7-1aa1fd9f0c6c", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -379,7 +379,7 @@ An example event for `policyaudit_raw_event` looks as following: ], "dataset": "cyberark_epm.policyaudit_raw_event", "end": "2024-11-25T10:37:58.431Z", - "ingested": "2025-01-06T05:27:15Z", + "ingested": "2026-07-06T11:52:53Z", "kind": "event", "original": "{\"accessTargetName\":\"C:\\\\Oracle\\\\oemmw\\\\OPatch\\\\version.txt\",\"accessTargetType\":\"ransomware\",\"agentEventCount\":2,\"agentId\":\"48b4bf28-5257-4460-a384-9aac70fb7db2\",\"applicationSubType\":null,\"arguments\":\"status sshd\",\"arrivalTime\":\"2024-11-25T14:27:54.054Z\",\"authorizationRights\":null,\"bundleName\":\"\",\"bundleVersion\":\"\",\"codeURL\":\"\",\"commandInfo\":\"\",\"company\":\"\",\"computerName\":\"k8sworker1-50-2-19\",\"displayName\":\"systemctl\",\"eventType\":\"StartElevated\",\"fileAccessPermission\":\"-rwxr-xr-x\",\"fileDescription\":\"systemctl\",\"fileName\":\"systemctl\",\"filePath\":\"/usr/bin/systemctl\",\"fileQualifier\":\"2375697114193346955\",\"fileSize\":1115760,\"fileVersion\":\"\",\"firstEventDate\":\"2024-11-25T10:31:12.018Z\",\"hash\":\"5f344897632b50114a8ff649054599c6f7fa8a69\",\"interpreter\":\"\",\"justification\":\"\",\"justificationEmail\":\"\",\"lastEventDate\":\"2024-11-25T10:37:58.431Z\",\"mimeType\":\"\",\"modificationTime\":\"2024-10-26T14:27:54.041Z\",\"operatingSystemType\":\"Linux\",\"originUserUID\":\"0\",\"originalFileName\":\"\",\"owner\":\"root\",\"packageName\":\"systemctl\",\"parentProcess\":\"\",\"policyAction\":\"Elevate\",\"policyName\":\"Test-elastic\",\"productCode\":\"\",\"productName\":\"SQL*PLUS\",\"productVersion\":\"\",\"publisher\":\"\",\"runAsUsername\":\"root\",\"skippedCount\":0,\"sourceName\":\"/usr/bin/systemctl\",\"sourceType\":\"LocalDisk\",\"symLink\":\"\",\"upgradeCode\":\"\",\"userIsAdmin\":true,\"userName\":\"root\",\"workingDirectory\":\"/home/serviceuser\"}", "start": "2024-11-25T10:31:12.018Z", @@ -530,11 +530,11 @@ An example event for `aggregated_event` looks as following: { "@timestamp": "2024-11-25T11:25:18.712Z", "agent": { - "ephemeral_id": "41121a9e-2b78-42e1-b4ee-97279ee58824", - "id": "497e924b-d605-4c9d-a197-8e5804077321", - "name": "elastic-agent-46395", + "ephemeral_id": "d7ea9f7e-3c32-4ab5-95c9-3a466e728db9", + "id": "2706ecc4-8a14-4ae7-ab62-4e01d6315282", + "name": "elastic-agent-81923", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "aggregated_event": { @@ -579,16 +579,16 @@ An example event for `aggregated_event` looks as following: }, "data_stream": { "dataset": "cyberark_epm.aggregated_event", - "namespace": "99704", + "namespace": "10671", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "497e924b-d605-4c9d-a197-8e5804077321", + "id": "2706ecc4-8a14-4ae7-ab62-4e01d6315282", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -597,7 +597,7 @@ An example event for `aggregated_event` looks as following: ], "dataset": "cyberark_epm.aggregated_event", "end": "2024-11-25T11:25:17.114Z", - "ingested": "2025-01-06T05:25:15Z", + "ingested": "2026-07-06T11:50:56Z", "kind": "event", "original": "{\"CLSID\":\"\",\"affectedComputers\":1,\"affectedUsers\":1,\"agentId\":\"109f521d-2ee1-450b-9f71-3cc56d8ebf37\",\"aggregatedBy\":\"0E4B8652719D84B66BFBFCF195C43513AF8459D8,2048\",\"appPackageDisplayName\":\"\",\"applicationType\":\"Executable\",\"applicationTypeId\":3,\"arrivalTime\":\"2024-11-25T11:25:18.712Z\",\"deceptionType\":0,\"defenceActionId\":0,\"eventType\":\"Launch\",\"eventTypeId\":2048,\"exposedUsers\":0,\"fileLocation\":\"C:\\\\Oracle\\\\oemmw\\\\oracle_common\\\\ccr\\\\bin\\\\\",\"fileQualifier\":\"-1035712369269809536\",\"fileSize\":13312,\"firstEventComputerName\":\"TEST\",\"firstEventDate\":\"2024-11-25T11:25:17.114Z\",\"firstEventUserName\":\"TEST\\\\Administrator\",\"hash\":\"SHA1##0E4B8652719D84B66BFBFCF195C43513AF8459D8\",\"lastAgentId\":\"109f521d-2ee1-450b-9f71-3cc56d8ebf37\",\"lastEventAccessTargetName\":\"\",\"lastEventAccessTargetType\":null,\"lastEventAgentId\":null,\"lastEventAuthorizationRights\":\"\",\"lastEventComputerName\":\"TEST\",\"lastEventDate\":\"2024-11-25T11:25:17.114Z\",\"lastEventDisplayName\":\"setupCCR.exe -a -d -S...\",\"lastEventExposedUsers\":null,\"lastEventExposedUsersCount\":0,\"lastEventFileName\":\"setupCCR.exe\",\"lastEventId\":\"ZpURY5MBdDBWucfdnK1j\",\"lastEventInitiatedProcess\":null,\"lastEventInitiatedProcessLocation\":null,\"lastEventJustification\":\"\",\"lastEventOriginalFileName\":\"\",\"lastEventPackageName\":null,\"lastEventSourceName\":\"ouiSFX (setup_em13200p1_win64.exe)\",\"lastEventSourceType\":\"LocalDisk\",\"lastEventSymLink\":\"\",\"lastEventUserName\":\"TEST\\\\Administrator\",\"mimeType\":\"\",\"operatingSystemType\":\"Windows\",\"packageName\":\"ouiSFX (setup_em13200p1_win64.exe)\",\"productCode\":null,\"publisher\":\"\",\"skipped\":false,\"skippedCount\":0,\"threatDetectionAction\":\"\",\"totalEvents\":1,\"upgradeCode\":null,\"url\":\"\"}", "start": "2024-11-25T11:25:17.114Z", @@ -735,11 +735,11 @@ An example event for `policyaudit_aggregated_event` looks as following: { "@timestamp": "2022-12-19T05:51:06.024Z", "agent": { - "ephemeral_id": "4a9c2d55-8e03-42ee-9d25-55164bff9092", - "id": "f1613af9-3456-4b63-b774-f20eda58a491", - "name": "elastic-agent-46379", + "ephemeral_id": "8cbdbba2-9c50-4854-9c2a-075ebcae2e70", + "id": "b6227a62-bc3a-4a3d-8a4c-e2ea82486928", + "name": "elastic-agent-56821", "type": "filebeat", - "version": "8.16.0" + "version": "8.19.2" }, "cyberark_epm": { "policyaudit_aggregated_event": { @@ -780,16 +780,16 @@ An example event for `policyaudit_aggregated_event` looks as following: }, "data_stream": { "dataset": "cyberark_epm.policyaudit_aggregated_event", - "namespace": "90464", + "namespace": "33531", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "f1613af9-3456-4b63-b774-f20eda58a491", + "id": "b6227a62-bc3a-4a3d-8a4c-e2ea82486928", "snapshot": false, - "version": "8.16.0" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -798,7 +798,7 @@ An example event for `policyaudit_aggregated_event` looks as following: ], "dataset": "cyberark_epm.policyaudit_aggregated_event", "end": "2022-12-19T01:04:47.284Z", - "ingested": "2025-01-06T05:26:14Z", + "ingested": "2026-07-06T11:51:54Z", "kind": "event", "original": "{\"CLSID\":\"\",\"adminTaskId\":\"\",\"affectedComputers\":1,\"affectedUsers\":1,\"aggregatedBy\":\"C340EFFBAED989E7F8FFC6F7574856CD8ED0D18B,QQQ\",\"appPackageDisplayName\":\"\",\"applicationType\":\"Executable\",\"arrivalTime\":\"2022-12-19T05:51:06.024Z\",\"authorizationRight\":\"com.apple.AOSNotification.FindMyMac.modify\",\"eventType\":\"Launch\",\"fileLocation\":\"C:\\\\Program Files (x86)\\\\Google\\\\Update\\\\1.3.36.152\\\\\",\"fileQualifier\":\"-5566271857083130002\",\"fileSize\":408536,\"firstEventAgentId\":\"b074b7d4-664a-40d1-b929-69e89bbd254c\",\"firstEventDate\":\"2022-12-14T21:06:44.756Z\",\"firstEventUserName\":\"NT AUTHORITY\\\\SYSTEM\",\"hash\":\"SHA1##C340EFFBAED989E7F8FFC6F7574856CD8ED0D18B\",\"lastEventAccessTarget\":null,\"lastEventAccessTargetType\":\"Registry\",\"lastEventAgentId\":\"b074b7d4-664a-40d1-b929-69e89bbd254c\",\"lastEventDate\":\"2022-12-19T01:04:47.284Z\",\"lastEventDisplayName\":\"Google Crash Handler (GoogleCrashHandler64.exe)\",\"lastEventFileName\":\"GoogleCrashHandler64.exe\",\"lastEventId\":\"QtvvKIUB8k35oa3KjVf7\",\"lastEventJustification\":\"\",\"lastEventPackageName\":\"Google Update (GoogleUpdate.exe)\",\"lastEventSourceName\":\"Updater (Google Updater)\",\"lastEventSourceType\":\"Updater\",\"lastEventSymlink\":\"\",\"lastEventUserName\":\"NT AUTHORITY\\\\SYSTEM\",\"mimeType\":\"\",\"operatingSystemType\":\"Windows\",\"policyAction\":null,\"policyId\":11161,\"policyName\":\"QQQ\",\"productCode\":null,\"publisher\":\"Google LLC\",\"skipped\":false,\"skippedCount\":0,\"totalEvents\":8,\"upgradeCode\":null,\"url\":\"\"}", "start": "2022-12-14T21:06:44.756Z", @@ -927,11 +927,11 @@ An example event for `admin_audit` looks as following: { "@timestamp": "2024-11-25T05:37:28.373Z", "agent": { - "ephemeral_id": "1948d980-9bbf-4bc6-b1fe-333a4b03ce3d", - "id": "1002d46a-e45c-4ff8-8460-b561d81b207e", - "name": "elastic-agent-83261", + "ephemeral_id": "4b45a5c1-7b38-434f-8f17-a8d605c63e7d", + "id": "75ccfaff-309d-4cc7-aad7-4b2e4a3e99ef", + "name": "elastic-agent-41944", "type": "filebeat", - "version": "8.18.1" + "version": "8.19.2" }, "cyberark_epm": { "admin_audit": { @@ -949,16 +949,16 @@ An example event for `admin_audit` looks as following: }, "data_stream": { "dataset": "cyberark_epm.admin_audit", - "namespace": "54477", + "namespace": "32767", "type": "logs" }, "ecs": { "version": "8.11.0" }, "elastic_agent": { - "id": "1002d46a-e45c-4ff8-8460-b561d81b207e", + "id": "75ccfaff-309d-4cc7-aad7-4b2e4a3e99ef", "snapshot": false, - "version": "8.18.1" + "version": "8.19.2" }, "event": { "agent_id_status": "verified", @@ -966,7 +966,7 @@ An example event for `admin_audit` looks as following: "iam" ], "dataset": "cyberark_epm.admin_audit", - "ingested": "2025-06-03T11:24:52Z", + "ingested": "2026-07-06T11:49:47Z", "kind": "event", "original": "{\"Administrator\":\"bob@example.com\",\"Description\":\"Enter Set Elastic/test\",\"EventTime\":\"2024-11-25T05:37:28.373Z\",\"Feature\":\"Sets\",\"InternalSessionId\":876,\"LoggedAt\":\"2024-11-25T05:25:13.167Z\",\"LoggedFrom\":\"175.16.199.1\",\"PermissionDescription\":\"None\",\"Role\":\"SetAdmin\",\"SetName\":\"Elastic/test\"}", "type": [ diff --git a/packages/cyberark_epm/manifest.yml b/packages/cyberark_epm/manifest.yml index 950958a16ac..d8a4313c02c 100644 --- a/packages/cyberark_epm/manifest.yml +++ b/packages/cyberark_epm/manifest.yml @@ -1,7 +1,7 @@ format_version: 3.3.2 name: cyberark_epm title: CyberArk EPM -version: "1.5.0" +version: "1.5.1" description: Collect logs from CyberArk EPM with Elastic Agent. type: integration categories: diff --git a/packages/cyera/_dev/build/docs/README.md b/packages/cyera/_dev/build/docs/README.md index 85867a6be1e..ecf5c61d4a2 100644 --- a/packages/cyera/_dev/build/docs/README.md +++ b/packages/cyera/_dev/build/docs/README.md @@ -16,10 +16,11 @@ This integration is compatible with different versions of Cyera APIs for respect | Issue | v3 | | Event | v1 | | Datastore | v2 | +| Audit | v2 | ### How it works -This integration periodically queries the Cyera API to retrieve classifications, issues, events and datastores. +This integration periodically queries the Cyera API to retrieve classifications, issues, events, datastores and audit logs. ## What data does this integration collect? @@ -33,8 +34,10 @@ This integration collects log messages of the following types: - `Datastore`: Collects all datastore objects from the Cyera system. +- `Audit`: Collects the platform audit trail (user logins, API key management, user and role management, and other administrative actions) from the Cyera system. + ### Supported use cases -Integrating Cyera Classification, Issues, Events and Datastore data streams with Elastic SIEM provides end-to-end visibility into where sensitive data resides, the risks tied to that data, and the security events triggered across cloud and SaaS environments. By correlating datastore metadata (such as type, provider, sensitivity, and ownership) with Cyera’s classification intelligence, issue context, and event activity in Elastic analytics, security teams can strengthen data security posture, accelerate incident response, and simplify compliance. Dashboards in Kibana present breakdowns by datastore type, sensitivity, category, severity, status, risk status, event type, and trends over time — enabling faster investigations, better prioritization, and improved accountability. +Integrating Cyera Classification, Issues, Events, Datastore and Audit data streams with Elastic SIEM provides end-to-end visibility into where sensitive data resides, the risks tied to that data, and the security events triggered across cloud and SaaS environments. By correlating datastore metadata (such as type, provider, sensitivity, and ownership) with Cyera’s classification intelligence, issue context, and event activity in Elastic analytics, security teams can strengthen data security posture, accelerate incident response, and simplify compliance. The audit trail adds accountability over the Cyera platform itself, surfacing who signed in, what was changed, and which credentials were created or removed. Dashboards in Kibana present breakdowns by datastore type, sensitivity, category, severity, status, risk status, event type, and trends over time — enabling faster investigations, better prioritization, and improved accountability. ## What do I need to use this integration? @@ -51,6 +54,7 @@ The integration authenticates to the Cyera API using a `Client ID` and `Client S - Cyera **Admin** role. - An active Cyera **DSPM** license. - Access to the partner integration page in the Cyera platform. +- For the Audit data stream: an API token generated by a user with the **Admin** role, and outbound HTTPS access to the Cyera audit API host (`https://auth.cyera.io` by default, configurable through the **Audit URL** setting). The audit trail is served from the Cyera authentication host, which is separate from the data API host. #### Obtain credentials @@ -93,6 +97,7 @@ Elastic Agent must be installed. For more details, check the Elastic Agent [inst - Configure **URL**, **Client ID**, and **Client Secret**. - Enable/Disable the required datasets. - For each dataset, adjust the integration configuration parameters if required, including the Initial Interval, Interval, Batch Size etc. to enable data collection. + - For the **Audit** dataset, confirm the **Audit URL** setting. It defaults to `https://auth.cyera.io`, the Cyera authentication host that serves the audit trail, and only needs to be changed if Cyera support has provided a different audit host for your tenant. Audit collection also requires the API token to have been generated by a user with the **Admin** role; tokens without it are rejected by the audit API. 6. Select **Save and continue** to save the integration. @@ -151,6 +156,14 @@ For more information on architectures that can be used for scaling this integrat {{event "event"}} +### Audit + +{{fields "audit"}} + +#### Example event + +{{event "audit"}} + ### Inputs used These inputs can be used in this integration: diff --git a/packages/cyera/_dev/deploy/docker/files/config.yml b/packages/cyera/_dev/deploy/docker/files/config.yml index 6e72259b1c0..9c8f1e1d10f 100644 --- a/packages/cyera/_dev/deploy/docker/files/config.yml +++ b/packages/cyera/_dev/deploy/docker/files/config.yml @@ -1883,6 +1883,141 @@ rules: ] } `}} + - path: /audits/resources/audits/v2 + methods: ['GET'] + query_params: + count: 2 + offset: 0 + created_from: "{createdFrom:20.*}" + request_headers: + Authorization: + - 'Bearer xxxx' + responses: + - status_code: 200 + headers: + Content-Type: + - 'application/json' + body: | + {{ minify_json ` + { + "data": [ + { + "frontegg_id": "5324ccd7-c588-4683-962e-219eaaaed8da", + "vendorId": "2dc00405-79cd-457b-b288-a119c6f0c7b7", + "tenantId": "854c25fb-84d6-49ac-a593-5cafb24f769e", + "severity": "Info", + "ip": "203.0.113.10", + "email": "jane.doe@example.com", + "action": "User logged in", + "description": "User logged in to the application", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36", + "createdAt": "2025-08-25T09:12:44.376Z", + "updatedAt": "2025-08-25T09:12:44.376Z", + "environmentName": "Global" + }, + { + "frontegg_id": "f2290969-377c-4541-8e3f-bf41a02450c0", + "vendorId": "2dc00405-79cd-457b-b288-a119c6f0c7b7", + "tenantId": "854c25fb-84d6-49ac-a593-5cafb24f769e", + "severity": "Info", + "ip": "198.51.100.24", + "email": "jane.doe@example.com", + "action": "Created API key", + "description": "Created new API key on the product", + "userAgent": "axios/1.7.2", + "createdAt": "2025-08-25T10:01:44.179Z", + "updatedAt": "2025-08-25T10:01:44.179Z", + "environmentName": "Global" + } + ], + "total": 5 + } + `}} + - path: /audits/resources/audits/v2 + methods: ['GET'] + query_params: + count: 2 + offset: 2 + created_from: "{createdFrom:20.*}" + request_headers: + Authorization: + - 'Bearer xxxx' + responses: + - status_code: 200 + headers: + Content-Type: + - 'application/json' + body: | + {{ minify_json ` + { + "data": [ + { + "frontegg_id": "a21d1ab0-855d-49da-9d21-6201d1c8b7c5", + "vendorId": "2dc00405-79cd-457b-b288-a119c6f0c7b7", + "tenantId": "854c25fb-84d6-49ac-a593-5cafb24f769e", + "severity": "Info", + "ip": "203.0.113.77", + "email": "sam.smith@example.com", + "action": "Updated profile", + "description": "User updated profile details", + "userAgent": "node", + "createdAt": "2025-08-26T20:32:28.549Z", + "updatedAt": "2025-08-26T20:32:28.549Z", + "environmentName": "Global" + }, + { + "frontegg_id": "b44e2cc1-91ad-42cb-8f00-3c1d20a9d001", + "vendorId": "2dc00405-79cd-457b-b288-a119c6f0c7b7", + "tenantId": "854c25fb-84d6-49ac-a593-5cafb24f769e", + "severity": "Info", + "email": "admin@example.com", + "action": "Added user", + "description": "Added user john.roe@example.com to tenant", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36", + "createdAt": "2025-08-27T08:15:02.113Z", + "updatedAt": "2025-08-27T08:15:02.113Z", + "environmentName": "Global" + } + ], + "total": 5 + } + `}} + - path: /audits/resources/audits/v2 + methods: ['GET'] + query_params: + count: 2 + offset: 4 + created_from: "{createdFrom:20.*}" + request_headers: + Authorization: + - 'Bearer xxxx' + responses: + - status_code: 200 + headers: + Content-Type: + - 'application/json' + body: | + {{ minify_json ` + { + "data": [ + { + "frontegg_id": "c9a01f60-3d2b-49ce-9f14-88a5f2f60b42", + "vendorId": "2dc00405-79cd-457b-b288-a119c6f0c7b7", + "tenantId": "854c25fb-84d6-49ac-a593-5cafb24f769e", + "severity": "Info", + "ip": "198.51.100.201", + "email": "admin@example.com", + "action": "Removed user john.roe@example.com from account", + "description": "Removed user from the account", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36", + "createdAt": "2025-08-28T17:59:09.862Z", + "updatedAt": "2025-08-28T17:59:09.862Z", + "environmentName": "Global" + } + ], + "total": 5 + } + `}} - path: /v2/datastores methods: ['GET'] query_params: @@ -1977,4 +2112,4 @@ rules: } ] } - `}} \ No newline at end of file + `}} diff --git a/packages/cyera/changelog.yml b/packages/cyera/changelog.yml index aa01a3e15a3..acc0c6c3f46 100644 --- a/packages/cyera/changelog.yml +++ b/packages/cyera/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "0.9.0" + changes: + - description: Add support of Audit data stream. + type: enhancement + link: https://github.com/elastic/integrations/pull/20121 - version: "0.8.0" changes: - description: Update documentation with the new Cyera API token generation flow. diff --git a/packages/cyera/docs/README.md b/packages/cyera/docs/README.md index 9b155e15191..2b19cb61f30 100644 --- a/packages/cyera/docs/README.md +++ b/packages/cyera/docs/README.md @@ -16,10 +16,11 @@ This integration is compatible with different versions of Cyera APIs for respect | Issue | v3 | | Event | v1 | | Datastore | v2 | +| Audit | v2 | ### How it works -This integration periodically queries the Cyera API to retrieve classifications, issues, events and datastores. +This integration periodically queries the Cyera API to retrieve classifications, issues, events, datastores and audit logs. ## What data does this integration collect? @@ -33,8 +34,10 @@ This integration collects log messages of the following types: - `Datastore`: Collects all datastore objects from the Cyera system. +- `Audit`: Collects the platform audit trail (user logins, API key management, user and role management, and other administrative actions) from the Cyera system. + ### Supported use cases -Integrating Cyera Classification, Issues, Events and Datastore data streams with Elastic SIEM provides end-to-end visibility into where sensitive data resides, the risks tied to that data, and the security events triggered across cloud and SaaS environments. By correlating datastore metadata (such as type, provider, sensitivity, and ownership) with Cyera’s classification intelligence, issue context, and event activity in Elastic analytics, security teams can strengthen data security posture, accelerate incident response, and simplify compliance. Dashboards in Kibana present breakdowns by datastore type, sensitivity, category, severity, status, risk status, event type, and trends over time — enabling faster investigations, better prioritization, and improved accountability. +Integrating Cyera Classification, Issues, Events, Datastore and Audit data streams with Elastic SIEM provides end-to-end visibility into where sensitive data resides, the risks tied to that data, and the security events triggered across cloud and SaaS environments. By correlating datastore metadata (such as type, provider, sensitivity, and ownership) with Cyera’s classification intelligence, issue context, and event activity in Elastic analytics, security teams can strengthen data security posture, accelerate incident response, and simplify compliance. The audit trail adds accountability over the Cyera platform itself, surfacing who signed in, what was changed, and which credentials were created or removed. Dashboards in Kibana present breakdowns by datastore type, sensitivity, category, severity, status, risk status, event type, and trends over time — enabling faster investigations, better prioritization, and improved accountability. ## What do I need to use this integration? @@ -51,6 +54,7 @@ The integration authenticates to the Cyera API using a `Client ID` and `Client S - Cyera **Admin** role. - An active Cyera **DSPM** license. - Access to the partner integration page in the Cyera platform. +- For the Audit data stream: an API token generated by a user with the **Admin** role, and outbound HTTPS access to the Cyera audit API host (`https://auth.cyera.io` by default, configurable through the **Audit URL** setting). The audit trail is served from the Cyera authentication host, which is separate from the data API host. #### Obtain credentials @@ -93,6 +97,7 @@ Elastic Agent must be installed. For more details, check the Elastic Agent [inst - Configure **URL**, **Client ID**, and **Client Secret**. - Enable/Disable the required datasets. - For each dataset, adjust the integration configuration parameters if required, including the Initial Interval, Interval, Batch Size etc. to enable data collection. + - For the **Audit** dataset, confirm the **Audit URL** setting. It defaults to `https://auth.cyera.io`, the Cyera authentication host that serves the audit trail, and only needs to be changed if Cyera support has provided a different audit host for your tenant. Audit collection also requires the API token to have been generated by a user with the **Admin** role; tokens without it are rejected by the audit API. 6. Select **Save and continue** to save the integration. @@ -899,6 +904,127 @@ An example event for `event` looks as following: } ``` +### Audit + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| cyera.audit.environment_name | Name of the Cyera environment where the action was performed. | keyword | +| cyera.audit.tenant_id | Unique identifier of the tenant associated with the audit entry. | keyword | +| cyera.audit.updated_at | Date when the audit entry was last updated. | date | +| cyera.audit.vendor_id | Unique identifier of the vendor associated with the audit entry. | keyword | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| input.type | Type of Filebeat input. | keyword | +| log.offset | Log offset. | long | +| observer.product | The product name of the observer. | constant_keyword | +| observer.vendor | Vendor name of the observer. | constant_keyword | + + +#### Example event + +An example event for `audit` looks as following: + +```json +{ + "@timestamp": "2025-08-25T09:12:44.376Z", + "agent": { + "ephemeral_id": "4d042e27-9e10-4188-a583-9ba1a73c3286", + "id": "eaf789cf-7bdd-4ef2-8559-6472fa03e928", + "name": "elastic-agent-91976", + "type": "filebeat", + "version": "9.4.3" + }, + "cyera": { + "audit": { + "environment_name": "Global", + "tenant_id": "854c25fb-84d6-49ac-a593-5cafb24f769e", + "updated_at": "2025-08-25T09:12:44.376Z", + "vendor_id": "2dc00405-79cd-457b-b288-a119c6f0c7b7" + } + }, + "data_stream": { + "dataset": "cyera.audit", + "namespace": "20319", + "type": "logs" + }, + "ecs": { + "version": "8.17.0" + }, + "elastic_agent": { + "id": "eaf789cf-7bdd-4ef2-8559-6472fa03e928", + "snapshot": false, + "version": "9.4.3" + }, + "event": { + "action": "User logged in", + "agent_id_status": "verified", + "category": [ + "authentication", + "session" + ], + "dataset": "cyera.audit", + "id": "5324ccd7-c588-4683-962e-219eaaaed8da", + "ingested": "2026-07-15T06:19:50Z", + "kind": "event", + "module": "cyera", + "original": "{\"action\":\"User logged in\",\"createdAt\":\"2025-08-25T09:12:44.376Z\",\"description\":\"User logged in to the application\",\"email\":\"jane.doe@example.com\",\"environmentName\":\"Global\",\"frontegg_id\":\"5324ccd7-c588-4683-962e-219eaaaed8da\",\"ip\":\"203.0.113.10\",\"severity\":\"Info\",\"tenantId\":\"854c25fb-84d6-49ac-a593-5cafb24f769e\",\"updatedAt\":\"2025-08-25T09:12:44.376Z\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36\",\"vendorId\":\"2dc00405-79cd-457b-b288-a119c6f0c7b7\"}", + "outcome": "success", + "type": [ + "start" + ] + }, + "input": { + "type": "cel" + }, + "log": { + "level": "Info" + }, + "message": "User logged in to the application", + "observer": { + "product": "Cyera", + "vendor": "Cyera" + }, + "related": { + "ip": [ + "203.0.113.10" + ], + "user": [ + "jane.doe@example.com" + ] + }, + "source": { + "ip": "203.0.113.10" + }, + "tags": [ + "preserve_original_event", + "forwarded", + "cyera-audit" + ], + "user": { + "email": "jane.doe@example.com" + }, + "user_agent": { + "device": { + "name": "Mac" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36", + "os": { + "full": "Mac OS X 10.15.7", + "name": "Mac OS X", + "version": "10.15.7" + }, + "version": "148.0.0.0" + } +} +``` + ### Inputs used These inputs can be used in this integration: diff --git a/packages/cyera/manifest.yml b/packages/cyera/manifest.yml index 905e6483f2e..2037ef9c72b 100644 --- a/packages/cyera/manifest.yml +++ b/packages/cyera/manifest.yml @@ -1,7 +1,7 @@ format_version: 3.3.2 name: cyera title: Cyera -version: 0.8.0 +version: 0.9.0 description: Collect logs from Cyera with Elastic Agent. type: integration categories: diff --git a/packages/kolide/_dev/build/docs/README.md b/packages/kolide/_dev/build/docs/README.md index 9cc0994d1fd..58b5baec52f 100644 --- a/packages/kolide/_dev/build/docs/README.md +++ b/packages/kolide/_dev/build/docs/README.md @@ -1,47 +1,88 @@ {{- generatedHeader }} + # Kolide Integration for Elastic ## Overview -The Kolide integration for Elastic collects device-trust and endpoint-compliance logs from [Kolide](https://www.kolide.com/) (by 1Password). It ingests authentication sessions, posture issues, device inventory and trust-status changes, and administrative audit events, normalizes them to the Elastic Common Schema (ECS), and makes them available for search, visualization, and detection in Elastic. +The Kolide integration for Elastic collects device-trust and endpoint-compliance logs from Kolide (by 1Password). It ingests authentication sessions, posture issues, approval-workflow requests, device inventory, trust-status changes, people identity records, and administrative audit events. The integration normalizes these logs to the Elastic Common Schema (ECS) so you can use them for search, visualization, and detection in Elastic. ### Compatibility -This integration works with the current Kolide Device Trust platform ("Kolide K2") and its public REST API (version `2026-04-07`) and webhooks. It does not cover the legacy open-source Kolide Fleet (osquery) product. +This integration works with the current Kolide Device Trust platform ("Kolide K2"), its public REST API (version `2026-04-07`), and webhooks. It doesn't support the legacy open-source Kolide Fleet (osquery) product. + +This integration is compatible with Elastic Stack version 8.19.0 or later. ### How it works -The integration supports three collection methods that you can choose between (and combine) when configuring it: +The integration supports four collection methods that you can choose between and combine when you configure it: -- Webhooks (HTTP endpoint): Kolide pushes events in near real time to an HTTP endpoint exposed by the Elastic Agent. This is the recommended method for low-latency device-compliance data. Each delivery is signed with an HMAC-SHA256 signature for verification. -- REST API (polling): the Elastic Agent periodically polls the Kolide REST API and collects new records using cursor-based pagination and a timestamp filter. This is useful for backfill and for fuller resource records. -- AWS S3 (Kolide Log Pipeline): Kolide's Log Pipeline writes objects to a customer-owned S3 bucket under per-type key prefixes (defaults: `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`); the Elastic Agent reads each prefix with an `aws-s3` input (SQS notifications or direct bucket polling). The `auth` and `audit` data streams can read their respective prefixes, and the dedicated `device_check` data stream reads `kolide/check_runs/`. S3 is the most complete source for check-run history — it includes passing, inapplicable, and unknown check results in addition to failures. Raw osquery `results` objects are not ingested. +- Webhooks (HTTP endpoint): Kolide pushes events in near real time to an HTTP endpoint that Elastic Agent exposes. This is the recommended method for low-latency device-compliance data. Each delivery is signed with an HMAC-SHA256 signature for verification. +- REST API (polling): Elastic Agent periodically polls the Kolide REST API and collects records using cursor-based pagination and timestamp filters where supported. This is useful for backfill and for fuller resource records. +- AWS S3 (Kolide Log Pipeline): Kolide's Log Pipeline writes objects to a customer-owned S3 bucket under per-type key prefixes (default values are `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`, `kolide/results/`, and `kolide/status/`). Elastic Agent reads each prefix using an `aws-s3` input through SQS notifications or direct bucket polling. The `auth` and `audit` data streams can read their respective prefixes. The dedicated `device_check` data stream reads `kolide/check_runs/`, and the dedicated `osquery_result` and `osquery_status` data streams read `kolide/results/` and `kolide/status/`, which are the raw osquery result and status logs. The Log Pipeline is the most complete source for check-run history because it includes passing, inapplicable, and unknown check results in addition to failures. +- Google Cloud Storage (Kolide Log Pipeline): The same Log Pipeline data is written to customer-owned GCS buckets under the same per-type key prefixes and read using a `gcs` input through bucket polling. The object payloads are identical to the S3 delivery, so the same `auth`, `audit`, `device_check`, `osquery_result`, and `osquery_status` data streams apply. You can choose S3 or GCS depending on which cloud your Kolide log destination targets. ## What data does this integration collect? The Kolide integration collects the following data streams: -* `webhook`: single webhook ingress that receives all Kolide webhook event types on one endpoint and routes each event to the correct data stream automatically. -* `auth`: SSO authentication sessions (`auth_logs.success`, `auth_logs.failure`; API `GET /auth_logs`). -* `issues`: device posture-check failures and resolutions (`issues.new`, `issues.resolved`; API `GET /issues`). -* `device`: device inventory and trust-status changes (`devices.created`, `devices.registered`, `devices.destroyed`, `device_trust.status_changed`; API `GET /devices`). -* `audit`: administrative audit log of console actions (`audit_log.recorded`; API `GET /audit_logs`; Log Pipeline S3 `kolide/audit_logs/`). -* `device_check`: device check-run results from the Log Pipeline (S3 `kolide/check_runs/`), covering every run — `passing`, `failing`, `inapplicable`, and `unknown`. This complements the failure-focused `issues` data stream. +- `webhook`: A single webhook ingress that receives all Kolide webhook event types on one endpoint and routes each event to the correct data stream automatically. +- `auth`: SSO authentication sessions (`auth_logs.success` and `auth_logs.failure` using the API endpoint `GET /auth_logs`). +- `issues`: Device posture-check failures and resolutions (`issues.new` and `issues.resolved` using the API endpoint `GET /issues`). +- `request`: Approval-workflow requests (`requests.issue_exemption` and `requests.registration` using the API endpoints `GET /exemption_requests` and `GET /registration_requests`, as well as request webhooks). +- `device`: Device inventory and trust-status changes (`devices.created`, `devices.registered`, `devices.destroyed`, and `device_trust.status_changed` using the API endpoint `GET /devices`). +- `people`: Identity records for people known to Kolide using the API endpoint `GET /people`. +- `deprovisioned_person`: Identity records for people who have been offboarded or deprovisioned in Kolide using the API endpoint `GET /deprovisioned_people`. This is a separate resource from `people`. +- `audit`: Administrative audit logs of console actions (`audit_log.recorded` using the API endpoint `GET /audit_logs` or Log Pipeline S3/GCS paths under `kolide/audit_logs/`). +- `device_check`: Device check-run results from the Log Pipeline (S3/GCS paths under `kolide/check_runs/`), covering every run including `passing`, `failing`, `inapplicable`, and `unknown` statuses. This complements the failure-focused `issues` data stream. +- `osquery_result`: Raw osquery Result Logs from the Log Pipeline (S3/GCS paths under `kolide/results/`), covering both snapshot-query rows and differential (`added` and `removed`) rows. Per-query column data is stored as a flattened field rather than mapped per column, since it is arbitrary and depends on the target osquery table or custom SQL. +- `osquery_status`: Raw osquery Status Logs from the Log Pipeline (S3/GCS paths under `kolide/status/`), which contain GLOG-style telemetry about the osquery daemon itself rather than host inventory state. + +The `auth` and `audit` data streams also support the Log Pipeline using the `aws-s3` and `gcs` inputs that read the `kolide/auth_logs/` and `kolide/audit_logs/` prefixes. + +### Osquery result and status details + +The `osquery_result` and `osquery_status` data streams ingest raw osquery agent logs, unlike the other Log Pipeline streams in this integration (`auth`, `audit`, and `device_check`), which are Kolide's own structured logs. The integration populates `host.id` and `host.name` from Kolide's `kolide_decorations` block. This block is only present when the device is enrolled with Kolide's own launcher. A bare open-source osquery deployment shipping logs through the Log Pipeline only carries osquery's own `hostIdentifier` (stored in `kolide.osquery_result.host_identifier` and `kolide.osquery_status.host_identifier`), and `host.id` and `host.name` do not populate. Per-query row data (`kolide.osquery_result.added`, `kolide.osquery_result.removed`, and `kolide.osquery_result.snapshot`) is a `flattened` field rather than a per-column mapping, since the columns are arbitrary and depend on the target osquery table or custom SQL. This keeps the mapping bounded, but means individual columns do not get native Kibana Lens numeric or date typing, or exact-match aggregations. + +### Event outcome for posture data + +For the `device_check` and `issues` data streams, `event.outcome` reflects the device posture result rather than the success of event processing. A check run with status `passing` (or a resolved issue) maps to `event.outcome: success`. A check run with status `failing` (or an open issue) maps to `event.outcome: failure`. An `inapplicable` or `unknown` check status maps to `event.outcome: unknown`. The integration preserves the raw posture state in `kolide.device_check.status` for `device_check`. + +### Host correlation for device checks + +Check-run results identify the device only by its numeric Kolide device ID, which maps to `host.id`. The payload carries no hostname, so the integration does not set `host.name` on this data stream. You can correlate check runs with the `device`, `auth`, and `issues` data streams using the shared `host.id`. If you need `host.name` directly on check-run documents, you must enrich them at ingest time with an Elasticsearch [enrich policy](https://www.elastic.co/docs/manage-data/ingest/transform-enrich/data-enrichment) that maps `host.id` to `host.name` from the `device` data stream. This setup requires you to enable the `device` data stream and periodically refresh the enrich policy so new or renamed devices resolve correctly. + +### Document identity for requests -The `auth` and `audit` data streams additionally support the Log Pipeline via an `aws-s3` input that reads the `kolide/auth_logs/` and `kolide/audit_logs/` prefixes. +The Kolide REST API endpoints `GET /exemption_requests` and `GET /registration_requests` do not support a modified-since filter, so the integration re-fetches every request on every poll. To prevent duplicate indexing of unchanged requests, the integration deduplicates documents using the request identity (a combination of `kolide.request.id` and `kolide.request.type`), its current status, and decision notes. This means the `request` data stream reflects each request's latest known status. It provides one document per request that is updated as its status changes, rather than a full history of every transition. Kolide allows reopening a previously approved or denied request, meaning a request can cycle through the same status multiple times. If a request is re-decided with the exact same status and decision note text as a previous decision, the integration deduplicates it as a duplicate event. To view the full timeline of who approved, denied, or reopened a request, use the `audit` data stream (`audit_log.recorded`), and correlate the events using `user.target.email` and `rule.name`. -> **Note on `event.outcome` for posture data:** For the `device_check` and `issues` data streams, `event.outcome` reflects the device posture result, not the success of event processing. A check run with status `passing` (or a resolved issue) maps to `event.outcome: success`, `failing` (or an open issue) maps to `event.outcome: failure`, and `inapplicable` or `unknown` check statuses map to `event.outcome: unknown`. The raw posture state is also preserved in `kolide.device_check.status` for `device_check`. +### Document identity for people -> **Note on host correlation for `device_check`:** Check-run results identify the device only by its numeric Kolide device ID, mapped to `host.id`. The payload carries no hostname, so `host.name` is not set on this data stream. Correlate check runs with the `device`, `auth`, and `issues` data streams using the shared `host.id`. If you need `host.name` directly on check-run documents, enrich them at ingest time with an Elasticsearch [enrich policy](https://www.elastic.co/docs/manage-data/ingest/transform-enrich/data-enrichment) that maps `host.id` to `host.name` from the `device` data stream. This requires the `device` data stream to be enabled and the enrich policy to be executed and periodically refreshed so new or renamed devices resolve. +The endpoint `GET /people` returns a full-table snapshot with no modified-since filter, so the integration re-fetches every person on every poll. To prevent unnecessary indexing, the integration deduplicates documents using a fingerprint of the entire raw record, excluding `last_authenticated_at`. This exclusion prevents a new document from being created every time an active person authenticates. A change to any other field (such as name, email, registered-device status, or SCIM usernames) produces a new document, while unchanged records are deduplicated across polls. ### Supported use cases -Monitoring device-trust posture, investigating SSO authentication outcomes alongside device compliance state, tracking device enrollment and blocking transitions, and auditing administrative changes in Kolide — all correlated with the rest of your security data in Elastic via ECS. +Integrating Kolide with Elastic provides a powerful solution for enhancing security posture and operational visibility. You can use this integration for the following use cases: + +- Monitor device-trust posture and investigate SSO authentication outcomes alongside device compliance state. +- Track approval workflows, device enrollment, and blocking transitions. +- Correlate device activity with identity records of people. +- Audit administrative changes in Kolide. +- Correlate your Kolide device trust data with the rest of your security data in Elastic using the Elastic Common Schema (ECS). ## What do I need to use this integration? -- Elastic Agent installed on a host that can receive Kolide webhooks (a publicly reachable HTTPS endpoint), reach `https://api.kolide.com`, or read from your AWS S3 bucket or SQS queue. +Before you set up the Kolide integration, you must have the following: - A Kolide tenant with Full Access administrator privileges to create API keys, webhook endpoints, or Log Pipeline destinations. +- An Elastic Agent installed on a host. Depending on your chosen ingestion method, the host must meet the following network requirements: + - Receive Kolide webhooks on a publicly reachable HTTPS endpoint. + - Reach the Kolide REST API at `https://api.kolide.com`. + - Access your AWS S3 bucket or Amazon Simple Queue Service (SQS) queue. + - Access your Google Cloud Storage (GCS) bucket. + +If you're collecting data using the REST API or the Log Pipeline, you must also configure the following resources: +- A Kolide API key with the form `k2sk_v1_` created in your Kolide console under Settings → Developers → API Keys. +- An AWS Identity and Access Management (IAM) role or credentials with permissions to read from your AWS S3 bucket or SQS queue, if you use AWS. +- A Google Cloud Platform (GCP) service account JSON key with the Storage Object Viewer role to read from your GCS bucket, if you use GCP. ## How do I deploy this integration? @@ -49,51 +90,159 @@ Monitoring device-trust posture, investigating SSO authentication outcomes along Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html). You can install only one Elastic Agent per host. +Elastic Agent is required to receive webhook requests, poll the REST API, or read from S3 or GCS buckets and ship the data to Elastic, where the events will then be processed using the integration's ingest pipelines. + +### Agentless deployment + +Agentless deployments are only supported in Elastic Serverless and Elastic Cloud environments. Agentless deployments provide a means to ingest data while avoiding the orchestration, management, and maintenance needs associated with standard ingest infrastructure. Using an agentless deployment makes manual agent deployment unnecessary, allowing you to focus on your data instead of the agent that collects it. + +For more information, refer to [Agentless integrations](https://www.elastic.co/guide/en/serverless/current/security-agentless-integrations.html) and [Agentless integrations FAQ](https://www.elastic.co/guide/en/serverless/current/agentless-integration-troubleshooting.html). + ### Set up steps in Kolide -As a Full Access administrator, sign in to Kolide and choose one or more collection methods: +To set up steps in Kolide, you must have full access administrator privileges. Sign in to Kolide and choose one or more of the collection methods below. + +#### Webhooks setup + +To configure Kolide webhooks, complete the following steps: +1. Log in to your Kolide account and navigate to Settings, then Developers, and then Webhooks. +2. Select Add Webhook and create one new endpoint. +3. Provide a publicly reachable HTTPS URL pointing at the Elastic Agent listen address, port, and path, such as `https://:9550/kolide/webhook` (replace `` with the actual address or hostname of your Elastic Agent). +4. Subscribe the endpoint to all event types. The integration automatically routes each event to the correct data stream. +5. Copy the signing secret displayed on screen. This secret is shown only once and is required to configure the HMAC key on the Elastic side. + +#### REST API setup -For webhooks: -1. Go to Settings → Developers → Webhooks and add **one** new endpoint. -2. Provide a publicly reachable HTTPS URL pointing at the Elastic Agent's listening address, port, and path (for example, `https://:9550/kolide/webhook`). -3. Subscribe the endpoint to **all** event types — the integration routes each event to the correct data stream automatically. -4. Copy the endpoint signing secret (shown once) — you will provide it to the integration as the HMAC key. +To configure the REST API, complete the following steps: +1. Log in to your Kolide account and navigate to Settings, then Developers, and then API Keys. +2. Select Create API Key. Read access is sufficient to retrieve logs. +3. Copy the API key. It is displayed only once and has the form `k2sk_v1_` followed by your token. -For the REST API: -1. Go to Settings → Developers → API Keys and create a new key (read access is sufficient). -2. Copy the API key (shown once); it has the form `k2sk_v1_...`. +#### AWS S3 log pipeline setup -For the AWS S3 Log Pipeline: -1. In Kolide, go to Log Destinations and add a new Amazon S3 Bucket destination. -2. Choose STS (recommended): create an IAM role in your own AWS account whose trust policy allows Kolide's AWS account (`516897320088`) to assume it, gated by the External ID that Kolide displays. Grant the role `s3:GetBucketLocation`, `s3:GetObject`, and `s3:PutObject` on the bucket so Kolide can write logs. -3. Select the log types to deliver (authentication logs, audit logs, and check results) and, optionally, customize the object key template. -4. On the read side, the Elastic Agent uses your own AWS credentials (not Kolide's role). For SQS mode, configure an S3 event notification (`s3:ObjectCreated:*`) to an SQS queue and grant the reader `s3:GetObject` plus `sqs:ReceiveMessage`, `sqs:DeleteMessage`, and `sqs:GetQueueAttributes`. For direct polling, grant `s3:GetObject` and `s3:ListBucket`. Add `kms:Decrypt` if the bucket uses SSE-KMS. +To configure the AWS S3 log pipeline, complete the following steps: +1. In Kolide, navigate to Log Destinations and select Amazon S3 Bucket to add a new destination. +2. Select the STS authorization method, which is the recommended approach. +3. Create an IAM role in your AWS account. Update the trust policy to allow Kolide's AWS account ID `516897320088` to assume the role, and restrict access using the External ID displayed in the Kolide console. +4. Grant the IAM role permissions for `s3:GetBucketLocation`, `s3:GetObject`, and `s3:PutObject` on your S3 bucket so Kolide can write logs. +5. Select the log types you want to deliver. The supported log types include authentication logs, audit logs, check results, and osquery Result or Status logs. +6. Configure the read permissions. The Elastic Agent reads the logs from your AWS S3 bucket and does not use Kolide's IAM role. You must configure the Elastic Agent with AWS credentials that have read access. +7. For SQS notification mode, configure an S3 event notification for `s3:ObjectCreated:*` to deliver notifications to your SQS queue. Grant your Elastic Agent IAM reader credentials the permissions for `s3:GetObject` on the bucket and `sqs:ReceiveMessage`, `sqs:DeleteMessage`, and `sqs:GetQueueAttributes` on the SQS queue. +8. For direct polling mode, grant your Elastic Agent IAM reader credentials the permissions for `s3:GetObject` and `s3:ListBucket` on the bucket. +9. If your bucket is encrypted using SSE-KMS, ensure the Elastic Agent IAM reader credentials also have `kms:Decrypt` permissions on the KMS key. -Note: Kolide sends webhooks from dynamic AWS us-east-1 IP addresses, so IP allow-listing is not a reliable control — rely on the HMAC signature instead. +#### Google Cloud Storage log pipeline setup + +To configure the Google Cloud Storage log pipeline, complete the following steps: +1. Log in to your Google Cloud Console, select your project, and create a GCS bucket. +2. Create a service account that can enumerate, read, and write objects in the bucket by granting it the Storage Object Admin role on the bucket, then generate a JSON key for this service account. +3. Log in to Kolide, navigate to Log Destinations, select GCP Storage Bucket, and enter a display name and the bucket name. +4. Paste the complete service account JSON key file contents into the field provided. +5. Select the log types to deliver. This integration supports Administrator Audit Logs, User Authentication Logs, Device Check Run Logs, and osquery Result and Status Logs. Keep the default object path templates because they match the integration's default file selectors. +6. Create a separate service account with read-only access (the Storage Object Viewer role) and generate a JSON key for it. The Elastic Agent uses this key to poll the bucket. Alternatively, if the Elastic Agent runs on a GCE or GKE instance, you can leave the credentials blank to use Application Default Credentials. #### Vendor resources + +The following resources provide additional information about setting up Kolide integrations: - [Kolide Webhooks documentation](https://www.kolide.com/docs/developers/webhooks) - [Kolide REST API reference](https://kolideapi.readme.io/reference) - [Kolide Log Pipeline documentation](https://www.kolide.com/docs/admins/log-pipeline/overview) +- [Configuring Google Cloud Storage for the Log Pipeline](https://www.kolide.com/docs/using-kolide/log-pipeline/configuring-google-cloud-storage) ### Set up steps in Kibana -1. In Kibana, go to Management → Integrations and search for Kolide. -2. Add the integration. -3. For webhooks: enable the `webhook` data stream (HTTP endpoint input). Set the listen address, port, and URL path, and provide the HMAC signing secret (and optionally the `X-Kolide-Webhook-Identifier` value). All Kolide event types are received on this single endpoint and routed automatically. -4. For the REST API: enable whichever data streams you want to poll (auth, issues, device, audit), select the CEL input, provide the API URL (`https://api.kolide.com`), the API key, and adjust the polling interval and initial lookback as needed. -5. For AWS S3 (Log Pipeline): provide your AWS credentials once on the integration, then enable the `aws-s3` input on the data streams you want — `auth`, `audit`, or `device_check`. Each defaults to its Kolide prefix (`kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`). For each, set either an SQS queue URL (SQS mode) or a bucket ARN (polling mode). In SQS mode, use a separate queue per prefix (filter S3 notifications by prefix); in polling mode each stream lists only its own prefix. Adjust the bucket list prefix if your Kolide destination uses a custom key template. +To set up the Kolide integration in Kibana, complete the following steps: +1. In Kibana, navigate to Management, select Integrations, and search for Kolide. +2. Select the Kolide integration, and click Add Kolide. +3. Configure the settings based on your chosen collection methods. You can enable and configure webhooks, the REST API, or log pipeline inputs. + +#### Webhooks configuration + +Configure the following settings to receive webhook events: + +| Setting | Description | +| ----------------------- | --------------------------------------------------------------------------------------------- | +| Listen Address | Bind address for the HTTP listener. Use `0.0.0.0` to listen on all interfaces. | +| Listen Port | Bind port for the HTTP listener, such as `9550`. | +| URL Path | The URL path to accept Kolide webhook requests on, such as `/kolide/webhook`. | +| Webhook Signing Secret | The signing secret copied from the Kolide webhook settings. Used to verify HMAC signatures. | +| Webhook Identifier | The webhook endpoint identifier value from the Kolide webhook settings. | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | + +#### REST API configuration + +Configure the following settings to pull logs from the Kolide REST API: + +| Setting | Description | +| ----------------------- | --------------------------------------------------------------------------------------------- | +| URL | The base URL of the Kolide REST API. The default is `https://api.kolide.com`. | +| API Key | The Kolide API key used as a Bearer token. This key has the form `k2sk_v1_`. | +| Interval | How often the Kolide REST API is polled, such as `5m` (5 minutes). | +| Initial Interval | How far back to look the first time the integration runs, such as `24h` (24 hours). | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | + +#### AWS S3 log pipeline configuration + +Configure the following settings to collect logs from AWS S3: + +| Setting | Description | +| ----------------------- | ----------------------------------------------------------------------------------------------------------- | +| Access Key ID | The AWS access key ID the Elastic Agent uses to read from the bucket or queue. | +| Secret Access Key | The AWS secret access key the Elastic Agent uses to read from the bucket or queue. | +| Session Token | The AWS session token for temporary credentials, if using STS. | +| SQS Queue URL | URL of the SQS queue receiving S3 object-created notifications. | +| S3 Bucket ARN | ARN of the S3 bucket to poll directly if not using SQS notifications, such as `arn:aws:s3:::kolide-bucket`. | +| Bucket List Prefix | Prefix used to list objects in the bucket, such as `kolide/audit_logs/`. | +| Number of Workers | Number of workers that process the S3 objects or SQS messages. | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | + +#### Google Cloud Storage log pipeline configuration + +Configure the following settings to collect logs from Google Cloud Storage: + +| Setting | Description | +| ----------------------- | --------------------------------------------------------------------------------------------- | +| Project ID | The GCP project ID that the GCS bucket belongs to. | +| Service Account Key | The GCP service account JSON key contents with Storage Object Viewer read access. | +| GCS Buckets | The list of GCS buckets to poll in YAML format, specifying the bucket name. | +| File Selectors | A list of regular expression patterns to filter which object keys are processed. | +| Number of Workers | Number of workers that process the GCS objects. | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | ### Validation -After setup, generate or wait for activity in Kolide (for example, sign in via SSO to produce an auth log). In Kibana, open Discover and confirm documents are arriving in the `logs-kolide.*` data streams. +To validate that the integration is working properly and ingesting data into Elasticsearch, perform the following steps: +1. Generate activity in Kolide, such as logging in via Single Sign-On (SSO) to trigger an authentication event, or running a manual device check. +2. In Kibana, navigate to Discover. +3. In the data view dropdown, select logs-*. +4. Search for incoming documents using the search query: + ```kql + data_stream.dataset: "kolide.webhook" or data_stream.dataset: "kolide.audit" or data_stream.dataset: "kolide.auth" + ``` +5. Verify that documents appear with recent timestamps and contains expected event values. +6. Navigate to Dashboards and select the [Logs Kolide] Overview dashboard to confirm that the visualizations are successfully populated with data. ## Troubleshooting -- No data via webhooks: Confirm the Kolide endpoint URL matches the Agent's listen address, port, and path, that the endpoint is publicly reachable over HTTPS, and that the HMAC signing secret matches. -- Webhook signature failures: Ensure the configured HMAC key equals the Kolide endpoint signing secret; Kolide signs the raw request body with HMAC-SHA256 and sends the lowercase hex digest in the `Authorization` header with no prefix. -- No data via the REST API: Verify the API key is valid (a 401 indicates a turned-off feature or bad token, and a 403 indicates the key lacks permission) and that the host can reach `https://api.kolide.com`. -- No data via AWS S3: Confirm the Elastic Agent credentials can `s3:ListBucket` and `s3:GetObject` on the bucket (and `sqs:ReceiveMessage` in SQS mode), that the bucket list prefix matches your Kolide object key template, and that SQS notifications are filtered to the correct prefix. Kolide writes to `kolide/auth_logs/`, `kolide/audit_logs/`, and `kolide/check_runs/` by default; osquery `results/` objects are not ingested. +For help with Elastic ingest tools, check [Common problems](https://www.elastic.co/docs/troubleshoot/ingest/fleet/common-problems). + +### Common configuration issues + +If you encounter issues with your Kolide integration, use the following solutions to resolve them: + +- No data from webhooks: Confirm the Kolide endpoint URL matches the Agent's listen address, port, and path. Verify that the endpoint is publicly reachable over HTTPS and that the HMAC signing secret matches. +- Webhook signature failures: Ensure the configured HMAC key matches the Kolide endpoint signing secret. Kolide signs the raw request body with HMAC-SHA256 and sends the lowercase hex digest in the `Authorization` header with no prefix. +- No data using the REST API: Verify the API key is valid. A 401 error code indicates a disabled feature or bad token, and a 403 error code indicates the key lacks permission. Confirm that the host can reach `https://api.kolide.com`. +- No data from AWS S3: Confirm the Elastic Agent credentials have permissions to run `s3:ListBucket` and `s3:GetObject` on the bucket. If you're using SQS mode, ensure the credentials have permissions for `sqs:ReceiveMessage`. Check that the bucket list prefix matches your Kolide object key template, and verify that SQS notifications are filtered to the correct prefix. Kolide writes to `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`, `kolide/results/`, and `kolide/status/` by default. +- No data from Google Cloud Storage: Confirm the project ID and bucket name are correct. Ensure that the reader service account has the `Storage Object Viewer` role on the bucket. Verify that each stream's file selector regex matches your Kolide object key template. By default, the templates expect the `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`, `kolide/results/`, and `kolide/status/` prefixes. +- No host ID or host name on osquery result or osquery status documents: These fields are populated from Kolide's `kolide_decorations` block, which requires the device to be enrolled with Kolide's own launcher. A bare open-source osquery deployment shipping logs through the Log Pipeline only carries `kolide.osquery_result.host_identifier` or `kolide.osquery_status.host_identifier` (osquery's own `hostIdentifier`), not the Kolide-decorated host fields. + +### Vendor resources + +For more details on configuring Kolide, check the following resources: + +- [Kolide Developer API Documentation](https://developer.kolide.com) +- [Kolide Log Pipeline Documentation](https://k2.kolide.com/x/features/log-pipeline) ## Performance and scaling @@ -101,29 +250,37 @@ For more information on architectures that can be used for scaling this integrat ### Choosing a transport per data stream -Kolide's Log Pipeline writes one log per S3 object rather than batching, so the AWS S3/SQS input makes a separate fetch for every document. For high-volume streams this is fine, but for small, sparse streams it adds many network round-trips and can make large backlogs slow to drain. To keep latency low and avoid contention on a shared S3 queue, consider matching the transport to the stream: +Kolide's Log Pipeline writes one log per object rather than batching, so the AWS S3/SQS and GCS inputs make a separate fetch for every document. For high-volume streams this is fine, but for small, sparse streams it adds many network round-trips and can make large backlogs slow to drain. To keep latency low and avoid contention on a shared S3 queue, you can match the transport to the stream. -- **`audit` and `auth`**: prefer the REST API (CEL) or webhook inputs. These streams are typically small and sparse, and the API/webhook paths deliver them quickly without per-object S3 fetches. -- **`device_check` (check runs)**: use the AWS S3 input. This stream is large, so S3 is the better fit, and keeping it on S3 keeps the small, important streams off the same queue. +To optimize your ingestion, configure the transports using these guidelines: +- For `audit` and `auth` data streams, prefer the REST API (CEL) or webhook inputs. These streams are typically small and sparse, and the API or webhook paths deliver them quickly without per-object fetches. +- For `device_check`, `osquery_result`, and `osquery_status` data streams, use the AWS S3 or GCS input because they're the only collection methods available. These streams are typically large or high-volume. The `osquery_result` stream is especially large because every scheduled query execution can produce a log line, making object storage the appropriate fit. Keeping them in object storage also keeps the small, important streams off the same queue. -This split keeps the small streams responsive while still using S3 for the bulk data. +This split keeps the small streams responsive while still using object storage for the bulk data. -If you do consume large streams over S3/SQS, you can increase throughput by running multiple Elastic Agents (or scaling out workers) so SQS messages are processed concurrently. Note the one-object-per-log behavior is a Kolide-side limitation. The guidance above is a workaround until it is addressed upstream. +If you consume large streams over S3/SQS or GCS, you can increase throughput by running multiple Elastic Agents or scaling out workers to process objects concurrently. The one-object-per-log behavior is a Kolide-side limitation. This guidance is a workaround until Kolide addresses the issue upstream. ## Reference ### Inputs used + {{ inputDocs }} ### API usage -These Kolide REST API endpoints are used by this integration: -* `GET /auth_logs` -* `GET /issues` -* `GET /devices` -* `GET /audit_logs` +The integration uses the following Kolide REST API endpoints to retrieve logs and telemetry: +- `GET /auth_logs` +- `GET /issues` +- `GET /exemption_requests` +- `GET /registration_requests` +- `GET /devices` +- `GET /people` +- `GET /deprovisioned_people` +- `GET /audit_logs` ### Vendor documentation links + +You can refer to the following vendor documentation for more details about Kolide features and APIs: - [Kolide documentation](https://www.kolide.com/docs) - [Kolide Webhooks](https://www.kolide.com/docs/developers/webhooks) - [Kolide REST API reference](https://kolideapi.readme.io/reference) @@ -131,9 +288,11 @@ These Kolide REST API endpoints are used by this integration: ### Data streams +This integration uses these data streams to organize collected logs and metrics: + #### webhook -The `webhook` data stream is the single ingress point for all Kolide webhook events. It listens on one HTTP endpoint and uses the ingest `reroute` processor to redirect each event to the appropriate target data stream (`auth`, `issues`, `device`, or `audit`) based on the Kolide event type. No documents are stored in the `webhook` data stream itself. +The `webhook` data stream is the single ingress point for all Kolide webhook events. It listens on one HTTP endpoint and uses the ingest `reroute` processor to redirect each event to the appropriate target data stream, such as `auth`, `issues`, `device`, or `audit`, based on the Kolide event type. No documents are stored in the `webhook` data stream itself. ##### webhook fields @@ -141,7 +300,7 @@ The `webhook` data stream is the single ingress point for all Kolide webhook eve #### auth -The `auth` data stream provides Kolide SSO authentication sessions, including the device-trust posture at sign-in, the client IP and geolocation, and the sub-events of the session. +The `auth` data stream provides Kolide SSO authentication sessions. This includes the device-trust posture at sign-in, the client IP address and geolocation, and the sub-events of the session. ##### auth fields @@ -163,9 +322,21 @@ The `issues` data stream provides Kolide posture-check failures and resolutions {{ event "issues" }} +#### request + +The `request` data stream collects approval-workflow requests from the Kolide REST API using the `GET /exemption_requests` and `GET /registration_requests` endpoints, as well as request webhooks. The logs from these endpoints are normalized into a single data stream with `kolide.request.type` set to either `exemption` or `registration`. + +##### request fields + +{{ fields "request" }} + +##### request sample event + +{{ event "request" }} + #### device -The `device` data stream provides Kolide device inventory records and device-trust status changes. +The `device` data stream provides Kolide device inventory records and device-trust status changes. Because the `GET /devices` endpoint does not expose a modified-since cursor, each interval retrieves the complete collection. The ingest pipeline assigns a content-based document `_id` so unchanged devices are deduplicated across polls, while any change is captured as a new document. ##### device fields @@ -175,9 +346,35 @@ The `device` data stream provides Kolide device inventory records and device-tru {{ event "device" }} +#### people + +The `people` data stream provides Kolide identity records for active people using the `GET /people` endpoint. This includes Elastic Common Schema (ECS) user fields, SCIM-imported usernames, last-authentication time, and device-registration flags that Kolide exposes on this resource. Group, identity provider (IdP), SCIM, and deprovisioning details live on separate Kolide API resources like `person_groups` and `deprovisioned_people` that this data stream does not collect. Because the `GET /people` endpoint does not expose a modified-since cursor, each interval retrieves the complete collection. The ingest pipeline derives a content-fingerprint document `_id`, excluding `last_authenticated_at`, so byte-identical records are deduplicated across polls; records whose tracked fields change between polls are indexed as new documents rather than overwriting the prior one. + +##### people fields + +{{ fields "people" }} + +##### people sample event + +{{ event "people" }} + +#### deprovisioned_person + +The `deprovisioned_person` data stream provides Kolide identity records for people who have been offboarded or deprovisioned using the `GET /deprovisioned_people` endpoint. This is a separate API resource from `people` rather than a field on the person object. You can use this data stream to detect lingering access or devices owned by departed identities. Unlike the `people` data stream, this resource does not return SCIM usernames, but it includes an `api_url` field that links back to the corresponding `GET /people/{id}` resource. + +Because the `GET /deprovisioned_people` endpoint does not expose a modified-since cursor, each interval collects the complete collection. This full collection retrieval is intentional because an incremental approach cannot detect when records disappear from the list, for example when a user is re-provisioned, when a Kolide-side correction is made, or when records are missed because of pagination drift. The ingest pipeline derives a content-fingerprint document `_id`, excluding `last_authenticated_at`, so duplicate records are deduplicated across polls. Records with tracked fields that change between polls are indexed as new documents. + +##### deprovisioned_person fields + +{{ fields "deprovisioned_person" }} + +##### deprovisioned_person sample event + +{{ event "deprovisioned_person" }} + #### audit -The `audit` data stream provides the Kolide administrative audit log of console actions. +The `audit` data stream provides the Kolide administrative audit log of console actions using the `GET /audit_logs` endpoint. ##### audit fields @@ -189,7 +386,11 @@ The `audit` data stream provides the Kolide administrative audit log of console #### device_check -The `device_check` data stream provides Kolide device check-run results delivered through the Log Pipeline (S3). Unlike the `issues` data stream, which tracks the failure lifecycle, this stream records every check run — `passing`, `failing`, `inapplicable`, and `unknown`. +The `device_check` data stream provides Kolide device check-run results delivered through the Kolide Log Pipeline using an Amazon S3 bucket. You can configure this using Amazon SQS notifications or direct bucket polling. Unlike the `issues` data stream, which tracks the failure lifecycle, this stream records every check run, including these check statuses: +- `passing` +- `failing` +- `inapplicable` +- `unknown` ##### device_check fields @@ -199,6 +400,30 @@ The `device_check` data stream provides Kolide device check-run results delivere {{ event "device_check" }} +#### osquery_result + +The `osquery_result` data stream provides raw osquery Result Logs delivered through the Kolide Log Pipeline using Amazon S3 or Google Cloud Storage under the `kolide/results/` prefix. This includes both snapshot-query rows and differential (`added` and `removed`) rows. Per-query column data in `kolide.osquery_result.added`, `kolide.osquery_result.removed`, or `kolide.osquery_result.snapshot` is arbitrary and depends on the target osquery table or custom SQL, so it is stored as a flattened field rather than mapped per column. + +##### osquery_result fields + +{{ fields "osquery_result" }} + +##### osquery_result sample event + +{{ event "osquery_result" }} + +#### osquery_status + +The `osquery_status` data stream provides raw osquery Status Logs, which contain GLOG-style telemetry about the osquery daemon itself, delivered through the Kolide Log Pipeline using Amazon S3 or Google Cloud Storage under the `kolide/status/` prefix. + +##### osquery_status fields + +{{ fields "osquery_status" }} + +##### osquery_status sample event + +{{ event "osquery_status" }} + {{ ilm }} {{ transform }} diff --git a/packages/kolide/changelog.yml b/packages/kolide/changelog.yml index ac84707ed68..4a638d09398 100644 --- a/packages/kolide/changelog.yml +++ b/packages/kolide/changelog.yml @@ -1,4 +1,12 @@ # later versions go on top +- version: "0.2.0" + changes: + - description: Add GCS input support, new deprovisioned_person, osquery_status, osquery_result, people, and request data streams, and webhook routing updates. + type: enhancement + link: https://github.com/elastic/integrations/pull/20108 + - description: Fix fetching events based on resolved_at, blocked and blocks_device_at fields in the issues pipeline. Update deduplication logic and @timestamp derivation. + type: bugfix + link: https://github.com/elastic/integrations/pull/20108 - version: "0.1.2" changes: - description: Standardize HTTP Endpoint capitalization in README file diff --git a/packages/kolide/data_stream/audit/_dev/deploy/docker/docker-compose.yml b/packages/kolide/data_stream/audit/_dev/deploy/docker/docker-compose.yml index 4d336caeaa3..c8956852012 100644 --- a/packages/kolide/data_stream/audit/_dev/deploy/docker/docker-compose.yml +++ b/packages/kolide/data_stream/audit/_dev/deploy/docker/docker-compose.yml @@ -13,3 +13,15 @@ services: - http-server - --addr=:8090 - --config=/files/config-audit.yml + gcs-mock: + image: shourieg/gcs-mock-service:latest + ports: + - "4443/tcp" + volumes: + - ./files/gcs-manifest.yml:/app/manifest.yml:ro + - ./files/gcs:/data:ro + healthcheck: + test: "wget --no-verbose --tries=1 --spider http://localhost:4443/health || exit 1" + interval: 10s + timeout: 5s + command: ["./gcs-mock-service", "--manifest", "/app/manifest.yml"] diff --git a/packages/kolide/data_stream/audit/agent/stream/aws-s3.yml.hbs b/packages/kolide/data_stream/audit/agent/stream/aws-s3.yml.hbs index 220a84c4d1b..2b9effbc5c3 100644 --- a/packages/kolide/data_stream/audit/agent/stream/aws-s3.yml.hbs +++ b/packages/kolide/data_stream/audit/agent/stream/aws-s3.yml.hbs @@ -89,6 +89,9 @@ credential_profile_name: {{credential_profile_name}} {{#if shared_credential_file}} shared_credential_file: {{shared_credential_file}} {{/if}} +{{#if region}} +region: {{region}} +{{/if}} {{#if endpoint}} endpoint: {{endpoint}} {{/if}} diff --git a/packages/kolide/data_stream/audit/elasticsearch/ingest_pipeline/default.yml b/packages/kolide/data_stream/audit/elasticsearch/ingest_pipeline/default.yml index fc6f857ad41..b44c953381d 100644 --- a/packages/kolide/data_stream/audit/elasticsearch/ingest_pipeline/default.yml +++ b/packages/kolide/data_stream/audit/elasticsearch/ingest_pipeline/default.yml @@ -69,15 +69,15 @@ processors: if: ctx.json == null && ctx.event?.original != null description: Decode the CEL message (a JSON string of one audit_log object) into the working json object. - # --- S3 (Log Pipeline) input only --- - # aws-s3 deliveries carry the envelope {type, timestamp, data}. Lift `data` up - # to json.* and map the flat actor/IP fields the API path expects nested / from - # the webhook branch. + # --- S3/GCS (Log Pipeline) input only --- + # Both aws-s3 and gcs deliveries carry the envelope {type, timestamp, data}. + # Lift `data` up to json.* and map the flat actor/IP fields the API path + # expects nested / from the webhook branch. - pipeline: name: '{{ IngestPipeline "s3" }}' tag: dispatch_s3 if: ctx.json?.type == 'audit_log' - # --- end S3-only --- + # --- end S3/GCS-only --- # Common normalization: @timestamp and event.id from the audit_log object. - date: @@ -234,9 +234,9 @@ processors: method: SHA-256 tag: fingerprint_event_id if: ctx.event?.id != null && ctx.event.id != '' - # S3 (Log Pipeline) audit deliveries carry no id field, so event.id is unset. - # Fingerprint the raw object instead, so a re-delivered S3 object (aws-s3 is - # at-least-once) deduplicates to the same _id. + # S3/GCS (Log Pipeline) audit deliveries carry no id field, so event.id is + # unset. Fingerprint the raw object instead, so a re-delivered S3/GCS object + # (both inputs are at-least-once) deduplicates to the same _id. - fingerprint: fields: - event.original diff --git a/packages/kolide/data_stream/audit/fields/agent.yml b/packages/kolide/data_stream/audit/fields/agent.yml index adac4241805..18fe7012378 100644 --- a/packages/kolide/data_stream/audit/fields/agent.yml +++ b/packages/kolide/data_stream/audit/fields/agent.yml @@ -17,3 +17,22 @@ - name: key type: keyword description: The AWS S3 object key. +- name: gcs.storage + type: group + description: Metadata added by the GCS input for objects collected from the Kolide Log Pipeline bucket. + fields: + - name: bucket + type: group + fields: + - name: name + type: keyword + description: The GCS bucket name. + - name: object + type: group + fields: + - name: name + type: keyword + description: The GCS object name. + - name: content_type + type: keyword + description: The content type of the GCS object. diff --git a/packages/kolide/data_stream/audit/fields/base-fields.yml b/packages/kolide/data_stream/audit/fields/base-fields.yml index b1dfbbb530f..77aef39b2b6 100644 --- a/packages/kolide/data_stream/audit/fields/base-fields.yml +++ b/packages/kolide/data_stream/audit/fields/base-fields.yml @@ -1,20 +1,16 @@ - name: data_stream.type - type: constant_keyword - description: Data stream type. + external: ecs - name: data_stream.dataset - type: constant_keyword - description: Data stream dataset. + external: ecs - name: data_stream.namespace - type: constant_keyword - description: Data stream namespace. + external: ecs - name: event.module + external: ecs type: constant_keyword - description: Event module. value: kolide - name: event.dataset + external: ecs type: constant_keyword - description: Event dataset. value: kolide.audit - name: '@timestamp' - type: date - description: Event timestamp. + external: ecs diff --git a/packages/kolide/data_stream/audit/manifest.yml b/packages/kolide/data_stream/audit/manifest.yml index 8693e973264..83b6c4f065c 100644 --- a/packages/kolide/data_stream/audit/manifest.yml +++ b/packages/kolide/data_stream/audit/manifest.yml @@ -112,6 +112,13 @@ streams: Name of the bucket to poll for 3rd-party S3-compatible services. required: false show_user: false + - name: region + type: text + title: "[S3] Region" + description: |- + Region of the non-AWS S3-compatible endpoint. Required when a non-AWS bucket name is configured. + required: false + show_user: false - name: bucket_list_prefix type: text title: "[S3] Bucket List Prefix" @@ -237,6 +244,105 @@ streams: required: false show_user: false default: "" + - input: gcs + title: "Kolide audit logs via Google Cloud Storage (Log Pipeline)" + description: |- + Collect Kolide admin audit logs (the `kolide/audit_logs/` prefix) that the Kolide Log Pipeline writes to a customer-owned GCS bucket, via bucket polling. + template_path: gcs.yml.hbs + enabled: false + vars: + - name: buckets + type: yaml + title: "[GCS] Buckets" + description: |- + The list of GCS buckets to poll, as YAML. The attribute `name` is required; `number_of_workers` (as `max_workers`), `poll`, `poll_interval`, and `bucket_timeout` can also be set per bucket to override the global values. See the [`gcs` input settings docs](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-gcs.html#attrib-buckets) for details. + required: true + show_user: true + default: | + # The bucket name is the Kolide Log Pipeline destination bucket. + - name: kolide-log-pipeline + - name: file_selectors + type: yaml + title: "[GCS] File Selectors" + description: |- + A list of regex patterns that limit which GCS objects are processed, matched against the object key. Defaults to the Kolide Log Pipeline prefix for this data type; adjust it if you customized the object path template in the Kolide log destination. + required: false + show_user: true + default: | + - regex: '^kolide/audit_logs/' + - name: number_of_workers + type: integer + title: "[GCS] Number of Workers" + description: |- + Number of workers that will process the GCS objects, per bucket. + required: false + show_user: true + default: 3 + - name: poll + type: bool + title: "[GCS] Polling" + description: |- + Determines if the bucket is continuously polled for new objects. + required: false + show_user: true + default: true + - name: poll_interval + type: text + title: "[GCS] Polling Interval" + description: |- + Time interval between polling operations. + required: false + show_user: true + default: 15s + - name: bucket_timeout + type: text + title: "[GCS] Bucket Timeout" + description: |- + Maximum time to wait for a bucket API response before timing out. Accepts a duration like `120s`, `2m`. + required: false + show_user: false + default: 120s + - name: timestamp_epoch + type: integer + title: "[GCS] Timestamp Epoch" + description: |- + If set, only process GCS objects whose last-modified time is newer than this Unix epoch time (in seconds). + required: false + show_user: false + - name: tags + type: text + title: "Tags" + description: |- + Tags to include in the published event. + multi: true + required: true + show_user: false + default: + - forwarded + - kolide-audit-gcs + - name: preserve_original_event + type: bool + title: "Preserve original event" + description: |- + Preserves a raw copy of the original event, added to the field `event.original`. + required: true + show_user: true + default: false + - name: processors + type: yaml + title: "Processors" + description: |- + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. + required: false + show_user: false + - name: custom + type: yaml + title: "Custom configurations" + description: |- + Additional settings to be added to the configuration. Be careful using this as it might break the input. See [`gcs` input settings docs](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-gcs.html) for details. + required: false + show_user: false + default: "" elasticsearch: index_template: mappings: diff --git a/packages/kolide/data_stream/audit/sample_event.json b/packages/kolide/data_stream/audit/sample_event.json index 5409f494dc8..4af95b47924 100644 --- a/packages/kolide/data_stream/audit/sample_event.json +++ b/packages/kolide/data_stream/audit/sample_event.json @@ -1,35 +1,34 @@ { "@timestamp": "2024-03-11T21:28:17.000Z", "agent": { - "ephemeral_id": "f734b99d-fd67-4981-bb45-59ca1024a4bf", - "id": "ce1af407-b9ee-42ff-9448-8cd015c5ac91", - "name": "elastic-agent-94474", + "ephemeral_id": "976911ab-bf56-45ea-b463-1ee8c348bb5f", + "id": "ab1e36dd-3a4a-4a94-95c7-8b8250ae7ee3", + "name": "elastic-agent-27061", "type": "filebeat", - "version": "9.4.1" + "version": "9.4.3" }, "data_stream": { "dataset": "kolide.audit", - "namespace": "14195", + "namespace": "56604", "type": "logs" }, "ecs": { - "version": "9.3.0" + "version": "9.4.0" }, "elastic_agent": { - "id": "ce1af407-b9ee-42ff-9448-8cd015c5ac91", + "id": "ab1e36dd-3a4a-4a94-95c7-8b8250ae7ee3", "snapshot": false, - "version": "9.4.1" + "version": "9.4.3" }, "event": { - "action": "audit_log", + "action": "check_enabled", "agent_id_status": "verified", "category": [ - "iam", "configuration" ], "dataset": "kolide.audit", "id": "01JA67B1DYJCKJ1J73T0F5EWGR", - "ingested": "2026-06-17T18:35:10Z", + "ingested": "2026-07-13T16:59:33Z", "kind": "event", "module": "kolide", "original": "{\"actor_info\":{\"actor_email\":\"alice@example.com\",\"actor_name\":\"Alice Johnson\",\"actor_type\":\"User\"},\"actor_name\":\"Alice Johnson\",\"description\":\"Enabled check 'iTerm2 - Require Secure Keyboard Entry to Be Enabled'\",\"id\":\"01JA67B1DYJCKJ1J73T0F5EWGR\",\"timestamp\":\"2024-03-11T21:28:17Z\"}", @@ -42,6 +41,7 @@ }, "kolide": { "audit": { + "actor_automated": false, "actor_type": "User" } }, diff --git a/packages/kolide/data_stream/auth/_dev/deploy/docker/docker-compose.yml b/packages/kolide/data_stream/auth/_dev/deploy/docker/docker-compose.yml index c6a9d4f2285..bcead2e4280 100644 --- a/packages/kolide/data_stream/auth/_dev/deploy/docker/docker-compose.yml +++ b/packages/kolide/data_stream/auth/_dev/deploy/docker/docker-compose.yml @@ -13,3 +13,15 @@ services: - http-server - --addr=:8090 - --config=/files/config-auth.yml + gcs-mock: + image: shourieg/gcs-mock-service:latest + ports: + - "4443/tcp" + volumes: + - ./files/gcs-manifest.yml:/app/manifest.yml:ro + - ./files/gcs:/data:ro + healthcheck: + test: "wget --no-verbose --tries=1 --spider http://localhost:4443/health || exit 1" + interval: 10s + timeout: 5s + command: ["./gcs-mock-service", "--manifest", "/app/manifest.yml"] diff --git a/packages/kolide/data_stream/auth/agent/stream/aws-s3.yml.hbs b/packages/kolide/data_stream/auth/agent/stream/aws-s3.yml.hbs index 220a84c4d1b..2b9effbc5c3 100644 --- a/packages/kolide/data_stream/auth/agent/stream/aws-s3.yml.hbs +++ b/packages/kolide/data_stream/auth/agent/stream/aws-s3.yml.hbs @@ -89,6 +89,9 @@ credential_profile_name: {{credential_profile_name}} {{#if shared_credential_file}} shared_credential_file: {{shared_credential_file}} {{/if}} +{{#if region}} +region: {{region}} +{{/if}} {{#if endpoint}} endpoint: {{endpoint}} {{/if}} diff --git a/packages/kolide/data_stream/auth/elasticsearch/ingest_pipeline/default.yml b/packages/kolide/data_stream/auth/elasticsearch/ingest_pipeline/default.yml index 88198959cf0..d14bc007d5e 100644 --- a/packages/kolide/data_stream/auth/elasticsearch/ingest_pipeline/default.yml +++ b/packages/kolide/data_stream/auth/elasticsearch/ingest_pipeline/default.yml @@ -67,15 +67,15 @@ processors: if: ctx.json == null && ctx.event?.original != null description: Decode the CEL message JSON into json. - # --- S3 (Log Pipeline) input only --- - # aws-s3 deliveries carry the envelope {type, timestamp, data}. Lift `data` up - # to json.* so the shared API field extraction below applies (the S3 data field - # names match the API names). + # --- S3/GCS (Log Pipeline) input only --- + # Both aws-s3 and gcs deliveries carry the envelope {type, timestamp, data}. + # Lift `data` up to json.* so the shared API field extraction below applies + # (the S3/GCS data field names match the API names). - pipeline: name: '{{ IngestPipeline "s3" }}' tag: dispatch_s3 if: ctx.json?.type == 'auth_log' - # --- end S3-only --- + # --- end S3/GCS-only --- # json.timestamp is the sub-event time (or session time); session_timestamp is session start. - date: diff --git a/packages/kolide/data_stream/auth/fields/agent.yml b/packages/kolide/data_stream/auth/fields/agent.yml index adac4241805..18fe7012378 100644 --- a/packages/kolide/data_stream/auth/fields/agent.yml +++ b/packages/kolide/data_stream/auth/fields/agent.yml @@ -17,3 +17,22 @@ - name: key type: keyword description: The AWS S3 object key. +- name: gcs.storage + type: group + description: Metadata added by the GCS input for objects collected from the Kolide Log Pipeline bucket. + fields: + - name: bucket + type: group + fields: + - name: name + type: keyword + description: The GCS bucket name. + - name: object + type: group + fields: + - name: name + type: keyword + description: The GCS object name. + - name: content_type + type: keyword + description: The content type of the GCS object. diff --git a/packages/kolide/data_stream/auth/fields/base-fields.yml b/packages/kolide/data_stream/auth/fields/base-fields.yml index 6dfa74b17eb..f49ec2f3deb 100644 --- a/packages/kolide/data_stream/auth/fields/base-fields.yml +++ b/packages/kolide/data_stream/auth/fields/base-fields.yml @@ -1,20 +1,16 @@ - name: data_stream.type - type: constant_keyword - description: Data stream type. + external: ecs - name: data_stream.dataset - type: constant_keyword - description: Data stream dataset. + external: ecs - name: data_stream.namespace - type: constant_keyword - description: Data stream namespace. + external: ecs - name: event.module + external: ecs type: constant_keyword - description: Event module. value: kolide - name: event.dataset + external: ecs type: constant_keyword - description: Event dataset. value: kolide.auth - name: '@timestamp' - type: date - description: Event timestamp. + external: ecs diff --git a/packages/kolide/data_stream/auth/manifest.yml b/packages/kolide/data_stream/auth/manifest.yml index 6489d1b7752..e5040bbb5f5 100644 --- a/packages/kolide/data_stream/auth/manifest.yml +++ b/packages/kolide/data_stream/auth/manifest.yml @@ -112,6 +112,13 @@ streams: Name of the bucket to poll for 3rd-party S3-compatible services. required: false show_user: false + - name: region + type: text + title: "[S3] Region" + description: |- + Region of the non-AWS S3-compatible endpoint. Required when a non-AWS bucket name is configured. + required: false + show_user: false - name: bucket_list_prefix type: text title: "[S3] Bucket List Prefix" @@ -237,6 +244,105 @@ streams: required: false show_user: false default: "" + - input: gcs + title: "Kolide authentication logs via Google Cloud Storage (Log Pipeline)" + description: |- + Collect Kolide authentication logs (the `kolide/auth_logs/` prefix) that the Kolide Log Pipeline writes to a customer-owned GCS bucket, via bucket polling. + template_path: gcs.yml.hbs + enabled: false + vars: + - name: buckets + type: yaml + title: "[GCS] Buckets" + description: |- + The list of GCS buckets to poll, as YAML. The attribute `name` is required; `number_of_workers` (as `max_workers`), `poll`, `poll_interval`, and `bucket_timeout` can also be set per bucket to override the global values. See the [`gcs` input settings docs](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-gcs.html#attrib-buckets) for details. + required: true + show_user: true + default: | + # The bucket name is the Kolide Log Pipeline destination bucket. + - name: kolide-log-pipeline + - name: file_selectors + type: yaml + title: "[GCS] File Selectors" + description: |- + A list of regex patterns that limit which GCS objects are processed, matched against the object key. Defaults to the Kolide Log Pipeline prefix for this data type; adjust it if you customized the object path template in the Kolide log destination. + required: false + show_user: true + default: | + - regex: '^kolide/auth_logs/' + - name: number_of_workers + type: integer + title: "[GCS] Number of Workers" + description: |- + Number of workers that will process the GCS objects, per bucket. + required: false + show_user: true + default: 3 + - name: poll + type: bool + title: "[GCS] Polling" + description: |- + Determines if the bucket is continuously polled for new objects. + required: false + show_user: true + default: true + - name: poll_interval + type: text + title: "[GCS] Polling Interval" + description: |- + Time interval between polling operations. + required: false + show_user: true + default: 15s + - name: bucket_timeout + type: text + title: "[GCS] Bucket Timeout" + description: |- + Maximum time to wait for a bucket API response before timing out. Accepts a duration like `120s`, `2m`. + required: false + show_user: false + default: 120s + - name: timestamp_epoch + type: integer + title: "[GCS] Timestamp Epoch" + description: |- + If set, only process GCS objects whose last-modified time is newer than this Unix epoch time (in seconds). + required: false + show_user: false + - name: tags + type: text + title: "Tags" + description: |- + Tags to include in the published event. + multi: true + required: true + show_user: false + default: + - forwarded + - kolide-auth-gcs + - name: preserve_original_event + type: bool + title: "Preserve original event" + description: |- + Preserves a raw copy of the original event, added to the field `event.original`. + required: true + show_user: true + default: false + - name: processors + type: yaml + title: "Processors" + description: |- + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. + required: false + show_user: false + - name: custom + type: yaml + title: "Custom configurations" + description: |- + Additional settings to be added to the configuration. Be careful using this as it might break the input. See [`gcs` input settings docs](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-gcs.html) for details. + required: false + show_user: false + default: "" elasticsearch: index_template: mappings: diff --git a/packages/kolide/data_stream/auth/sample_event.json b/packages/kolide/data_stream/auth/sample_event.json index c29c7ed093d..816ef00117a 100644 --- a/packages/kolide/data_stream/auth/sample_event.json +++ b/packages/kolide/data_stream/auth/sample_event.json @@ -1,24 +1,27 @@ { - "@timestamp": "2024-03-11T21:28:17.000Z", + "@timestamp": "2026-06-11T16:29:17.000Z", "agent": { - "ephemeral_id": "a7e8f0c3-3f3c-4df1-a711-dca5f997077c", - "id": "d9df3829-c2e0-4721-8242-1cf13796bbc4", - "name": "elastic-agent-47734", + "ephemeral_id": "ead84309-61e4-4649-884b-5c2bbcb28888", + "id": "dccea145-284f-4566-914a-d93ed70b44fc", + "name": "elastic-agent-96605", "type": "filebeat", - "version": "9.4.1" + "version": "8.19.0" + }, + "cloud": { + "provider": "google cloud" }, "data_stream": { "dataset": "kolide.auth", - "namespace": "93060", + "namespace": "86759", "type": "logs" }, "ecs": { - "version": "9.3.0" + "version": "9.4.0" }, "elastic_agent": { - "id": "d9df3829-c2e0-4721-8242-1cf13796bbc4", + "id": "dccea145-284f-4566-914a-d93ed70b44fc", "snapshot": false, - "version": "9.4.1" + "version": "8.19.0" }, "event": { "action": "sign_in_attempt", @@ -28,52 +31,42 @@ "session" ], "dataset": "kolide.auth", - "id": "3374648:sign_in_attempt:2024-03-11T21:28:17Z", - "ingested": "2026-06-17T18:36:02Z", + "id": "id-95314806818425813618559742320:sign_in_attempt:2026-06-11T16:29:17Z", + "ingested": "2026-07-13T18:22:27Z", "kind": "event", - "module": "kolide", - "original": "{\"agent_version\":\"1.4.0\",\"browser_name\":\"Chrome\",\"browser_user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\",\"city\":\"New York\",\"country\":\"United States\",\"device_info\":{\"identifier\":\"1\",\"link\":\"https://api.example.com/devices/1\"},\"events\":[{\"event_description\":\"The end-user was redirected to Kolide via a valid SAML request\",\"event_type\":\"sign_in_attempt\",\"timestamp\":\"2024-03-11T21:28:17Z\"},{\"event_description\":\"The end-user clicked Continue to Sign In\",\"event_type\":\"sign_in_success\",\"timestamp\":\"2024-03-11T21:28:19Z\"}],\"id\":\"3374648\",\"initial_status\":\"all_good\",\"ip_address\":\"198.51.100.23\",\"issues_displayed\":[{\"blocking_status\":\"will_block\",\"id\":\"9999\",\"link\":\"https://api.example.com/issues/9999\",\"title\":\"macOS Firewall is Disabled\"}],\"okta_app_instance_id\":\"0oa1example2instance3\",\"okta_app_name\":\"Example Corp SSO\",\"person_email\":\"user@example.com\",\"person_info\":{\"identifier\":\"3\",\"link\":\"https://api.example.com/people/3\"},\"person_name\":\"Alice Johnson\",\"result\":\"Success\",\"session_timestamp\":\"2024-03-11T21:28:17Z\",\"sub_event_description\":\"The end-user was redirected to Kolide via a valid SAML request\",\"sub_event_type\":\"sign_in_attempt\",\"timestamp\":\"2024-03-11T21:28:17Z\"}", - "outcome": "success", - "start": "2024-03-11T21:28:17.000Z", + "original": "{\"timestamp\":\"2026-06-11T16:29:17Z\",\"type\":\"auth_log\",\"data\":{\"request_id\":\"id-95314806818425813618559742320\",\"auth_event_type\":\"sign_in_attempt\",\"ip_address\":\"198.51.100.210\"}}", "type": [ - "start", - "info" + "start" ] }, - "host": { - "id": "1" + "gcs": { + "storage": { + "bucket": { + "name": "kolide-auth" + }, + "object": { + "content_type": "application/x-ndjson", + "name": "kolide-auth.log" + } + } }, "input": { - "type": "cel" + "type": "gcs" }, "kolide": { "auth": { - "agent_version": "1.4.0", - "initial_status": "all_good", - "issues_displayed": [ - { - "blocking_status": "will_block", - "id": "9999", - "link": "https://api.example.com/issues/9999", - "title": "macOS Firewall is Disabled" - } - ], - "okta": { - "app_instance_id": "0oa1example2instance3", - "app_name": "Example Corp SSO" - }, - "result": "Success", - "session_id": "3374648" + "session_id": "id-95314806818425813618559742320" } }, - "message": "The end-user was redirected to Kolide via a valid SAML request", + "log": { + "file": { + "path": "gs://kolide-auth/kolide-auth.log" + }, + "offset": 0 + }, "related": { "ip": [ - "198.51.100.23" - ], - "user": [ - "Alice Johnson", - "user@example.com" + "198.51.100.210" ] }, "source": { @@ -89,35 +82,17 @@ "country_iso_code": "NL", "country_name": "Netherlands", "location": { - "lat": 52.37403995823115, - "lon": 4.889689916744828 + "lat": 52.37404, + "lon": 4.88969 }, "region_iso_code": "NL-NH", "region_name": "North Holland" }, - "ip": "198.51.100.23" + "ip": "198.51.100.210" }, "tags": [ "preserve_original_event", "forwarded", - "kolide-auth" - ], - "user": { - "email": "user@example.com", - "id": "3", - "name": "Alice Johnson" - }, - "user_agent": { - "device": { - "name": "Mac" - }, - "name": "Chrome", - "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", - "os": { - "full": "Mac OS X 10.15.7", - "name": "Mac OS X", - "version": "10.15.7" - }, - "version": "122.0.0.0" - } -} \ No newline at end of file + "kolide-auth-gcs" + ] +} diff --git a/packages/kolide/data_stream/device/_dev/test/pipeline/test-kolide-device-pipeline.json-expected.json b/packages/kolide/data_stream/device/_dev/test/pipeline/test-kolide-device-pipeline.json-expected.json index 9d42e29cb0f..71e9a4744ef 100644 --- a/packages/kolide/data_stream/device/_dev/test/pipeline/test-kolide-device-pipeline.json-expected.json +++ b/packages/kolide/data_stream/device/_dev/test/pipeline/test-kolide-device-pipeline.json-expected.json @@ -1,7 +1,7 @@ { "expected": [ { - "@timestamp": "2026-06-25T18:22:37.270529961Z", + "@timestamp": "2026-07-13T16:34:27.742192424Z", "ecs": { "version": "9.4.0" }, @@ -53,7 +53,7 @@ ] }, { - "@timestamp": "2026-06-25T18:22:37.270544003Z", + "@timestamp": "2026-07-13T16:34:27.742201632Z", "ecs": { "version": "9.4.0" }, @@ -118,7 +118,7 @@ } }, { - "@timestamp": "2026-06-25T18:22:37.270545169Z", + "@timestamp": "2026-07-13T16:34:27.742203174Z", "ecs": { "version": "9.4.0" }, @@ -182,7 +182,7 @@ } }, { - "@timestamp": "2026-06-25T18:22:37.270545753Z", + "@timestamp": "2026-07-13T16:34:27.742204382Z", "ecs": { "version": "9.4.0" }, @@ -247,7 +247,7 @@ } }, { - "@timestamp": "2026-06-25T18:22:37.270546253Z", + "@timestamp": "2026-07-13T16:34:27.742205466Z", "ecs": { "version": "9.4.0" }, @@ -312,7 +312,7 @@ } }, { - "@timestamp": "2026-06-25T18:22:37.270546836Z", + "@timestamp": "2026-07-13T16:34:27.742206507Z", "ecs": { "version": "9.4.0" }, @@ -377,7 +377,7 @@ } }, { - "@timestamp": "2026-06-25T18:22:37.270547294Z", + "@timestamp": "2026-07-13T16:34:27.742207549Z", "ecs": { "version": "9.4.0" }, diff --git a/packages/kolide/data_stream/device/fields/base-fields.yml b/packages/kolide/data_stream/device/fields/base-fields.yml index 5fff24fc9be..46ba398c4d0 100644 --- a/packages/kolide/data_stream/device/fields/base-fields.yml +++ b/packages/kolide/data_stream/device/fields/base-fields.yml @@ -1,20 +1,16 @@ - name: data_stream.type - type: constant_keyword - description: Data stream type. + external: ecs - name: data_stream.dataset - type: constant_keyword - description: Data stream dataset. + external: ecs - name: data_stream.namespace - type: constant_keyword - description: Data stream namespace. + external: ecs - name: event.module + external: ecs type: constant_keyword - description: Event module. value: kolide - name: event.dataset + external: ecs type: constant_keyword - description: Event dataset. value: kolide.device - name: '@timestamp' - type: date - description: Event timestamp. + external: ecs diff --git a/packages/kolide/data_stream/device/manifest.yml b/packages/kolide/data_stream/device/manifest.yml index 004431d4232..1480bf00e89 100644 --- a/packages/kolide/data_stream/device/manifest.yml +++ b/packages/kolide/data_stream/device/manifest.yml @@ -7,8 +7,8 @@ streams: Collect the full Kolide device inventory from the Kolide REST API (GET /devices) on every poll. The /devices endpoint exposes no modified-since cursor, so each interval re-collects the complete collection; the ingest pipeline assigns a - content-based document `_id` so unchanged devices are overwritten and any change - is captured as a new document. + content-based document `_id` so unchanged devices are deduplicated across polls + and any change is captured as a new document. template_path: cel.yml.hbs vars: - name: interval diff --git a/packages/kolide/data_stream/device/sample_event.json b/packages/kolide/data_stream/device/sample_event.json index c3438d0fd13..5f55220203f 100644 --- a/packages/kolide/data_stream/device/sample_event.json +++ b/packages/kolide/data_stream/device/sample_event.json @@ -1,24 +1,24 @@ { - "@timestamp": "2026-06-26T19:45:06.028069753Z", + "@timestamp": "2026-07-13T16:41:33.883Z", "agent": { - "ephemeral_id": "cd0d58a1-1d21-45e2-accf-77d9d46080b3", - "id": "c5bb2007-c7a7-44cb-a399-4679caac8c22", - "name": "elastic-agent-37867", + "ephemeral_id": "6dc17ec1-2f49-4b4a-899d-a50c23e3256a", + "id": "8fc63088-0e7a-4b0a-80b6-d927c6b6fd64", + "name": "elastic-agent-75041", "type": "filebeat", - "version": "8.19.0" + "version": "9.4.3" }, "data_stream": { "dataset": "kolide.device", - "namespace": "47456", + "namespace": "92721", "type": "logs" }, "ecs": { "version": "9.4.0" }, "elastic_agent": { - "id": "c5bb2007-c7a7-44cb-a399-4679caac8c22", + "id": "8fc63088-0e7a-4b0a-80b6-d927c6b6fd64", "snapshot": false, - "version": "8.19.0" + "version": "9.4.3" }, "event": { "action": "device", @@ -27,8 +27,9 @@ "host" ], "dataset": "kolide.device", - "ingested": "2026-06-26T19:45:06Z", + "ingested": "2026-07-13T16:41:33Z", "kind": "state", + "module": "kolide", "original": "{\"auth_configuration\":{\"authentication_mode\":\"only_registered_owner\",\"device_id\":\"1\",\"person_groups\":[]},\"auth_state\":\"Good\",\"device_type\":\"Mac\",\"form_factor\":\"Computer\",\"hardware_model\":\"MacBookPro18,1\",\"hardware_uuid\":\"00000000-0000-0000-0000-000000000000\",\"id\":\"1\",\"last_authenticated_at\":\"2024-03-11T21:28:17Z\",\"last_seen_at\":\"2024-03-11T21:30:00Z\",\"name\":\"Alices-MacBook-Pro\",\"note\":\"Loaner device\",\"operating_system\":\"macOS 14.4.1\",\"product_image_url\":\"https://example.com/images/macbookpro.png\",\"registered_at\":\"2023-10-28T20:12:14Z\",\"registered_owner_info\":{\"identifier\":\"1\",\"link\":\"https://api.example.com/people/1\"},\"serial\":\"C02EXAMPLE123\",\"will_block_at\":null}", "start": "2023-10-28T20:12:14.000Z", "type": [ diff --git a/packages/kolide/data_stream/device_check/agent/stream/aws-s3.yml.hbs b/packages/kolide/data_stream/device_check/agent/stream/aws-s3.yml.hbs index 220a84c4d1b..2b9effbc5c3 100644 --- a/packages/kolide/data_stream/device_check/agent/stream/aws-s3.yml.hbs +++ b/packages/kolide/data_stream/device_check/agent/stream/aws-s3.yml.hbs @@ -89,6 +89,9 @@ credential_profile_name: {{credential_profile_name}} {{#if shared_credential_file}} shared_credential_file: {{shared_credential_file}} {{/if}} +{{#if region}} +region: {{region}} +{{/if}} {{#if endpoint}} endpoint: {{endpoint}} {{/if}} diff --git a/packages/kolide/data_stream/device_check/elasticsearch/ingest_pipeline/default.yml b/packages/kolide/data_stream/device_check/elasticsearch/ingest_pipeline/default.yml index 7a7b31c8c3b..c644fa123c5 100644 --- a/packages/kolide/data_stream/device_check/elasticsearch/ingest_pipeline/default.yml +++ b/packages/kolide/data_stream/device_check/elasticsearch/ingest_pipeline/default.yml @@ -1,7 +1,7 @@ --- description: >- Parse Kolide device check-run results (type "check_result") collected from the - Kolide Log Pipeline via the aws-s3 input. Unlike the issues data stream (which + Kolide Log Pipeline via the aws-s3/gcs inputs. Unlike the issues data stream (which tracks the failure lifecycle), check-run results include every run: passing, failing, inapplicable, and unknown. Reference: https://www.kolide.com/docs/admins/log-pipeline/overview @@ -11,8 +11,8 @@ processors: tag: set_ecs_version value: '9.4.0' - # The aws-s3 input delivers the raw object in `message`. Keep a raw copy in - # event.original, then decode it into the working `json` object below. + # The aws-s3/gcs inputs deliver the raw object in `message`. Keep a raw copy + # in event.original, then decode it into the working `json` object below. - rename: field: message tag: rename_message_to_event_original @@ -127,8 +127,9 @@ processors: ignore_missing_pipeline: true # event.id / deduplication: check-run results have no native id, so derive a - # stable event.id from device_id + check_id + @timestamp. aws-s3 is - # at-least-once, so fingerprint it to _id to upsert re-delivered objects. + # stable event.id from device_id + check_id + @timestamp. aws-s3/gcs are + # at-least-once, so fingerprint it to _id so re-delivered objects are dropped + # as duplicates instead of indexed twice. - set: field: event.id tag: set_event_id diff --git a/packages/kolide/data_stream/device_check/fields/agent.yml b/packages/kolide/data_stream/device_check/fields/agent.yml index adac4241805..18fe7012378 100644 --- a/packages/kolide/data_stream/device_check/fields/agent.yml +++ b/packages/kolide/data_stream/device_check/fields/agent.yml @@ -17,3 +17,22 @@ - name: key type: keyword description: The AWS S3 object key. +- name: gcs.storage + type: group + description: Metadata added by the GCS input for objects collected from the Kolide Log Pipeline bucket. + fields: + - name: bucket + type: group + fields: + - name: name + type: keyword + description: The GCS bucket name. + - name: object + type: group + fields: + - name: name + type: keyword + description: The GCS object name. + - name: content_type + type: keyword + description: The content type of the GCS object. diff --git a/packages/kolide/data_stream/device_check/fields/base-fields.yml b/packages/kolide/data_stream/device_check/fields/base-fields.yml index a4e85e23a7e..0af8cae0592 100644 --- a/packages/kolide/data_stream/device_check/fields/base-fields.yml +++ b/packages/kolide/data_stream/device_check/fields/base-fields.yml @@ -1,20 +1,16 @@ - name: data_stream.type - type: constant_keyword - description: Data stream type. + external: ecs - name: data_stream.dataset - type: constant_keyword - description: Data stream dataset. + external: ecs - name: data_stream.namespace - type: constant_keyword - description: Data stream namespace. + external: ecs - name: event.module + external: ecs type: constant_keyword - description: Event module. value: kolide - name: event.dataset + external: ecs type: constant_keyword - description: Event dataset. value: kolide.device_check - name: '@timestamp' - type: date - description: Event timestamp. + external: ecs diff --git a/packages/kolide/data_stream/device_check/manifest.yml b/packages/kolide/data_stream/device_check/manifest.yml index 3d2689a13e5..0d1088a0a35 100644 --- a/packages/kolide/data_stream/device_check/manifest.yml +++ b/packages/kolide/data_stream/device_check/manifest.yml @@ -36,6 +36,13 @@ streams: Name of the bucket to poll for 3rd-party S3-compatible services. required: false show_user: false + - name: region + type: text + title: "[S3] Region" + description: |- + Region of the non-AWS S3-compatible endpoint. Required when a non-AWS bucket name is configured. + required: false + show_user: false - name: bucket_list_prefix type: text title: "[S3] Bucket List Prefix" @@ -161,6 +168,105 @@ streams: required: false show_user: false default: "" + - input: gcs + title: "Kolide device check-run results via Google Cloud Storage (Log Pipeline)" + description: |- + Collect Kolide device check-run results (the `kolide/check_runs/` prefix) that the Kolide Log Pipeline writes to a customer-owned GCS bucket, via bucket polling. + template_path: gcs.yml.hbs + enabled: false + vars: + - name: buckets + type: yaml + title: "[GCS] Buckets" + description: |- + The list of GCS buckets to poll, as YAML. The attribute `name` is required; `number_of_workers` (as `max_workers`), `poll`, `poll_interval`, and `bucket_timeout` can also be set per bucket to override the global values. See the [`gcs` input settings docs](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-gcs.html#attrib-buckets) for details. + required: true + show_user: true + default: | + # The bucket name is the Kolide Log Pipeline destination bucket. + - name: kolide-log-pipeline + - name: file_selectors + type: yaml + title: "[GCS] File Selectors" + description: |- + A list of regex patterns that limit which GCS objects are processed, matched against the object key. Defaults to the Kolide Log Pipeline prefix for this data type; adjust it if you customized the object path template in the Kolide log destination. + required: false + show_user: true + default: | + - regex: '^kolide/check_runs/' + - name: number_of_workers + type: integer + title: "[GCS] Number of Workers" + description: |- + Number of workers that will process the GCS objects, per bucket. + required: false + show_user: true + default: 3 + - name: poll + type: bool + title: "[GCS] Polling" + description: |- + Determines if the bucket is continuously polled for new objects. + required: false + show_user: true + default: true + - name: poll_interval + type: text + title: "[GCS] Polling Interval" + description: |- + Time interval between polling operations. + required: false + show_user: true + default: 15s + - name: bucket_timeout + type: text + title: "[GCS] Bucket Timeout" + description: |- + Maximum time to wait for a bucket API response before timing out. Accepts a duration like `120s`, `2m`. + required: false + show_user: false + default: 120s + - name: timestamp_epoch + type: integer + title: "[GCS] Timestamp Epoch" + description: |- + If set, only process GCS objects whose last-modified time is newer than this Unix epoch time (in seconds). + required: false + show_user: false + - name: tags + type: text + title: "Tags" + description: |- + Tags to include in the published event. + multi: true + required: true + show_user: false + default: + - forwarded + - kolide-device-check-gcs + - name: preserve_original_event + type: bool + title: "Preserve original event" + description: |- + Preserves a raw copy of the original event, added to the field `event.original`. + required: true + show_user: true + default: false + - name: processors + type: yaml + title: "Processors" + description: |- + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. + required: false + show_user: false + - name: custom + type: yaml + title: "Custom configurations" + description: |- + Additional settings to be added to the configuration. Be careful using this as it might break the input. See [`gcs` input settings docs](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-gcs.html) for details. + required: false + show_user: false + default: "" elasticsearch: index_template: mappings: diff --git a/packages/kolide/data_stream/device_check/sample_event.json b/packages/kolide/data_stream/device_check/sample_event.json index 2c14cc4e807..adafa3cf559 100644 --- a/packages/kolide/data_stream/device_check/sample_event.json +++ b/packages/kolide/data_stream/device_check/sample_event.json @@ -1,24 +1,27 @@ { "@timestamp": "2026-06-02T15:45:01.000Z", "agent": { - "ephemeral_id": "b2c4d6e8-f0a1-4b3c-8d7e-9f0a1b2c3d4e", - "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", - "name": "elastic-agent-12345", + "ephemeral_id": "7688604a-e3eb-4d25-a462-28596cd3c236", + "id": "c4e7e825-937b-4db3-a16a-67072d1169fa", + "name": "elastic-agent-75667", "type": "filebeat", - "version": "9.4.1" + "version": "9.4.3" + }, + "cloud": { + "provider": "google cloud" }, "data_stream": { "dataset": "kolide.device_check", - "namespace": "48291", + "namespace": "77666", "type": "logs" }, "ecs": { - "version": "9.3.0" + "version": "9.4.0" }, "elastic_agent": { - "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "id": "c4e7e825-937b-4db3-a16a-67072d1169fa", "snapshot": false, - "version": "9.4.1" + "version": "9.4.3" }, "event": { "action": "check_result", @@ -27,8 +30,8 @@ "host" ], "dataset": "kolide.device_check", - "id": "7386319-10-2026-06-02T15:45:01.000Z", - "ingested": "2026-06-17T18:40:00Z", + "id": "7386319-10-2026-06-02T15:45:01Z", + "ingested": "2026-07-13T16:43:34Z", "kind": "state", "module": "kolide", "original": "{\"type\":\"check_result\",\"timestamp\":\"2026-06-02T15:45:01Z\",\"data\":{\"check_id\":10,\"check_slug\":\"macos_file_sharing\",\"device_id\":7386319,\"status\":\"passing\",\"check_result_data\":[{\"file_sharing\":\"0\",\"current_os_version\":\"26.4.1\",\"KOLIDE_CHECK_STATUS\":\"PASS\"}]}}", @@ -37,27 +40,42 @@ "info" ] }, + "gcs": { + "storage": { + "bucket": { + "name": "kolide-device-check" + }, + "object": { + "content_type": "application/x-ndjson", + "name": "kolide-device-check.log" + } + } + }, "host": { "id": "7386319" }, "input": { - "type": "aws-s3" + "type": "gcs" }, "kolide": { "device_check": { "check_id": 10, - "check_result_data": [ - { - "KOLIDE_CHECK_STATUS": "PASS", - "current_os_version": "26.4.1", - "file_sharing": "0" - } - ], + "check_result_data": { + "KOLIDE_CHECK_STATUS": "PASS", + "current_os_version": "26.4.1", + "file_sharing": "0" + }, "check_slug": "macos_file_sharing", "device_id": 7386319, "status": "passing" } }, + "log": { + "file": { + "path": "gs://kolide-device-check/kolide-device-check.log" + }, + "offset": 1670 + }, "rule": { "id": "10", "name": "macos_file_sharing" @@ -65,6 +83,6 @@ "tags": [ "preserve_original_event", "forwarded", - "kolide-device-check-s3" + "kolide-device-check-gcs" ] -} \ No newline at end of file +} diff --git a/packages/kolide/data_stream/issues/_dev/deploy/docker/files/config-issues.yml b/packages/kolide/data_stream/issues/_dev/deploy/docker/files/config-issues.yml index 048bdf726aa..196fe651e7b 100644 --- a/packages/kolide/data_stream/issues/_dev/deploy/docker/files/config-issues.yml +++ b/packages/kolide/data_stream/issues/_dev/deploy/docker/files/config-issues.yml @@ -1,15 +1,24 @@ rules: - # Round 2+ (convergence): the cursor is the exact max detected_at from round 1 - # (2026-06-15T12:00:00.000Z), so the initial query carries that timestamp. + # Round 2+ (convergence): the cursor's last_timestamp is the max of + # detected_at/resolved_at/blocks_device_at across round 1 -- here that's + # 2026-06-15T13:59:00Z, the *resolved_at* of issue 500000012, not its + # detected_at (2026-06-15T12:00:00Z). This is the regression test for the + # cursor-advancement bug: if last_timestamp were computed from detected_at + # alone, the query below would carry the earlier (wrong) timestamp instead, + # this rule would never match, every poll would fall through to the page-1 + # catch-all below, and the same 5 records would be re-fetched on every poll + # forever instead of the query converging to an empty result set. (CEL's + # string(timestamp(...)) omits fractional seconds when they are zero, hence + # no ".000" here, unlike the RFC3339 timestamps in the source records.) # Return an empty page so polling converges and hit_count stays stable. (Against - # the real inclusive API the boundary record is re-returned and collapses via the - # _id fingerprint; the mock returns empty for simplicity.) Must precede the - # page-1 catch-all so it wins for the advanced-cursor query. + # the real inclusive API the boundary record is re-returned and dropped as a + # duplicate via the _id fingerprint; the mock returns empty for simplicity.) + # Must precede the page-1 catch-all so it wins for the advanced-cursor query. - path: /issues methods: ['GET'] query_params: per_page: '{per_page:.*}' - query: 'detected_at>2026-06-15T12:00:00.000Z' + query: 'detected_at>2026-06-15T13:59:00Z OR resolved_at>2026-06-15T13:59:00Z OR blocks_device_at>2026-06-15T13:59:00Z' request_headers: Authorization: - 'Bearer k2sk_v1_exampleexampleexample' diff --git a/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json b/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json index 2fe7d788ce3..81dbf775b9e 100644 --- a/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json +++ b/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json @@ -23,6 +23,12 @@ }, { "message": "{\"id\":\"500000041\",\"title\":\"Insecure Zoom Video Conference Server\",\"value\":{\"KOLIDE_CHECK_STATUS\":\"FAIL\"},\"exempted\":false,\"resolved_at\":null,\"detected_at\":\"2024-03-11T10:00:00Z\",\"blocks_device_at\":null,\"last_rechecked_at\":\"2024-03-11T10:05:00Z\",\"device_information\":{\"identifier\":\"device-mac-41\",\"link\":\"https://api.example.com/devices/41\"},\"check_information\":{\"identifier\":\"41\",\"link\":\"https://api.example.com/checks/41\"}}" + }, + { + "message": "{\"id\":\"500000099\",\"title\":\"Device Blocked - Firewall Disabled\",\"value\":{\"KOLIDE_CHECK_STATUS\":\"FAIL\"},\"exempted\":false,\"resolved_at\":null,\"detected_at\":\"2026-06-15T00:00:00Z\",\"blocks_device_at\":\"2026-06-16T00:00:00Z\",\"device_information\":{\"identifier\":\"device-blocked-01\",\"link\":\"https://api.example.com/devices/99\"},\"check_information\":{\"identifier\":\"32\",\"link\":\"https://api.example.com/checks/32\"},\"last_rechecked_at\":\"2026-06-16T00:00:00Z\"}" + }, + { + "message": "{\"id\":\"500000100\",\"title\":\"Resolved After Block Window\",\"value\":{\"KOLIDE_CHECK_STATUS\":\"PASS\"},\"exempted\":false,\"resolved_at\":\"2026-06-20T00:00:00Z\",\"detected_at\":\"2026-06-15T00:00:00Z\",\"blocks_device_at\":\"2026-06-16T00:00:00Z\",\"device_information\":{\"identifier\":\"device-resolved-after-block\",\"link\":\"https://api.example.com/devices/100\"},\"check_information\":{\"identifier\":\"32\",\"link\":\"https://api.example.com/checks/32\"},\"last_rechecked_at\":\"2026-06-20T00:00:00Z\"}" } ] -} +} \ No newline at end of file diff --git a/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json-expected.json b/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json-expected.json index d527ff3df6a..79f9dcab114 100644 --- a/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json-expected.json +++ b/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-pipeline.json-expected.json @@ -147,12 +147,12 @@ } }, { - "@timestamp": "2026-06-15T00:13:30.889Z", + "@timestamp": "2026-06-15T13:59:00Z", "ecs": { "version": "9.4.0" }, "event": { - "action": "issue", + "action": "resolved", "category": [ "configuration" ], @@ -369,7 +369,7 @@ } }, { - "@timestamp": "2024-03-11T09:00:00.000Z", + "@timestamp": "2024-03-11T09:00:00Z", "ecs": { "version": "9.4.0" }, @@ -433,7 +433,7 @@ ] }, { - "@timestamp": "2024-03-11T09:00:00.000Z", + "@timestamp": "2024-03-11T09:00:00Z", "ecs": { "version": "9.4.0" }, @@ -488,7 +488,7 @@ ] }, { - "@timestamp": "2024-03-11T10:00:00.000Z", + "@timestamp": "2024-03-11T10:00:00Z", "ecs": { "version": "9.4.0" }, @@ -537,6 +537,110 @@ "tags": [ "preserve_original_event" ] + }, + { + "@timestamp": "2026-06-16T00:00:00Z", + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "blocked", + "category": [ + "configuration" + ], + "id": "500000099", + "kind": "event", + "original": "{\"id\":\"500000099\",\"title\":\"Device Blocked - Firewall Disabled\",\"value\":{\"KOLIDE_CHECK_STATUS\":\"FAIL\"},\"exempted\":false,\"resolved_at\":null,\"detected_at\":\"2026-06-15T00:00:00Z\",\"blocks_device_at\":\"2026-06-16T00:00:00Z\",\"device_information\":{\"identifier\":\"device-blocked-01\",\"link\":\"https://api.example.com/devices/99\"},\"check_information\":{\"identifier\":\"32\",\"link\":\"https://api.example.com/checks/32\"},\"last_rechecked_at\":\"2026-06-16T00:00:00Z\"}", + "outcome": "failure", + "start": "2026-06-15T00:00:00.000Z", + "type": [ + "change" + ] + }, + "host": { + "id": "device-blocked-01" + }, + "kolide": { + "issues": { + "blocks_device_at": "2026-06-16T00:00:00.000Z", + "check_information": { + "link": "https://api.example.com/checks/32" + }, + "detected_at": "2026-06-15T00:00:00.000Z", + "device_information": { + "link": "https://api.example.com/devices/99" + }, + "exempted": false, + "id": "500000099", + "last_rechecked_at": "2026-06-16T00:00:00.000Z", + "title": "Device Blocked - Firewall Disabled", + "value": { + "KOLIDE_CHECK_STATUS": "FAIL" + } + } + }, + "message": "Device Blocked - Firewall Disabled", + "rule": { + "id": "32", + "name": "Device Blocked - Firewall Disabled", + "reference": "https://api.example.com/checks/32" + }, + "tags": [ + "preserve_original_event" + ] + }, + { + "@timestamp": "2026-06-20T00:00:00Z", + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "resolved", + "category": [ + "configuration" + ], + "end": "2026-06-20T00:00:00.000Z", + "id": "500000100", + "kind": "event", + "original": "{\"id\":\"500000100\",\"title\":\"Resolved After Block Window\",\"value\":{\"KOLIDE_CHECK_STATUS\":\"PASS\"},\"exempted\":false,\"resolved_at\":\"2026-06-20T00:00:00Z\",\"detected_at\":\"2026-06-15T00:00:00Z\",\"blocks_device_at\":\"2026-06-16T00:00:00Z\",\"device_information\":{\"identifier\":\"device-resolved-after-block\",\"link\":\"https://api.example.com/devices/100\"},\"check_information\":{\"identifier\":\"32\",\"link\":\"https://api.example.com/checks/32\"},\"last_rechecked_at\":\"2026-06-20T00:00:00Z\"}", + "outcome": "success", + "start": "2026-06-15T00:00:00.000Z", + "type": [ + "change" + ] + }, + "host": { + "id": "device-resolved-after-block" + }, + "kolide": { + "issues": { + "blocks_device_at": "2026-06-16T00:00:00.000Z", + "check_information": { + "link": "https://api.example.com/checks/32" + }, + "detected_at": "2026-06-15T00:00:00.000Z", + "device_information": { + "link": "https://api.example.com/devices/100" + }, + "exempted": false, + "id": "500000100", + "last_rechecked_at": "2026-06-20T00:00:00.000Z", + "resolved_at": "2026-06-20T00:00:00.000Z", + "title": "Resolved After Block Window", + "value": { + "KOLIDE_CHECK_STATUS": "PASS" + } + } + }, + "message": "Resolved After Block Window", + "rule": { + "id": "32", + "name": "Resolved After Block Window", + "reference": "https://api.example.com/checks/32" + }, + "tags": [ + "preserve_original_event" + ] } ] } diff --git a/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-webhook.json-expected.json b/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-webhook.json-expected.json index 5bf1b3cc938..e49778cb8af 100644 --- a/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-webhook.json-expected.json +++ b/packages/kolide/data_stream/issues/_dev/test/pipeline/test-kolide-issues-webhook.json-expected.json @@ -31,6 +31,7 @@ "firewall" ] }, + "detected_at": "2023-10-28T20:50:15.000Z", "id": "2", "title": "macOS Firewall is Disabled" } @@ -86,6 +87,7 @@ ] }, "id": "2", + "resolved_at": "2023-10-28T21:00:58.000Z", "title": "macOS Firewall is Disabled" } }, diff --git a/packages/kolide/data_stream/issues/agent/stream/cel.yml.hbs b/packages/kolide/data_stream/issues/agent/stream/cel.yml.hbs index 18eb5157cfd..c05234c0e22 100644 --- a/packages/kolide/data_stream/issues/agent/stream/cel.yml.hbs +++ b/packages/kolide/data_stream/issues/agent/stream/cel.yml.hbs @@ -43,7 +43,7 @@ program: |- : { "per_page": [string(int(state.batch_size))], - "query": ["detected_at>" + since], + "query": ["detected_at>" + since + " OR resolved_at>" + since + " OR blocks_device_at>" + since], } ).format_query() ).with( @@ -59,10 +59,20 @@ program: |- { "events": records.map(e, {"message": e.encode_json()}), "cursor": { + // resolved_at/blocks_device_at are frequently present with an + // explicit JSON null (not absent), and .orValue() only + // substitutes for an absent key, not a present null value, so + // each field is explicitly null-checked before timestamp(). + // blocks_device_at is a *future* enforcement deadline (not a + // past event like detected_at/resolved_at), so it can exceed + // "now" -- cap the result at now so the cursor never jumps + // ahead of real time and starves later polls of real matches. "last_timestamp": (size(records) > 0) ? - string( - (records.map(e, timestamp(e.?detected_at.orValue(since))) - + [timestamp(since)]).max() + (records.map(e, timestamp(e.?detected_at.orValue(since))) + + records.map(e, e.?resolved_at.orValue(since).as(v, timestamp(v == null ? since : v))) + + records.map(e, e.?blocks_device_at.orValue(since).as(v, timestamp(v == null ? since : v))) + + [timestamp(since)]).max().as(candidate, + string((candidate > now) ? now : candidate) ) : since, diff --git a/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/categorize.yml b/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/categorize.yml index e68be7673b3..a016edd0e7c 100644 --- a/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/categorize.yml +++ b/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/categorize.yml @@ -7,9 +7,12 @@ description: >- domain category (malware or vulnerability), keyed by check id (rule.id); the base configuration category is always retained, and unlisted checks remain configuration only. event.type is creation for a newly detected/open issue - and change for a resolved or updated issue (resolved_at set, or the - issues.resolved webhook action). event.outcome (open -> failure, resolved -> - success) is assigned in default.yml and is left untouched here. + and change for a resolved, pending-block, or blocked issue (resolved_at set, + blocks_device_at set, or the issues.resolved webhook action). event.action + becomes will_be_blocked once blocks_device_at is set but its deadline hasn't + passed yet, and blocked once the deadline has passed. event.outcome (open -> + failure, resolved -> success) is assigned in default.yml and is left + untouched here. processors: - script: lang: painless @@ -52,9 +55,35 @@ processors: } } - // A resolved/updated issue is a change; a newly detected issue is a creation. + // blocked/resolved issues are a change; a newly detected issue is a creation. + // blocked_device_at is a future deadline, not an immediate state: the device + // is only actually blocked once that deadline has passed relative to this event. + boolean pendingBlock = (ctx.kolide?.issues?.blocks_device_at != null); + boolean blocked = false; + if (pendingBlock && ctx['@timestamp'] != null) { + ZonedDateTime blockAt = ZonedDateTime.parse(ctx.kolide.issues.blocks_device_at); + ZonedDateTime eventTime = ZonedDateTime.parse(ctx['@timestamp']); + blocked = !blockAt.isAfter(eventTime); + } boolean resolved = (ctx.kolide?.issues?.resolved_at != null) || (action == 'issues.resolved'); - ctx.event.type = resolved ? ['change'] : ['creation']; + ctx.event.type = (pendingBlock || resolved) ? ['change'] : ['creation']; + + // Persist the computed blocked state for the fingerprint processor in + // default.yml, so pending/blocked/resolved each fingerprint to a distinct _id. + ctx._tmp = ctx._tmp == null ? [:] : ctx._tmp; + ctx._tmp.blocked = blocked; + + // Precedence: a resolved issue takes priority over a still-blocking one; + // a pending future block takes priority over a plain open issue. + if (action == 'issue') { + if (resolved) { + ctx.event.action = 'resolved'; + } else if (blocked) { + ctx.event.action = 'blocked'; + } else if (pendingBlock) { + ctx.event.action = 'will_be_blocked'; + } + } on_failure: - append: diff --git a/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/default.yml b/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/default.yml index b7ef2d277c0..c7bfc99c7d7 100644 --- a/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/default.yml +++ b/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/default.yml @@ -69,7 +69,14 @@ processors: description: Decode the CEL message (a JSON string of one issue object) into the working json object. # Common normalization (`json` is an API issue object or a webhook envelope). - # @timestamp: webhook `timestamp`, else API `detected_at`. + # @timestamp: webhook `timestamp`, else the max of the API's three lifecycle + # timestamps (detected_at/resolved_at/blocks_device_at). Using detected_at + # alone made a freshly-blocked or freshly-resolved issue's document appear + # to have an old @timestamp from whenever it was originally detected, even + # though the fetch was triggered by a state change that just happened. + # blocks_device_at is a *future* enforcement deadline (see fields.yml), not a + # past event, so it is capped at the current time -- otherwise a document + # could be indexed with a future @timestamp. - date: field: json.timestamp target_field: '@timestamp' @@ -77,13 +84,32 @@ processors: - ISO8601 tag: date_timestamp_webhook if: ctx.json?.timestamp != null - - date: - field: json.detected_at - target_field: '@timestamp' - formats: - - ISO8601 - tag: date_timestamp_api + - set: + field: _tmp.ingest_timestamp + copy_from: _ingest.timestamp + tag: set_tmp_ingest_timestamp + if: ctx.json?.timestamp == null && ctx.json?.detected_at != null + - script: + lang: painless + tag: set_timestamp_api_max_lifecycle + description: >- + Sets @timestamp to the most recent of detected_at/resolved_at/blocks_device_at + (capped at now) so the document reflects the state change that triggered + this fetch, not always the issue's original detection time. if: ctx.json?.timestamp == null && ctx.json?.detected_at != null + source: |- + ZonedDateTime now = (ZonedDateTime) ctx._tmp.ingest_timestamp; + ZonedDateTime max = ZonedDateTime.parse(ctx.json.detected_at); + if (ctx.json.resolved_at != null) { + ZonedDateTime resolved = ZonedDateTime.parse(ctx.json.resolved_at); + if (resolved.isAfter(max)) { max = resolved; } + } + if (ctx.json.blocks_device_at != null) { + ZonedDateTime blocked = ZonedDateTime.parse(ctx.json.blocks_device_at); + if (blocked.isAfter(max)) { max = blocked; } + } + if (max.isAfter(now)) { max = now; } + ctx['@timestamp'] = max.format(DateTimeFormatter.ISO_INSTANT); # event.id: webhook delivery ULID (`json.id`) or API issue id (`json.id`). - rename: @@ -330,14 +356,21 @@ processors: tag: categorize ignore_missing_pipeline: true - # Deduplication: CEL cursor uses an inclusive detected_at boundary, so the last - # record may be re-collected. Fingerprint event.id to _id so polls upsert state. + # Deduplication: CEL cursor's inclusive detected_at boundary can re-collect + # the last record, so fingerprint drops duplicates. resolved_at, blocked and + # blocks_device_at are included so pending/blocked/resolved states of the same + # states of the same issue fingerprint to distinct _ids instead of collapsing. - fingerprint: fields: - event.id + - kolide.issues.detected_at + - kolide.issues.resolved_at + - _tmp.blocked + - kolide.issues.blocks_device_at target_field: _id method: SHA-256 - tag: fingerprint_event_id + ignore_missing: true + tag: fingerprint_event_id_detected_at_blocks_device_at_blocked_resolved_at if: ctx.event?.id != null && ctx.event.id != '' # Cleanup. diff --git a/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/webhook.yml b/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/webhook.yml index 7e7ede187b9..d4a92c3f768 100644 --- a/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/webhook.yml +++ b/packages/kolide/data_stream/issues/elasticsearch/ingest_pipeline/webhook.yml @@ -67,6 +67,20 @@ processors: target_field: kolide.issues.check.tags tag: rename_check_tags_webhook ignore_missing: true + - date: + field: json.timestamp + target_field: kolide.issues.resolved_at + formats: + - ISO8601 + tag: date_resolved_at_webhook + if: ctx.json?.timestamp != null && ctx.event?.action == 'issues.resolved' + - date: + field: json.timestamp + target_field: kolide.issues.detected_at + formats: + - ISO8601 + tag: date_detected_at_webhook + if: ctx.json?.timestamp != null && ctx.event?.action == 'issues.new' on_failure: - append: diff --git a/packages/kolide/data_stream/issues/fields/base-fields.yml b/packages/kolide/data_stream/issues/fields/base-fields.yml index 45ab50301c5..c6df543830d 100644 --- a/packages/kolide/data_stream/issues/fields/base-fields.yml +++ b/packages/kolide/data_stream/issues/fields/base-fields.yml @@ -1,20 +1,16 @@ - name: data_stream.type - type: constant_keyword - description: Data stream type. + external: ecs - name: data_stream.dataset - type: constant_keyword - description: Data stream dataset. + external: ecs - name: data_stream.namespace - type: constant_keyword - description: Data stream namespace. + external: ecs - name: event.module + external: ecs type: constant_keyword - description: Event module. value: kolide - name: event.dataset + external: ecs type: constant_keyword - description: Event dataset. value: kolide.issues - name: '@timestamp' - type: date - description: Event timestamp. + external: ecs diff --git a/packages/kolide/data_stream/issues/fields/fields.yml b/packages/kolide/data_stream/issues/fields/fields.yml index 9ceed5de6fe..fbc0ee2275f 100644 --- a/packages/kolide/data_stream/issues/fields/fields.yml +++ b/packages/kolide/data_stream/issues/fields/fields.yml @@ -22,10 +22,10 @@ description: Whether the issue has been exempted from blocking the device (API only). - name: detected_at type: date - description: Timestamp at which the issue was first detected (API only). + description: Timestamp at which the issue was first detected (API), or the webhook delivery time for `issues.new` webhook deliveries. - name: resolved_at type: date - description: Timestamp at which the issue was resolved, if any (API only). + description: Timestamp at which the issue was resolved, if any (API), or the webhook delivery time for `issues.resolved` webhook deliveries. - name: blocks_device_at type: date description: Timestamp at which the issue will begin blocking the device (API only). diff --git a/packages/kolide/data_stream/issues/sample_event.json b/packages/kolide/data_stream/issues/sample_event.json index fe368cd2939..99a9bfa90bd 100644 --- a/packages/kolide/data_stream/issues/sample_event.json +++ b/packages/kolide/data_stream/issues/sample_event.json @@ -1,40 +1,41 @@ { - "@timestamp": "2023-10-28T20:50:15.000Z", + "@timestamp": "2023-11-04T20:50:15.000Z", "agent": { - "ephemeral_id": "7429995a-4016-41dc-9ca9-92589f75758b", - "id": "583c03ad-a4d1-45e8-b155-49c05bac1c14", - "name": "elastic-agent-31084", + "ephemeral_id": "ca392310-3081-40aa-8dc2-593fbd4e68c0", + "id": "3034cebb-69a8-4e14-9ef7-9080f748e9a0", + "name": "elastic-agent-79628", "type": "filebeat", - "version": "8.19.0" + "version": "9.4.3" }, "data_stream": { "dataset": "kolide.issues", - "namespace": "94759", + "namespace": "18609", "type": "logs" }, "ecs": { "version": "9.4.0" }, "elastic_agent": { - "id": "583c03ad-a4d1-45e8-b155-49c05bac1c14", + "id": "3034cebb-69a8-4e14-9ef7-9080f748e9a0", "snapshot": false, - "version": "8.19.0" + "version": "9.4.3" }, "event": { - "action": "issue", + "action": "blocked", "agent_id_status": "verified", "category": [ "configuration" ], "dataset": "kolide.issues", "id": "9999", - "ingested": "2026-06-26T19:47:03Z", + "ingested": "2026-07-13T16:44:23Z", "kind": "event", + "module": "kolide", "original": "{\"blocks_device_at\":\"2023-11-04T20:50:15Z\",\"check_information\":{\"identifier\":\"71\",\"link\":\"https://api.example.com/checks/71\"},\"detected_at\":\"2023-10-28T20:50:15Z\",\"device_information\":{\"identifier\":\"1\",\"link\":\"https://api.example.com/devices/1\"},\"exempted\":false,\"id\":\"9999\",\"issue_key\":\"bundle_id\",\"issue_value\":\"com.example.app\",\"last_rechecked_at\":\"2023-10-28T21:00:58Z\",\"resolved_at\":null,\"title\":\"macOS Firewall is Disabled\",\"value\":{\"firewall_enabled\":false}}", "outcome": "failure", "start": "2023-10-28T20:50:15.000Z", "type": [ - "creation" + "change" ] }, "host": { @@ -60,7 +61,7 @@ "last_rechecked_at": "2023-10-28T21:00:58.000Z", "title": "macOS Firewall is Disabled", "value": { - "firewall_enabled": false + "firewall_enabled": "false" } } }, diff --git a/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json b/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json index 3207876f372..91cad45d352 100644 --- a/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json +++ b/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json @@ -119,6 +119,41 @@ "ip_address": "198.51.100.23", "description": "Enabled check 'iTerm2 - Require Secure Keyboard Entry to Be Enabled'" } + }, + { + "event": "requests.issue_exemption", + "id": "webhook-exemption-001", + "timestamp": "2024-03-13T14:15:00Z", + "data": { + "device_id": "200003", + "device_name": "example-windows-pc", + "person_email": "carol.nguyen@example.com", + "message": "Travel exception requested", + "issues": [ + { + "issue_id": "8888", + "issue_url": "https://api.example.com/issues/8888" + } + ] + } + }, + { + "event": "requests.registration", + "id": "webhook-registration-001", + "timestamp": "2024-03-13T15:00:00Z", + "data": { + "device": { + "id": "200004", + "name": "example-linux-workstation", + "url": "https://api.example.com/devices/200004" + }, + "requester": { + "id": "100004", + "email": "dana.lee@example.com", + "url": "https://api.example.com/people/100004" + }, + "message": "Please approve this device" + } } ] } \ No newline at end of file diff --git a/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json-expected.json b/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json-expected.json index 1b7e1a72e98..b05322e9024 100644 --- a/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json-expected.json +++ b/packages/kolide/data_stream/webhook/_dev/test/pipeline/test-kolide-webhook-pipeline.json-expected.json @@ -206,6 +206,61 @@ "id": "01JA67B1DYJCKJ1J73T0F5EWGR", "timestamp": "2024-10-14T19:16:05Z" } + }, + { + "data_stream": { + "dataset": "kolide.request", + "namespace": "default", + "type": "logs" + }, + "ecs": { + "version": "9.4.0" + }, + "json": { + "data": { + "device_id": "200003", + "device_name": "example-windows-pc", + "issues": [ + { + "issue_id": "8888", + "issue_url": "https://api.example.com/issues/8888" + } + ], + "message": "Travel exception requested", + "person_email": "carol.nguyen@example.com" + }, + "event": "requests.issue_exemption", + "id": "webhook-exemption-001", + "timestamp": "2024-03-13T14:15:00Z" + } + }, + { + "data_stream": { + "dataset": "kolide.request", + "namespace": "default", + "type": "logs" + }, + "ecs": { + "version": "9.4.0" + }, + "json": { + "data": { + "device": { + "id": "200004", + "name": "example-linux-workstation", + "url": "https://api.example.com/devices/200004" + }, + "message": "Please approve this device", + "requester": { + "email": "dana.lee@example.com", + "id": "100004", + "url": "https://api.example.com/people/100004" + } + }, + "event": "requests.registration", + "id": "webhook-registration-001", + "timestamp": "2024-03-13T15:00:00Z" + } } ] } diff --git a/packages/kolide/data_stream/webhook/fields/base-fields.yml b/packages/kolide/data_stream/webhook/fields/base-fields.yml index 88cb10f3c1c..b0f7fbdba64 100644 --- a/packages/kolide/data_stream/webhook/fields/base-fields.yml +++ b/packages/kolide/data_stream/webhook/fields/base-fields.yml @@ -1,20 +1,16 @@ - name: data_stream.type - type: constant_keyword - description: Data stream type. + external: ecs - name: data_stream.dataset - type: constant_keyword - description: Data stream dataset. + external: ecs - name: data_stream.namespace - type: constant_keyword - description: Data stream namespace. + external: ecs - name: event.module + external: ecs type: constant_keyword - description: Event module. value: kolide - name: event.dataset + external: ecs type: constant_keyword - description: Event dataset. value: kolide.webhook - name: '@timestamp' - type: date - description: Event timestamp. + external: ecs diff --git a/packages/kolide/data_stream/webhook/manifest.yml b/packages/kolide/data_stream/webhook/manifest.yml index cff5b7b362c..130f2039dc9 100644 --- a/packages/kolide/data_stream/webhook/manifest.yml +++ b/packages/kolide/data_stream/webhook/manifest.yml @@ -5,7 +5,7 @@ streams: - input: http_endpoint title: "Kolide events via webhooks" description: |- - Receive all Kolide webhook events on a single endpoint. Events are automatically routed to the appropriate data stream (auth, issues, device, audit) based on the Kolide event type field. + Receive all Kolide webhook events on a single endpoint. Events are automatically routed to the appropriate data stream (auth, issues, request, device, audit) based on the Kolide event type field. template_path: http_endpoint.yml.hbs vars: - name: listen_address diff --git a/packages/kolide/data_stream/webhook/routing_rules.yml b/packages/kolide/data_stream/webhook/routing_rules.yml index b3a84823444..99e0783b5c6 100644 --- a/packages/kolide/data_stream/webhook/routing_rules.yml +++ b/packages/kolide/data_stream/webhook/routing_rules.yml @@ -10,6 +10,12 @@ namespace: - '{{data_stream.namespace}}' - default + - target_dataset: kolide.request + if: >- + ctx?.json?.event == 'requests.issue_exemption' || ctx?.json?.event == 'requests.registration' + namespace: + - '{{data_stream.namespace}}' + - default - target_dataset: kolide.device if: >- ctx?.json?.event == 'devices.created' || ctx?.json?.event == 'devices.registered' || ctx?.json?.event == 'devices.destroyed' || ctx?.json?.event == 'device_trust.status_changed' diff --git a/packages/kolide/docs/README.md b/packages/kolide/docs/README.md index 0cb9ed0c6e3..5710851086e 100644 --- a/packages/kolide/docs/README.md +++ b/packages/kolide/docs/README.md @@ -1,48 +1,89 @@ + # Kolide Integration for Elastic ## Overview -The Kolide integration for Elastic collects device-trust and endpoint-compliance logs from [Kolide](https://www.kolide.com/) (by 1Password). It ingests authentication sessions, posture issues, device inventory and trust-status changes, and administrative audit events, normalizes them to the Elastic Common Schema (ECS), and makes them available for search, visualization, and detection in Elastic. +The Kolide integration for Elastic collects device-trust and endpoint-compliance logs from Kolide (by 1Password). It ingests authentication sessions, posture issues, approval-workflow requests, device inventory, trust-status changes, people identity records, and administrative audit events. The integration normalizes these logs to the Elastic Common Schema (ECS) so you can use them for search, visualization, and detection in Elastic. ### Compatibility -This integration works with the current Kolide Device Trust platform ("Kolide K2") and its public REST API (version `2026-04-07`) and webhooks. It does not cover the legacy open-source Kolide Fleet (osquery) product. +This integration works with the current Kolide Device Trust platform ("Kolide K2"), its public REST API (version `2026-04-07`), and webhooks. It doesn't support the legacy open-source Kolide Fleet (osquery) product. + +This integration is compatible with Elastic Stack version 8.19.0 or later. ### How it works -The integration supports three collection methods that you can choose between (and combine) when configuring it: +The integration supports four collection methods that you can choose between and combine when you configure it: -- Webhooks (HTTP endpoint): Kolide pushes events in near real time to an HTTP endpoint exposed by the Elastic Agent. This is the recommended method for low-latency device-compliance data. Each delivery is signed with an HMAC-SHA256 signature for verification. -- REST API (polling): the Elastic Agent periodically polls the Kolide REST API and collects new records using cursor-based pagination and a timestamp filter. This is useful for backfill and for fuller resource records. -- AWS S3 (Kolide Log Pipeline): Kolide's Log Pipeline writes objects to a customer-owned S3 bucket under per-type key prefixes (defaults: `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`); the Elastic Agent reads each prefix with an `aws-s3` input (SQS notifications or direct bucket polling). The `auth` and `audit` data streams can read their respective prefixes, and the dedicated `device_check` data stream reads `kolide/check_runs/`. S3 is the most complete source for check-run history — it includes passing, inapplicable, and unknown check results in addition to failures. Raw osquery `results` objects are not ingested. +- Webhooks (HTTP endpoint): Kolide pushes events in near real time to an HTTP endpoint that Elastic Agent exposes. This is the recommended method for low-latency device-compliance data. Each delivery is signed with an HMAC-SHA256 signature for verification. +- REST API (polling): Elastic Agent periodically polls the Kolide REST API and collects records using cursor-based pagination and timestamp filters where supported. This is useful for backfill and for fuller resource records. +- AWS S3 (Kolide Log Pipeline): Kolide's Log Pipeline writes objects to a customer-owned S3 bucket under per-type key prefixes (default values are `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`, `kolide/results/`, and `kolide/status/`). Elastic Agent reads each prefix using an `aws-s3` input through SQS notifications or direct bucket polling. The `auth` and `audit` data streams can read their respective prefixes. The dedicated `device_check` data stream reads `kolide/check_runs/`, and the dedicated `osquery_result` and `osquery_status` data streams read `kolide/results/` and `kolide/status/`, which are the raw osquery result and status logs. The Log Pipeline is the most complete source for check-run history because it includes passing, inapplicable, and unknown check results in addition to failures. +- Google Cloud Storage (Kolide Log Pipeline): The same Log Pipeline data is written to customer-owned GCS buckets under the same per-type key prefixes and read using a `gcs` input through bucket polling. The object payloads are identical to the S3 delivery, so the same `auth`, `audit`, `device_check`, `osquery_result`, and `osquery_status` data streams apply. You can choose S3 or GCS depending on which cloud your Kolide log destination targets. ## What data does this integration collect? The Kolide integration collects the following data streams: -* `webhook`: single webhook ingress that receives all Kolide webhook event types on one endpoint and routes each event to the correct data stream automatically. -* `auth`: SSO authentication sessions (`auth_logs.success`, `auth_logs.failure`; API `GET /auth_logs`). -* `issues`: device posture-check failures and resolutions (`issues.new`, `issues.resolved`; API `GET /issues`). -* `device`: device inventory and trust-status changes (`devices.created`, `devices.registered`, `devices.destroyed`, `device_trust.status_changed`; API `GET /devices`). -* `audit`: administrative audit log of console actions (`audit_log.recorded`; API `GET /audit_logs`; Log Pipeline S3 `kolide/audit_logs/`). -* `device_check`: device check-run results from the Log Pipeline (S3 `kolide/check_runs/`), covering every run — `passing`, `failing`, `inapplicable`, and `unknown`. This complements the failure-focused `issues` data stream. +- `webhook`: A single webhook ingress that receives all Kolide webhook event types on one endpoint and routes each event to the correct data stream automatically. +- `auth`: SSO authentication sessions (`auth_logs.success` and `auth_logs.failure` using the API endpoint `GET /auth_logs`). +- `issues`: Device posture-check failures and resolutions (`issues.new` and `issues.resolved` using the API endpoint `GET /issues`). +- `request`: Approval-workflow requests (`requests.issue_exemption` and `requests.registration` using the API endpoints `GET /exemption_requests` and `GET /registration_requests`, as well as request webhooks). +- `device`: Device inventory and trust-status changes (`devices.created`, `devices.registered`, `devices.destroyed`, and `device_trust.status_changed` using the API endpoint `GET /devices`). +- `people`: Identity records for people known to Kolide using the API endpoint `GET /people`. +- `deprovisioned_person`: Identity records for people who have been offboarded or deprovisioned in Kolide using the API endpoint `GET /deprovisioned_people`. This is a separate resource from `people`. +- `audit`: Administrative audit logs of console actions (`audit_log.recorded` using the API endpoint `GET /audit_logs` or Log Pipeline S3/GCS paths under `kolide/audit_logs/`). +- `device_check`: Device check-run results from the Log Pipeline (S3/GCS paths under `kolide/check_runs/`), covering every run including `passing`, `failing`, `inapplicable`, and `unknown` statuses. This complements the failure-focused `issues` data stream. +- `osquery_result`: Raw osquery Result Logs from the Log Pipeline (S3/GCS paths under `kolide/results/`), covering both snapshot-query rows and differential (`added` and `removed`) rows. Per-query column data is stored as a flattened field rather than mapped per column, since it is arbitrary and depends on the target osquery table or custom SQL. +- `osquery_status`: Raw osquery Status Logs from the Log Pipeline (S3/GCS paths under `kolide/status/`), which contain GLOG-style telemetry about the osquery daemon itself rather than host inventory state. + +The `auth` and `audit` data streams also support the Log Pipeline using the `aws-s3` and `gcs` inputs that read the `kolide/auth_logs/` and `kolide/audit_logs/` prefixes. + +### Osquery result and status details + +The `osquery_result` and `osquery_status` data streams ingest raw osquery agent logs, unlike the other Log Pipeline streams in this integration (`auth`, `audit`, and `device_check`), which are Kolide's own structured logs. The integration populates `host.id` and `host.name` from Kolide's `kolide_decorations` block. This block is only present when the device is enrolled with Kolide's own launcher. A bare open-source osquery deployment shipping logs through the Log Pipeline only carries osquery's own `hostIdentifier` (stored in `kolide.osquery_result.host_identifier` and `kolide.osquery_status.host_identifier`), and `host.id` and `host.name` do not populate. Per-query row data (`kolide.osquery_result.added`, `kolide.osquery_result.removed`, and `kolide.osquery_result.snapshot`) is a `flattened` field rather than a per-column mapping, since the columns are arbitrary and depend on the target osquery table or custom SQL. This keeps the mapping bounded, but means individual columns do not get native Kibana Lens numeric or date typing, or exact-match aggregations. + +### Event outcome for posture data + +For the `device_check` and `issues` data streams, `event.outcome` reflects the device posture result rather than the success of event processing. A check run with status `passing` (or a resolved issue) maps to `event.outcome: success`. A check run with status `failing` (or an open issue) maps to `event.outcome: failure`. An `inapplicable` or `unknown` check status maps to `event.outcome: unknown`. The integration preserves the raw posture state in `kolide.device_check.status` for `device_check`. + +### Host correlation for device checks -The `auth` and `audit` data streams additionally support the Log Pipeline via an `aws-s3` input that reads the `kolide/auth_logs/` and `kolide/audit_logs/` prefixes. +Check-run results identify the device only by its numeric Kolide device ID, which maps to `host.id`. The payload carries no hostname, so the integration does not set `host.name` on this data stream. You can correlate check runs with the `device`, `auth`, and `issues` data streams using the shared `host.id`. If you need `host.name` directly on check-run documents, you must enrich them at ingest time with an Elasticsearch [enrich policy](https://www.elastic.co/docs/manage-data/ingest/transform-enrich/data-enrichment) that maps `host.id` to `host.name` from the `device` data stream. This setup requires you to enable the `device` data stream and periodically refresh the enrich policy so new or renamed devices resolve correctly. -> **Note on `event.outcome` for posture data:** For the `device_check` and `issues` data streams, `event.outcome` reflects the device posture result, not the success of event processing. A check run with status `passing` (or a resolved issue) maps to `event.outcome: success`, `failing` (or an open issue) maps to `event.outcome: failure`, and `inapplicable` or `unknown` check statuses map to `event.outcome: unknown`. The raw posture state is also preserved in `kolide.device_check.status` for `device_check`. +### Document identity for requests -> **Note on host correlation for `device_check`:** Check-run results identify the device only by its numeric Kolide device ID, mapped to `host.id`. The payload carries no hostname, so `host.name` is not set on this data stream. Correlate check runs with the `device`, `auth`, and `issues` data streams using the shared `host.id`. If you need `host.name` directly on check-run documents, enrich them at ingest time with an Elasticsearch [enrich policy](https://www.elastic.co/docs/manage-data/ingest/transform-enrich/data-enrichment) that maps `host.id` to `host.name` from the `device` data stream. This requires the `device` data stream to be enabled and the enrich policy to be executed and periodically refreshed so new or renamed devices resolve. +The Kolide REST API endpoints `GET /exemption_requests` and `GET /registration_requests` do not support a modified-since filter, so the integration re-fetches every request on every poll. To prevent duplicate indexing of unchanged requests, the integration deduplicates documents using the request identity (a combination of `kolide.request.id` and `kolide.request.type`), its current status, and decision notes. This means the `request` data stream reflects each request's latest known status. It provides one document per request that is updated as its status changes, rather than a full history of every transition. Kolide allows reopening a previously approved or denied request, meaning a request can cycle through the same status multiple times. If a request is re-decided with the exact same status and decision note text as a previous decision, the integration deduplicates it as a duplicate event. To view the full timeline of who approved, denied, or reopened a request, use the `audit` data stream (`audit_log.recorded`), and correlate the events using `user.target.email` and `rule.name`. + +### Document identity for people + +The endpoint `GET /people` returns a full-table snapshot with no modified-since filter, so the integration re-fetches every person on every poll. To prevent unnecessary indexing, the integration deduplicates documents using a fingerprint of the entire raw record, excluding `last_authenticated_at`. This exclusion prevents a new document from being created every time an active person authenticates. A change to any other field (such as name, email, registered-device status, or SCIM usernames) produces a new document, while unchanged records are deduplicated across polls. ### Supported use cases -Monitoring device-trust posture, investigating SSO authentication outcomes alongside device compliance state, tracking device enrollment and blocking transitions, and auditing administrative changes in Kolide — all correlated with the rest of your security data in Elastic via ECS. +Integrating Kolide with Elastic provides a powerful solution for enhancing security posture and operational visibility. You can use this integration for the following use cases: + +- Monitor device-trust posture and investigate SSO authentication outcomes alongside device compliance state. +- Track approval workflows, device enrollment, and blocking transitions. +- Correlate device activity with identity records of people. +- Audit administrative changes in Kolide. +- Correlate your Kolide device trust data with the rest of your security data in Elastic using the Elastic Common Schema (ECS). ## What do I need to use this integration? -- Elastic Agent installed on a host that can receive Kolide webhooks (a publicly reachable HTTPS endpoint), reach `https://api.kolide.com`, or read from your AWS S3 bucket or SQS queue. +Before you set up the Kolide integration, you must have the following: - A Kolide tenant with Full Access administrator privileges to create API keys, webhook endpoints, or Log Pipeline destinations. +- An Elastic Agent installed on a host. Depending on your chosen ingestion method, the host must meet the following network requirements: + - Receive Kolide webhooks on a publicly reachable HTTPS endpoint. + - Reach the Kolide REST API at `https://api.kolide.com`. + - Access your AWS S3 bucket or Amazon Simple Queue Service (SQS) queue. + - Access your Google Cloud Storage (GCS) bucket. + +If you're collecting data using the REST API or the Log Pipeline, you must also configure the following resources: +- A Kolide API key with the form `k2sk_v1_` created in your Kolide console under Settings → Developers → API Keys. +- An AWS Identity and Access Management (IAM) role or credentials with permissions to read from your AWS S3 bucket or SQS queue, if you use AWS. +- A Google Cloud Platform (GCP) service account JSON key with the Storage Object Viewer role to read from your GCS bucket, if you use GCP. ## How do I deploy this integration? @@ -50,51 +91,159 @@ Monitoring device-trust posture, investigating SSO authentication outcomes along Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html). You can install only one Elastic Agent per host. +Elastic Agent is required to receive webhook requests, poll the REST API, or read from S3 or GCS buckets and ship the data to Elastic, where the events will then be processed using the integration's ingest pipelines. + +### Agentless deployment + +Agentless deployments are only supported in Elastic Serverless and Elastic Cloud environments. Agentless deployments provide a means to ingest data while avoiding the orchestration, management, and maintenance needs associated with standard ingest infrastructure. Using an agentless deployment makes manual agent deployment unnecessary, allowing you to focus on your data instead of the agent that collects it. + +For more information, refer to [Agentless integrations](https://www.elastic.co/guide/en/serverless/current/security-agentless-integrations.html) and [Agentless integrations FAQ](https://www.elastic.co/guide/en/serverless/current/agentless-integration-troubleshooting.html). + ### Set up steps in Kolide -As a Full Access administrator, sign in to Kolide and choose one or more collection methods: +To set up steps in Kolide, you must have full access administrator privileges. Sign in to Kolide and choose one or more of the collection methods below. -For webhooks: -1. Go to Settings → Developers → Webhooks and add **one** new endpoint. -2. Provide a publicly reachable HTTPS URL pointing at the Elastic Agent's listening address, port, and path (for example, `https://:9550/kolide/webhook`). -3. Subscribe the endpoint to **all** event types — the integration routes each event to the correct data stream automatically. -4. Copy the endpoint signing secret (shown once) — you will provide it to the integration as the HMAC key. +#### Webhooks setup -For the REST API: -1. Go to Settings → Developers → API Keys and create a new key (read access is sufficient). -2. Copy the API key (shown once); it has the form `k2sk_v1_...`. +To configure Kolide webhooks, complete the following steps: +1. Log in to your Kolide account and navigate to Settings, then Developers, and then Webhooks. +2. Select Add Webhook and create one new endpoint. +3. Provide a publicly reachable HTTPS URL pointing at the Elastic Agent listen address, port, and path, such as `https://:9550/kolide/webhook` (replace `` with the actual address or hostname of your Elastic Agent). +4. Subscribe the endpoint to all event types. The integration automatically routes each event to the correct data stream. +5. Copy the signing secret displayed on screen. This secret is shown only once and is required to configure the HMAC key on the Elastic side. -For the AWS S3 Log Pipeline: -1. In Kolide, go to Log Destinations and add a new Amazon S3 Bucket destination. -2. Choose STS (recommended): create an IAM role in your own AWS account whose trust policy allows Kolide's AWS account (`516897320088`) to assume it, gated by the External ID that Kolide displays. Grant the role `s3:GetBucketLocation`, `s3:GetObject`, and `s3:PutObject` on the bucket so Kolide can write logs. -3. Select the log types to deliver (authentication logs, audit logs, and check results) and, optionally, customize the object key template. -4. On the read side, the Elastic Agent uses your own AWS credentials (not Kolide's role). For SQS mode, configure an S3 event notification (`s3:ObjectCreated:*`) to an SQS queue and grant the reader `s3:GetObject` plus `sqs:ReceiveMessage`, `sqs:DeleteMessage`, and `sqs:GetQueueAttributes`. For direct polling, grant `s3:GetObject` and `s3:ListBucket`. Add `kms:Decrypt` if the bucket uses SSE-KMS. +#### REST API setup -Note: Kolide sends webhooks from dynamic AWS us-east-1 IP addresses, so IP allow-listing is not a reliable control — rely on the HMAC signature instead. +To configure the REST API, complete the following steps: +1. Log in to your Kolide account and navigate to Settings, then Developers, and then API Keys. +2. Select Create API Key. Read access is sufficient to retrieve logs. +3. Copy the API key. It is displayed only once and has the form `k2sk_v1_` followed by your token. + +#### AWS S3 log pipeline setup + +To configure the AWS S3 log pipeline, complete the following steps: +1. In Kolide, navigate to Log Destinations and select Amazon S3 Bucket to add a new destination. +2. Select the STS authorization method, which is the recommended approach. +3. Create an IAM role in your AWS account. Update the trust policy to allow Kolide's AWS account ID `516897320088` to assume the role, and restrict access using the External ID displayed in the Kolide console. +4. Grant the IAM role permissions for `s3:GetBucketLocation`, `s3:GetObject`, and `s3:PutObject` on your S3 bucket so Kolide can write logs. +5. Select the log types you want to deliver. The supported log types include authentication logs, audit logs, check results, and osquery Result or Status logs. +6. Configure the read permissions. The Elastic Agent reads the logs from your AWS S3 bucket and does not use Kolide's IAM role. You must configure the Elastic Agent with AWS credentials that have read access. +7. For SQS notification mode, configure an S3 event notification for `s3:ObjectCreated:*` to deliver notifications to your SQS queue. Grant your Elastic Agent IAM reader credentials the permissions for `s3:GetObject` on the bucket and `sqs:ReceiveMessage`, `sqs:DeleteMessage`, and `sqs:GetQueueAttributes` on the SQS queue. +8. For direct polling mode, grant your Elastic Agent IAM reader credentials the permissions for `s3:GetObject` and `s3:ListBucket` on the bucket. +9. If your bucket is encrypted using SSE-KMS, ensure the Elastic Agent IAM reader credentials also have `kms:Decrypt` permissions on the KMS key. + +#### Google Cloud Storage log pipeline setup + +To configure the Google Cloud Storage log pipeline, complete the following steps: +1. Log in to your Google Cloud Console, select your project, and create a GCS bucket. +2. Create a service account that can enumerate, read, and write objects in the bucket by granting it the Storage Object Admin role on the bucket, then generate a JSON key for this service account. +3. Log in to Kolide, navigate to Log Destinations, select GCP Storage Bucket, and enter a display name and the bucket name. +4. Paste the complete service account JSON key file contents into the field provided. +5. Select the log types to deliver. This integration supports Administrator Audit Logs, User Authentication Logs, Device Check Run Logs, and osquery Result and Status Logs. Keep the default object path templates because they match the integration's default file selectors. +6. Create a separate service account with read-only access (the Storage Object Viewer role) and generate a JSON key for it. The Elastic Agent uses this key to poll the bucket. Alternatively, if the Elastic Agent runs on a GCE or GKE instance, you can leave the credentials blank to use Application Default Credentials. #### Vendor resources + +The following resources provide additional information about setting up Kolide integrations: - [Kolide Webhooks documentation](https://www.kolide.com/docs/developers/webhooks) - [Kolide REST API reference](https://kolideapi.readme.io/reference) - [Kolide Log Pipeline documentation](https://www.kolide.com/docs/admins/log-pipeline/overview) +- [Configuring Google Cloud Storage for the Log Pipeline](https://www.kolide.com/docs/using-kolide/log-pipeline/configuring-google-cloud-storage) ### Set up steps in Kibana -1. In Kibana, go to Management → Integrations and search for Kolide. -2. Add the integration. -3. For webhooks: enable the `webhook` data stream (HTTP endpoint input). Set the listen address, port, and URL path, and provide the HMAC signing secret (and optionally the `X-Kolide-Webhook-Identifier` value). All Kolide event types are received on this single endpoint and routed automatically. -4. For the REST API: enable whichever data streams you want to poll (auth, issues, device, audit), select the CEL input, provide the API URL (`https://api.kolide.com`), the API key, and adjust the polling interval and initial lookback as needed. -5. For AWS S3 (Log Pipeline): provide your AWS credentials once on the integration, then enable the `aws-s3` input on the data streams you want — `auth`, `audit`, or `device_check`. Each defaults to its Kolide prefix (`kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`). For each, set either an SQS queue URL (SQS mode) or a bucket ARN (polling mode). In SQS mode, use a separate queue per prefix (filter S3 notifications by prefix); in polling mode each stream lists only its own prefix. Adjust the bucket list prefix if your Kolide destination uses a custom key template. +To set up the Kolide integration in Kibana, complete the following steps: +1. In Kibana, navigate to Management, select Integrations, and search for Kolide. +2. Select the Kolide integration, and click Add Kolide. +3. Configure the settings based on your chosen collection methods. You can enable and configure webhooks, the REST API, or log pipeline inputs. + +#### Webhooks configuration + +Configure the following settings to receive webhook events: + +| Setting | Description | +| ----------------------- | --------------------------------------------------------------------------------------------- | +| Listen Address | Bind address for the HTTP listener. Use `0.0.0.0` to listen on all interfaces. | +| Listen Port | Bind port for the HTTP listener, such as `9550`. | +| URL Path | The URL path to accept Kolide webhook requests on, such as `/kolide/webhook`. | +| Webhook Signing Secret | The signing secret copied from the Kolide webhook settings. Used to verify HMAC signatures. | +| Webhook Identifier | The webhook endpoint identifier value from the Kolide webhook settings. | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | + +#### REST API configuration + +Configure the following settings to pull logs from the Kolide REST API: + +| Setting | Description | +| ----------------------- | --------------------------------------------------------------------------------------------- | +| URL | The base URL of the Kolide REST API. The default is `https://api.kolide.com`. | +| API Key | The Kolide API key used as a Bearer token. This key has the form `k2sk_v1_`. | +| Interval | How often the Kolide REST API is polled, such as `5m` (5 minutes). | +| Initial Interval | How far back to look the first time the integration runs, such as `24h` (24 hours). | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | + +#### AWS S3 log pipeline configuration + +Configure the following settings to collect logs from AWS S3: + +| Setting | Description | +| ----------------------- | ----------------------------------------------------------------------------------------------------------- | +| Access Key ID | The AWS access key ID the Elastic Agent uses to read from the bucket or queue. | +| Secret Access Key | The AWS secret access key the Elastic Agent uses to read from the bucket or queue. | +| Session Token | The AWS session token for temporary credentials, if using STS. | +| SQS Queue URL | URL of the SQS queue receiving S3 object-created notifications. | +| S3 Bucket ARN | ARN of the S3 bucket to poll directly if not using SQS notifications, such as `arn:aws:s3:::kolide-bucket`. | +| Bucket List Prefix | Prefix used to list objects in the bucket, such as `kolide/audit_logs/`. | +| Number of Workers | Number of workers that process the S3 objects or SQS messages. | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | + +#### Google Cloud Storage log pipeline configuration + +Configure the following settings to collect logs from Google Cloud Storage: + +| Setting | Description | +| ----------------------- | --------------------------------------------------------------------------------------------- | +| Project ID | The GCP project ID that the GCS bucket belongs to. | +| Service Account Key | The GCP service account JSON key contents with Storage Object Viewer read access. | +| GCS Buckets | The list of GCS buckets to poll in YAML format, specifying the bucket name. | +| File Selectors | A list of regular expression patterns to filter which object keys are processed. | +| Number of Workers | Number of workers that process the GCS objects. | +| Preserve Original Event | Check this option to preserve a raw copy of the original event in the `event.original` field. | ### Validation -After setup, generate or wait for activity in Kolide (for example, sign in via SSO to produce an auth log). In Kibana, open Discover and confirm documents are arriving in the `logs-kolide.*` data streams. +To validate that the integration is working properly and ingesting data into Elasticsearch, perform the following steps: +1. Generate activity in Kolide, such as logging in via Single Sign-On (SSO) to trigger an authentication event, or running a manual device check. +2. In Kibana, navigate to Discover. +3. In the data view dropdown, select logs-*. +4. Search for incoming documents using the search query: + ```kql + data_stream.dataset: "kolide.webhook" or data_stream.dataset: "kolide.audit" or data_stream.dataset: "kolide.auth" + ``` +5. Verify that documents appear with recent timestamps and contains expected event values. +6. Navigate to Dashboards and select the [Logs Kolide] Overview dashboard to confirm that the visualizations are successfully populated with data. ## Troubleshooting -- No data via webhooks: Confirm the Kolide endpoint URL matches the Agent's listen address, port, and path, that the endpoint is publicly reachable over HTTPS, and that the HMAC signing secret matches. -- Webhook signature failures: Ensure the configured HMAC key equals the Kolide endpoint signing secret; Kolide signs the raw request body with HMAC-SHA256 and sends the lowercase hex digest in the `Authorization` header with no prefix. -- No data via the REST API: Verify the API key is valid (a 401 indicates a turned-off feature or bad token, and a 403 indicates the key lacks permission) and that the host can reach `https://api.kolide.com`. -- No data via AWS S3: Confirm the Elastic Agent credentials can `s3:ListBucket` and `s3:GetObject` on the bucket (and `sqs:ReceiveMessage` in SQS mode), that the bucket list prefix matches your Kolide object key template, and that SQS notifications are filtered to the correct prefix. Kolide writes to `kolide/auth_logs/`, `kolide/audit_logs/`, and `kolide/check_runs/` by default; osquery `results/` objects are not ingested. +For help with Elastic ingest tools, check [Common problems](https://www.elastic.co/docs/troubleshoot/ingest/fleet/common-problems). + +### Common configuration issues + +If you encounter issues with your Kolide integration, use the following solutions to resolve them: + +- No data from webhooks: Confirm the Kolide endpoint URL matches the Agent's listen address, port, and path. Verify that the endpoint is publicly reachable over HTTPS and that the HMAC signing secret matches. +- Webhook signature failures: Ensure the configured HMAC key matches the Kolide endpoint signing secret. Kolide signs the raw request body with HMAC-SHA256 and sends the lowercase hex digest in the `Authorization` header with no prefix. +- No data using the REST API: Verify the API key is valid. A 401 error code indicates a disabled feature or bad token, and a 403 error code indicates the key lacks permission. Confirm that the host can reach `https://api.kolide.com`. +- No data from AWS S3: Confirm the Elastic Agent credentials have permissions to run `s3:ListBucket` and `s3:GetObject` on the bucket. If you're using SQS mode, ensure the credentials have permissions for `sqs:ReceiveMessage`. Check that the bucket list prefix matches your Kolide object key template, and verify that SQS notifications are filtered to the correct prefix. Kolide writes to `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`, `kolide/results/`, and `kolide/status/` by default. +- No data from Google Cloud Storage: Confirm the project ID and bucket name are correct. Ensure that the reader service account has the `Storage Object Viewer` role on the bucket. Verify that each stream's file selector regex matches your Kolide object key template. By default, the templates expect the `kolide/auth_logs/`, `kolide/audit_logs/`, `kolide/check_runs/`, `kolide/results/`, and `kolide/status/` prefixes. +- No host ID or host name on osquery result or osquery status documents: These fields are populated from Kolide's `kolide_decorations` block, which requires the device to be enrolled with Kolide's own launcher. A bare open-source osquery deployment shipping logs through the Log Pipeline only carries `kolide.osquery_result.host_identifier` or `kolide.osquery_status.host_identifier` (osquery's own `hostIdentifier`), not the Kolide-decorated host fields. + +### Vendor resources + +For more details on configuring Kolide, check the following resources: + +- [Kolide Developer API Documentation](https://developer.kolide.com) +- [Kolide Log Pipeline Documentation](https://k2.kolide.com/x/features/log-pipeline) ## Performance and scaling @@ -102,18 +251,20 @@ For more information on architectures that can be used for scaling this integrat ### Choosing a transport per data stream -Kolide's Log Pipeline writes one log per S3 object rather than batching, so the AWS S3/SQS input makes a separate fetch for every document. For high-volume streams this is fine, but for small, sparse streams it adds many network round-trips and can make large backlogs slow to drain. To keep latency low and avoid contention on a shared S3 queue, consider matching the transport to the stream: +Kolide's Log Pipeline writes one log per object rather than batching, so the AWS S3/SQS and GCS inputs make a separate fetch for every document. For high-volume streams this is fine, but for small, sparse streams it adds many network round-trips and can make large backlogs slow to drain. To keep latency low and avoid contention on a shared S3 queue, you can match the transport to the stream. -- **`audit` and `auth`**: prefer the REST API (CEL) or webhook inputs. These streams are typically small and sparse, and the API/webhook paths deliver them quickly without per-object S3 fetches. -- **`device_check` (check runs)**: use the AWS S3 input. This stream is large, so S3 is the better fit, and keeping it on S3 keeps the small, important streams off the same queue. +To optimize your ingestion, configure the transports using these guidelines: +- For `audit` and `auth` data streams, prefer the REST API (CEL) or webhook inputs. These streams are typically small and sparse, and the API or webhook paths deliver them quickly without per-object fetches. +- For `device_check`, `osquery_result`, and `osquery_status` data streams, use the AWS S3 or GCS input because they're the only collection methods available. These streams are typically large or high-volume. The `osquery_result` stream is especially large because every scheduled query execution can produce a log line, making object storage the appropriate fit. Keeping them in object storage also keeps the small, important streams off the same queue. -This split keeps the small streams responsive while still using S3 for the bulk data. +This split keeps the small streams responsive while still using object storage for the bulk data. -If you do consume large streams over S3/SQS, you can increase throughput by running multiple Elastic Agents (or scaling out workers) so SQS messages are processed concurrently. Note the one-object-per-log behavior is a Kolide-side limitation. The guidance above is a workaround until it is addressed upstream. +If you consume large streams over S3/SQS or GCS, you can increase throughput by running multiple Elastic Agents or scaling out workers to process objects concurrently. The one-object-per-log behavior is a Kolide-side limitation. This guidance is a workaround until Kolide addresses the issue upstream. ## Reference ### Inputs used + These inputs can be used with this integration:

      aws-s3 @@ -177,6 +328,19 @@ To collect logs via API endpoint, configure the following parameters: - Request interval (how often to fetch data)
      +gcs + +## Setup +For more details about the GCS input settings, check the [Filebeat documentation](https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-gcs). + +### Collecting logs from GCS + +To collect logs via GCS, select **Collect logs via GCS** and configure the following parameters: + +- Buckets: This attribute contains details related to specific buckets like `name`, `number_of_workers`, `poll`, `poll_interval`, and `bucket_timeout`. The attribute `name` is specific to a bucket as it describes the bucket name, while the fields `number_of_workers`, `poll`, `poll_interval` and `bucket_timeout` can exist at the bucket level and at the global level. If you defined the attributes globally, you can only specify the name in this YAML config. If you want to override any specific attribute for a specific bucket, you can define it here. Any attribute defined in the YAML will override the global definitions. Check the [Filebeat documentation](https://www.elastic.co/guide/en/beats/filebeat/8.5/filebeat-input-gcs.html#attrib-buckets) for further information. +- Project ID: This attribute is required for various internal operations with respect to authentication, creating storage clients and logging which are used internally for various processing purposes. +
      +
      http_endpoint ## Setup @@ -194,13 +358,19 @@ To collect logs via HTTP Endpoint, select **Collect logs via HTTP Endpoint** and ### API usage -These Kolide REST API endpoints are used by this integration: -* `GET /auth_logs` -* `GET /issues` -* `GET /devices` -* `GET /audit_logs` +The integration uses the following Kolide REST API endpoints to retrieve logs and telemetry: +- `GET /auth_logs` +- `GET /issues` +- `GET /exemption_requests` +- `GET /registration_requests` +- `GET /devices` +- `GET /people` +- `GET /deprovisioned_people` +- `GET /audit_logs` ### Vendor documentation links + +You can refer to the following vendor documentation for more details about Kolide features and APIs: - [Kolide documentation](https://www.kolide.com/docs) - [Kolide Webhooks](https://www.kolide.com/docs/developers/webhooks) - [Kolide REST API reference](https://kolideapi.readme.io/reference) @@ -208,9 +378,11 @@ These Kolide REST API endpoints are used by this integration: ### Data streams +This integration uses these data streams to organize collected logs and metrics: + #### webhook -The `webhook` data stream is the single ingress point for all Kolide webhook events. It listens on one HTTP endpoint and uses the ingest `reroute` processor to redirect each event to the appropriate target data stream (`auth`, `issues`, `device`, or `audit`) based on the Kolide event type. No documents are stored in the `webhook` data stream itself. +The `webhook` data stream is the single ingress point for all Kolide webhook events. It listens on one HTTP endpoint and uses the ingest `reroute` processor to redirect each event to the appropriate target data stream, such as `auth`, `issues`, `device`, or `audit`, based on the Kolide event type. No documents are stored in the `webhook` data stream itself. ##### webhook fields @@ -218,15 +390,15 @@ The `webhook` data stream is the single ingress point for all Kolide webhook eve | Field | Description | Type | |---|---|---| -| @timestamp | Event timestamp. | date | -| data_stream.dataset | Data stream dataset. | constant_keyword | -| data_stream.namespace | Data stream namespace. | constant_keyword | -| data_stream.type | Data stream type. | constant_keyword | +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | | ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | | error.message | Error message. | match_only_text | -| event.dataset | Event dataset. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | | event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | -| event.module | Event module. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | | input.type | Type of filebeat input. | keyword | | json | Working object used to hold the raw Kolide webhook envelope fields before the event is routed to the appropriate data stream. Contains event (event type string), id (ULID), timestamp, and data (event payload). Cleaned up by the target data stream pipeline after routing. | flattened | | log.offset | Log offset. | long | @@ -235,7 +407,7 @@ The `webhook` data stream is the single ingress point for all Kolide webhook eve #### auth -The `auth` data stream provides Kolide SSO authentication sessions, including the device-trust posture at sign-in, the client IP and geolocation, and the sub-events of the session. +The `auth` data stream provides Kolide SSO authentication sessions. This includes the device-trust posture at sign-in, the client IP address and geolocation, and the sub-events of the session. ##### auth fields @@ -243,25 +415,28 @@ The `auth` data stream provides Kolide SSO authentication sessions, including th | Field | Description | Type | |---|---|---| -| @timestamp | Event timestamp. | date | +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | | aws.s3.bucket.arn | The AWS S3 bucket ARN. | keyword | | aws.s3.bucket.name | The AWS S3 bucket name. | keyword | | aws.s3.object.key | The AWS S3 object key. | keyword | -| data_stream.dataset | Data stream dataset. | constant_keyword | -| data_stream.namespace | Data stream namespace. | constant_keyword | -| data_stream.type | Data stream type. | constant_keyword | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | | ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | | error.message | Error message. | match_only_text | | event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | | event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | -| event.dataset | Event dataset. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | | event.id | Unique ID to describe the event. | keyword | | event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | -| event.module | Event module. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | | event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | | event.outcome | This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense. | keyword | | event.start | `event.start` contains the date when the event started or when the activity was first observed. | date | | event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| gcs.storage.bucket.name | The GCS bucket name. | keyword | +| gcs.storage.object.content_type | The content type of the GCS object. | keyword | +| gcs.storage.object.name | The GCS object name. | keyword | | host.hostname | Hostname of the host. It normally contains what the `hostname` command returns on the host machine. | keyword | | host.id | Unique host id. As hostname is not always unique, use values that are meaningful in your environment. Example: The current usage of `beat.name`. | keyword | | host.name | Name of the host. It can contain what hostname returns on Unix systems, the fully qualified domain name (FQDN), or a name specified by the user. The recommended value is the lowercase FQDN of the host. | keyword | @@ -318,26 +493,29 @@ An example event for `auth` looks as following: ```json { - "@timestamp": "2024-03-11T21:28:17.000Z", + "@timestamp": "2026-06-11T16:29:17.000Z", "agent": { - "ephemeral_id": "a7e8f0c3-3f3c-4df1-a711-dca5f997077c", - "id": "d9df3829-c2e0-4721-8242-1cf13796bbc4", - "name": "elastic-agent-47734", + "ephemeral_id": "ead84309-61e4-4649-884b-5c2bbcb28888", + "id": "dccea145-284f-4566-914a-d93ed70b44fc", + "name": "elastic-agent-96605", "type": "filebeat", - "version": "9.4.1" + "version": "8.19.0" + }, + "cloud": { + "provider": "google cloud" }, "data_stream": { "dataset": "kolide.auth", - "namespace": "93060", + "namespace": "86759", "type": "logs" }, "ecs": { - "version": "9.3.0" + "version": "9.4.0" }, "elastic_agent": { - "id": "d9df3829-c2e0-4721-8242-1cf13796bbc4", + "id": "dccea145-284f-4566-914a-d93ed70b44fc", "snapshot": false, - "version": "9.4.1" + "version": "8.19.0" }, "event": { "action": "sign_in_attempt", @@ -347,52 +525,42 @@ An example event for `auth` looks as following: "session" ], "dataset": "kolide.auth", - "id": "3374648:sign_in_attempt:2024-03-11T21:28:17Z", - "ingested": "2026-06-17T18:36:02Z", + "id": "id-95314806818425813618559742320:sign_in_attempt:2026-06-11T16:29:17Z", + "ingested": "2026-07-13T18:22:27Z", "kind": "event", - "module": "kolide", - "original": "{\"agent_version\":\"1.4.0\",\"browser_name\":\"Chrome\",\"browser_user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\",\"city\":\"New York\",\"country\":\"United States\",\"device_info\":{\"identifier\":\"1\",\"link\":\"https://api.example.com/devices/1\"},\"events\":[{\"event_description\":\"The end-user was redirected to Kolide via a valid SAML request\",\"event_type\":\"sign_in_attempt\",\"timestamp\":\"2024-03-11T21:28:17Z\"},{\"event_description\":\"The end-user clicked Continue to Sign In\",\"event_type\":\"sign_in_success\",\"timestamp\":\"2024-03-11T21:28:19Z\"}],\"id\":\"3374648\",\"initial_status\":\"all_good\",\"ip_address\":\"198.51.100.23\",\"issues_displayed\":[{\"blocking_status\":\"will_block\",\"id\":\"9999\",\"link\":\"https://api.example.com/issues/9999\",\"title\":\"macOS Firewall is Disabled\"}],\"okta_app_instance_id\":\"0oa1example2instance3\",\"okta_app_name\":\"Example Corp SSO\",\"person_email\":\"user@example.com\",\"person_info\":{\"identifier\":\"3\",\"link\":\"https://api.example.com/people/3\"},\"person_name\":\"Alice Johnson\",\"result\":\"Success\",\"session_timestamp\":\"2024-03-11T21:28:17Z\",\"sub_event_description\":\"The end-user was redirected to Kolide via a valid SAML request\",\"sub_event_type\":\"sign_in_attempt\",\"timestamp\":\"2024-03-11T21:28:17Z\"}", - "outcome": "success", - "start": "2024-03-11T21:28:17.000Z", + "original": "{\"timestamp\":\"2026-06-11T16:29:17Z\",\"type\":\"auth_log\",\"data\":{\"request_id\":\"id-95314806818425813618559742320\",\"auth_event_type\":\"sign_in_attempt\",\"ip_address\":\"198.51.100.210\"}}", "type": [ - "start", - "info" + "start" ] }, - "host": { - "id": "1" + "gcs": { + "storage": { + "bucket": { + "name": "kolide-auth" + }, + "object": { + "content_type": "application/x-ndjson", + "name": "kolide-auth.log" + } + } }, "input": { - "type": "cel" + "type": "gcs" }, "kolide": { "auth": { - "agent_version": "1.4.0", - "initial_status": "all_good", - "issues_displayed": [ - { - "blocking_status": "will_block", - "id": "9999", - "link": "https://api.example.com/issues/9999", - "title": "macOS Firewall is Disabled" - } - ], - "okta": { - "app_instance_id": "0oa1example2instance3", - "app_name": "Example Corp SSO" - }, - "result": "Success", - "session_id": "3374648" + "session_id": "id-95314806818425813618559742320" } }, - "message": "The end-user was redirected to Kolide via a valid SAML request", + "log": { + "file": { + "path": "gs://kolide-auth/kolide-auth.log" + }, + "offset": 0 + }, "related": { "ip": [ - "198.51.100.23" - ], - "user": [ - "Alice Johnson", - "user@example.com" + "198.51.100.210" ] }, "source": { @@ -408,37 +576,19 @@ An example event for `auth` looks as following: "country_iso_code": "NL", "country_name": "Netherlands", "location": { - "lat": 52.37403995823115, - "lon": 4.889689916744828 + "lat": 52.37404, + "lon": 4.88969 }, "region_iso_code": "NL-NH", "region_name": "North Holland" }, - "ip": "198.51.100.23" + "ip": "198.51.100.210" }, "tags": [ "preserve_original_event", "forwarded", - "kolide-auth" - ], - "user": { - "email": "user@example.com", - "id": "3", - "name": "Alice Johnson" - }, - "user_agent": { - "device": { - "name": "Mac" - }, - "name": "Chrome", - "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", - "os": { - "full": "Mac OS X 10.15.7", - "name": "Mac OS X", - "version": "10.15.7" - }, - "version": "122.0.0.0" - } + "kolide-auth-gcs" + ] } ``` @@ -452,19 +602,19 @@ The `issues` data stream provides Kolide posture-check failures and resolutions | Field | Description | Type | |---|---|---| -| @timestamp | Event timestamp. | date | -| data_stream.dataset | Data stream dataset. | constant_keyword | -| data_stream.namespace | Data stream namespace. | constant_keyword | -| data_stream.type | Data stream type. | constant_keyword | +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | | ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | | error.message | Error message. | match_only_text | | event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | | event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | -| event.dataset | Event dataset. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | | event.end | `event.end` contains the date when the event ended or when the activity was last observed. | date | | event.id | Unique ID to describe the event. | keyword | | event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | -| event.module | Event module. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | | event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | | event.outcome | This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense. | keyword | | event.start | `event.start` contains the date when the event started or when the activity was first observed. | date | @@ -482,7 +632,7 @@ The `issues` data stream provides Kolide posture-check failures and resolutions | kolide.issues.check.id | Identifier of the failing check (webhook `check_id`). | keyword | | kolide.issues.check.tags | Tags associated with the check (webhook only). | keyword | | kolide.issues.check_information.link | API URL of the check record. | keyword | -| kolide.issues.detected_at | Timestamp at which the issue was first detected (API only). | date | +| kolide.issues.detected_at | Timestamp at which the issue was first detected (API), or the webhook delivery time for `issues.new` webhook deliveries. | date | | kolide.issues.detected_version | Version of the software detected on the device (for example, Chrome, OS). | keyword | | kolide.issues.device_information.link | API URL of the device record. | keyword | | kolide.issues.exempted | Whether the issue has been exempted from blocking the device (API only). | boolean | @@ -491,7 +641,7 @@ The `issues` data stream provides Kolide posture-check failures and resolutions | kolide.issues.issue_key | The key that identifies what kind of issue this is, for example `bundle_id` (API only). | keyword | | kolide.issues.issue_value | The value associated with the issue key, for example the offending bundle identifier (API only). | keyword | | kolide.issues.last_rechecked_at | Timestamp at which the issue was last rechecked (API only). | date | -| kolide.issues.resolved_at | Timestamp at which the issue was resolved, if any (API only). | date | +| kolide.issues.resolved_at | Timestamp at which the issue was resolved, if any (API), or the webhook delivery time for `issues.resolved` webhook deliveries. | date | | kolide.issues.ssh_key_type | SSH key algorithm type (for example, ssh-ed25519, ssh-rsa). | keyword | | kolide.issues.title | Short human-readable description of the issue. Can be null on `issues.new` webhooks. | keyword | | kolide.issues.value | Structured details about why the device failed the check; the shape varies by check (API only). | flattened | @@ -515,42 +665,43 @@ An example event for `issues` looks as following: ```json { - "@timestamp": "2023-10-28T20:50:15.000Z", + "@timestamp": "2023-11-04T20:50:15.000Z", "agent": { - "ephemeral_id": "7429995a-4016-41dc-9ca9-92589f75758b", - "id": "583c03ad-a4d1-45e8-b155-49c05bac1c14", - "name": "elastic-agent-31084", + "ephemeral_id": "ca392310-3081-40aa-8dc2-593fbd4e68c0", + "id": "3034cebb-69a8-4e14-9ef7-9080f748e9a0", + "name": "elastic-agent-79628", "type": "filebeat", - "version": "8.19.0" + "version": "9.4.3" }, "data_stream": { "dataset": "kolide.issues", - "namespace": "94759", + "namespace": "18609", "type": "logs" }, "ecs": { "version": "9.4.0" }, "elastic_agent": { - "id": "583c03ad-a4d1-45e8-b155-49c05bac1c14", + "id": "3034cebb-69a8-4e14-9ef7-9080f748e9a0", "snapshot": false, - "version": "8.19.0" + "version": "9.4.3" }, "event": { - "action": "issue", + "action": "blocked", "agent_id_status": "verified", "category": [ "configuration" ], "dataset": "kolide.issues", "id": "9999", - "ingested": "2026-06-26T19:47:03Z", + "ingested": "2026-07-13T16:44:23Z", "kind": "event", + "module": "kolide", "original": "{\"blocks_device_at\":\"2023-11-04T20:50:15Z\",\"check_information\":{\"identifier\":\"71\",\"link\":\"https://api.example.com/checks/71\"},\"detected_at\":\"2023-10-28T20:50:15Z\",\"device_information\":{\"identifier\":\"1\",\"link\":\"https://api.example.com/devices/1\"},\"exempted\":false,\"id\":\"9999\",\"issue_key\":\"bundle_id\",\"issue_value\":\"com.example.app\",\"last_rechecked_at\":\"2023-10-28T21:00:58Z\",\"resolved_at\":null,\"title\":\"macOS Firewall is Disabled\",\"value\":{\"firewall_enabled\":false}}", "outcome": "failure", "start": "2023-10-28T20:50:15.000Z", "type": [ - "creation" + "change" ] }, "host": { @@ -576,7 +727,7 @@ An example event for `issues` looks as following: "last_rechecked_at": "2023-10-28T21:00:58.000Z", "title": "macOS Firewall is Disabled", "value": { - "firewall_enabled": false + "firewall_enabled": "false" } } }, @@ -594,9 +745,148 @@ An example event for `issues` looks as following: } ``` +#### request + +The `request` data stream collects approval-workflow requests from the Kolide REST API using the `GET /exemption_requests` and `GET /registration_requests` endpoints, as well as request webhooks. The logs from these endpoints are normalized into a single data stream with `kolide.request.type` set to either `exemption` or `registration`. + +##### request fields + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| error.message | Error message. | match_only_text | +| event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | +| event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.id | Unique ID to describe the event. | keyword | +| event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | +| event.outcome | This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense. | keyword | +| event.reason | Reason why this event happened, according to the source. This describes the why of a particular action or outcome captured in the event. Where `event.action` captures the action from the event, `event.reason` describes why that action was taken. For example, a web proxy with an `event.action` which denied the request may also populate `event.reason` with the reason why (e.g. `blocked site`). | keyword | +| event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| host.hostname | Hostname of the host. It normally contains what the `hostname` command returns on the host machine. | keyword | +| host.id | Unique host id. As hostname is not always unique, use values that are meaningful in your environment. Example: The current usage of `beat.name`. | keyword | +| host.name | Name of the host. It can contain what hostname returns on Unix systems, the fully qualified domain name (FQDN), or a name specified by the user. The recommended value is the lowercase FQDN of the host. | keyword | +| input.type | Type of filebeat input. | keyword | +| kolide.request.created_at | Timestamp at which the request was created. From API `requested_at`. | date | +| kolide.request.device.url | API URL of the referenced device. From API `device_information.link` or webhook `data.device.url`. | keyword | +| kolide.request.id | Kolide request identifier. | keyword | +| kolide.request.internal_message | Admin-internal note explaining the approval/denial decision, not shown to the requester. From API `internal_explanation` (exemption) or `internal_denial_note` / `internal_approval_note` (registration). | match_only_text | +| kolide.request.issues | Issues referenced by an exemption request. From API `issues` (array of `identifier`/`link` link-objects) or webhook `data.issues` (array of `issue_id`/`issue_url` objects); the shape varies by source. | flattened | +| kolide.request.message | Human-entered request message or reason. From API `requester_message` or webhook `data.message`. | match_only_text | +| kolide.request.requester.url | API URL of the referenced requester. From API `requester_information.link` or webhook `data.requester.url`. | keyword | +| kolide.request.state | Normalized request state, for example `pending`, `approved`, or `denied`. | keyword | +| kolide.request.type | Type of request, either `exemption` or `registration`. | keyword | +| message | For log events the message field contains the log message, optimized for viewing in a log viewer. For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. If multiple messages exist, they can be combined into one message. | match_only_text | +| related.hosts | All hostnames or other host identifiers seen on your event. Example identifiers include FQDNs, domain names, workstation names, or aliases. | keyword | +| related.user | All the user names or other user identifiers seen on the event. | keyword | +| tags | List of keywords used to tag each event. | keyword | +| user.email | User email address. | keyword | +| user.id | Unique identifier of the user. | keyword | +| user.name | Short name or login of the user. | keyword | +| user.name.text | Multi-field of `user.name`. | match_only_text | + + +##### request sample event + +An example event for `request` looks as following: + +```json +{ + "@timestamp": "2026-07-13T16:49:30.078Z", + "agent": { + "ephemeral_id": "1c11b942-f3cd-49ce-90be-6bf18cc0dca7", + "id": "4f49a520-5e31-4eda-8941-f2131aa5a324", + "name": "elastic-agent-87676", + "type": "filebeat", + "version": "9.4.3" + }, + "data_stream": { + "dataset": "kolide.request", + "namespace": "47623", + "type": "logs" + }, + "ecs": { + "version": "9.4.0" + }, + "elastic_agent": { + "id": "4f49a520-5e31-4eda-8941-f2131aa5a324", + "snapshot": false, + "version": "9.4.3" + }, + "event": { + "action": "exemption_request_open", + "agent_id_status": "verified", + "category": [ + "configuration", + "iam" + ], + "dataset": "kolide.request", + "id": "exemption-request-001", + "ingested": "2026-07-13T16:49:33Z", + "kind": "event", + "module": "kolide", + "original": "{\"_kolide_request_type\":\"exemption\",\"device_information\":{\"identifier\":\"200001\",\"link\":\"https://api.example.com/devices/200001\"},\"id\":\"exemption-request-001\",\"issues\":[{\"identifier\":\"9999\",\"link\":\"https://api.example.com/issues/9999\"}],\"requested_at\":\"2024-03-11T21:28:17Z\",\"requester_information\":{\"identifier\":\"100001\",\"link\":\"https://api.example.com/people/100001\"},\"requester_message\":\"Need temporary access for incident response\",\"status\":\"open\"}", + "outcome": "unknown", + "type": [ + "creation" + ] + }, + "host": { + "id": "200001" + }, + "input": { + "type": "cel" + }, + "kolide": { + "request": { + "created_at": "2024-03-11T21:28:17.000Z", + "device": { + "url": "https://api.example.com/devices/200001" + }, + "id": "exemption-request-001", + "issues": { + "identifier": "9999", + "link": "https://api.example.com/issues/9999" + }, + "message": "Need temporary access for incident response", + "requester": { + "url": "https://api.example.com/people/100001" + }, + "state": "open", + "type": "exemption" + } + }, + "message": "Need temporary access for incident response", + "related": { + "hosts": [ + "200001" + ], + "user": [ + "100001" + ] + }, + "tags": [ + "preserve_original_event", + "forwarded", + "kolide-request" + ], + "user": { + "id": "100001" + } +} +``` + #### device -The `device` data stream provides Kolide device inventory records and device-trust status changes. +The `device` data stream provides Kolide device inventory records and device-trust status changes. Because the `GET /devices` endpoint does not expose a modified-since cursor, each interval retrieves the complete collection. The ingest pipeline assigns a content-based document `_id` so unchanged devices are deduplicated across polls, while any change is captured as a new document. ##### device fields @@ -604,18 +894,18 @@ The `device` data stream provides Kolide device inventory records and device-tru | Field | Description | Type | |---|---|---| -| @timestamp | Event timestamp. | date | -| data_stream.dataset | Data stream dataset. | constant_keyword | -| data_stream.namespace | Data stream namespace. | constant_keyword | -| data_stream.type | Data stream type. | constant_keyword | +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | | ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | | error.message | Error message. | match_only_text | | event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | | event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | -| event.dataset | Event dataset. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | | event.id | Unique ID to describe the event. | keyword | | event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | -| event.module | Event module. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | | event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | | event.outcome | This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense. | keyword | | event.start | `event.start` contains the date when the event started or when the activity was first observed. | date | @@ -668,26 +958,26 @@ An example event for `device` looks as following: ```json { - "@timestamp": "2026-06-26T19:45:06.028069753Z", + "@timestamp": "2026-07-13T16:41:33.883Z", "agent": { - "ephemeral_id": "cd0d58a1-1d21-45e2-accf-77d9d46080b3", - "id": "c5bb2007-c7a7-44cb-a399-4679caac8c22", - "name": "elastic-agent-37867", + "ephemeral_id": "6dc17ec1-2f49-4b4a-899d-a50c23e3256a", + "id": "8fc63088-0e7a-4b0a-80b6-d927c6b6fd64", + "name": "elastic-agent-75041", "type": "filebeat", - "version": "8.19.0" + "version": "9.4.3" }, "data_stream": { "dataset": "kolide.device", - "namespace": "47456", + "namespace": "92721", "type": "logs" }, "ecs": { "version": "9.4.0" }, "elastic_agent": { - "id": "c5bb2007-c7a7-44cb-a399-4679caac8c22", + "id": "8fc63088-0e7a-4b0a-80b6-d927c6b6fd64", "snapshot": false, - "version": "8.19.0" + "version": "9.4.3" }, "event": { "action": "device", @@ -696,8 +986,9 @@ An example event for `device` looks as following: "host" ], "dataset": "kolide.device", - "ingested": "2026-06-26T19:45:06Z", + "ingested": "2026-07-13T16:41:33Z", "kind": "state", + "module": "kolide", "original": "{\"auth_configuration\":{\"authentication_mode\":\"only_registered_owner\",\"device_id\":\"1\",\"person_groups\":[]},\"auth_state\":\"Good\",\"device_type\":\"Mac\",\"form_factor\":\"Computer\",\"hardware_model\":\"MacBookPro18,1\",\"hardware_uuid\":\"00000000-0000-0000-0000-000000000000\",\"id\":\"1\",\"last_authenticated_at\":\"2024-03-11T21:28:17Z\",\"last_seen_at\":\"2024-03-11T21:30:00Z\",\"name\":\"Alices-MacBook-Pro\",\"note\":\"Loaner device\",\"operating_system\":\"macOS 14.4.1\",\"product_image_url\":\"https://example.com/images/macbookpro.png\",\"registered_at\":\"2023-10-28T20:12:14Z\",\"registered_owner_info\":{\"identifier\":\"1\",\"link\":\"https://api.example.com/people/1\"},\"serial\":\"C02EXAMPLE123\",\"will_block_at\":null}", "start": "2023-10-28T20:12:14.000Z", "type": [ @@ -760,9 +1051,213 @@ An example event for `device` looks as following: } ``` +#### people + +The `people` data stream provides Kolide identity records for active people using the `GET /people` endpoint. This includes Elastic Common Schema (ECS) user fields, SCIM-imported usernames, last-authentication time, and device-registration flags that Kolide exposes on this resource. Group, identity provider (IdP), SCIM, and deprovisioning details live on separate Kolide API resources like `person_groups` and `deprovisioned_people` that this data stream does not collect. Because the `GET /people` endpoint does not expose a modified-since cursor, each interval retrieves the complete collection. The ingest pipeline derives a content-fingerprint document `_id`, excluding `last_authenticated_at`, so byte-identical records are deduplicated across polls; records whose tracked fields change between polls are indexed as new documents rather than overwriting the prior one. + +##### people fields + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| error.message | Error message. | match_only_text | +| event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | +| event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | +| event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| input.type | Type of filebeat input. | keyword | +| kolide.people.created_at | Timestamp at which the person record was created. | date | +| kolide.people.has_registered_device | Whether the person has at least one registered device. | boolean | +| kolide.people.id | Kolide person identifier. | keyword | +| kolide.people.last_authenticated_at | When the person last authenticated with Kolide. | date | +| kolide.people.usernames | Usernames imported from the SCIM provider associated with this person. | keyword | +| log.offset | Log offset. | long | +| related.user | All the user names or other user identifiers seen on the event. | keyword | +| tags | List of keywords used to tag each event. | keyword | +| user.email | User email address. | keyword | +| user.full_name | User's full name, if available. | keyword | +| user.full_name.text | Multi-field of `user.full_name`. | match_only_text | +| user.id | Unique identifier of the user. | keyword | +| user.name | Short name or login of the user. | keyword | +| user.name.text | Multi-field of `user.name`. | match_only_text | + + +##### people sample event + +An example event for `people` looks as following: + +```json +{ + "@timestamp": "2026-06-26T19:45:06.028069753Z", + "data_stream": { + "dataset": "kolide.people", + "namespace": "default", + "type": "logs" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "person", + "category": [ + "iam" + ], + "dataset": "kolide.people", + "kind": "state", + "original": "{\"id\":\"861637\",\"name\":\"Alice Johnson\",\"email\":\"alice.johnson@example.com\",\"created_at\":\"2024-01-10T08:00:00Z\",\"last_authenticated_at\":\"2024-06-15T12:00:00Z\",\"has_registered_device\":true,\"usernames\":[\"alice.johnson@example.com\"]}", + "type": [ + "user", + "info" + ] + }, + "input": { + "type": "cel" + }, + "kolide": { + "people": { + "created_at": "2024-01-10T08:00:00.000Z", + "has_registered_device": true, + "id": "861637", + "last_authenticated_at": "2024-06-15T12:00:00.000Z", + "usernames": [ + "alice.johnson@example.com" + ] + } + }, + "related": { + "user": [ + "alice.johnson@example.com", + "861637" + ] + }, + "tags": [ + "preserve_original_event", + "forwarded", + "kolide-people" + ], + "user": { + "email": "alice.johnson@example.com", + "full_name": "Alice Johnson", + "id": "861637", + "name": "alice.johnson@example.com" + } +} +``` + +#### deprovisioned_person + +The `deprovisioned_person` data stream provides Kolide identity records for people who have been offboarded or deprovisioned using the `GET /deprovisioned_people` endpoint. This is a separate API resource from `people` rather than a field on the person object. You can use this data stream to detect lingering access or devices owned by departed identities. Unlike the `people` data stream, this resource does not return SCIM usernames, but it includes an `api_url` field that links back to the corresponding `GET /people/{id}` resource. + +Because the `GET /deprovisioned_people` endpoint does not expose a modified-since cursor, each interval collects the complete collection. This full collection retrieval is intentional because an incremental approach cannot detect when records disappear from the list, for example when a user is re-provisioned, when a Kolide-side correction is made, or when records are missed because of pagination drift. The ingest pipeline derives a content-fingerprint document `_id`, excluding `last_authenticated_at`, so duplicate records are deduplicated across polls. Records with tracked fields that change between polls are indexed as new documents. + +##### deprovisioned_person fields + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| error.message | Error message. | match_only_text | +| event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | +| event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | +| event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| input.type | Type of filebeat input. | keyword | +| kolide.deprovisioned_person.api_url | Kolide REST API URL for the corresponding person resource. Points at GET /people/\{id\}, not a /deprovisioned_people path. | keyword | +| kolide.deprovisioned_person.created_at | Timestamp at which the person record was originally created. | date | +| kolide.deprovisioned_person.has_registered_device | Whether the person had at least one registered device at the time of deprovisioning. | boolean | +| kolide.deprovisioned_person.id | Kolide person identifier. | keyword | +| kolide.deprovisioned_person.last_authenticated_at | When the person last authenticated with Kolide, prior to deprovisioning. | date | +| log.offset | Log offset. | long | +| related.user | All the user names or other user identifiers seen on the event. | keyword | +| tags | List of keywords used to tag each event. | keyword | +| user.email | User email address. | keyword | +| user.full_name | User's full name, if available. | keyword | +| user.full_name.text | Multi-field of `user.full_name`. | match_only_text | +| user.id | Unique identifier of the user. | keyword | +| user.name | Short name or login of the user. | keyword | +| user.name.text | Multi-field of `user.name`. | match_only_text | + + +##### deprovisioned_person sample event + +An example event for `deprovisioned_person` looks as following: + +```json +{ + "@timestamp": "2026-06-26T19:45:06.028069753Z", + "data_stream": { + "dataset": "kolide.deprovisioned_person", + "namespace": "default", + "type": "logs" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "person_deprovisioned", + "category": [ + "iam" + ], + "dataset": "kolide.deprovisioned_person", + "kind": "state", + "original": "{\"id\":\"861637\",\"name\":\"Alice Johnson\",\"email\":\"alice.johnson@example.com\",\"created_at\":\"2026-06-04T18:29:22.129Z\",\"last_authenticated_at\":\"2024-06-15T12:00:00Z\",\"has_registered_device\":false,\"api_url\":\"https://api.kolide.com/people/861637\"}", + "type": [ + "user", + "info" + ] + }, + "input": { + "type": "cel" + }, + "kolide": { + "deprovisioned_person": { + "api_url": "https://api.kolide.com/people/861637", + "created_at": "2026-06-04T18:29:22.129Z", + "has_registered_device": false, + "id": "861637", + "last_authenticated_at": "2024-06-15T12:00:00.000Z" + } + }, + "related": { + "user": [ + "alice.johnson@example.com", + "861637" + ] + }, + "tags": [ + "preserve_original_event", + "forwarded", + "kolide-deprovisioned-person" + ], + "user": { + "email": "alice.johnson@example.com", + "full_name": "Alice Johnson", + "id": "861637", + "name": "alice.johnson@example.com" + } +} +``` + #### audit -The `audit` data stream provides the Kolide administrative audit log of console actions. +The `audit` data stream provides the Kolide administrative audit log of console actions using the `GET /audit_logs` endpoint. ##### audit fields @@ -770,24 +1265,27 @@ The `audit` data stream provides the Kolide administrative audit log of console | Field | Description | Type | |---|---|---| -| @timestamp | Event timestamp. | date | +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | | aws.s3.bucket.arn | The AWS S3 bucket ARN. | keyword | | aws.s3.bucket.name | The AWS S3 bucket name. | keyword | | aws.s3.object.key | The AWS S3 object key. | keyword | -| data_stream.dataset | Data stream dataset. | constant_keyword | -| data_stream.namespace | Data stream namespace. | constant_keyword | -| data_stream.type | Data stream type. | constant_keyword | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | | ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | | error.message | Error message. | match_only_text | | event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | | event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | -| event.dataset | Event dataset. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | | event.id | Unique ID to describe the event. | keyword | | event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | -| event.module | Event module. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | | event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | | event.outcome | This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense. | keyword | | event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| gcs.storage.bucket.name | The GCS bucket name. | keyword | +| gcs.storage.object.content_type | The content type of the GCS object. | keyword | +| gcs.storage.object.name | The GCS object name. | keyword | | host.hostname | Hostname of the host. It normally contains what the `hostname` command returns on the host machine. | keyword | | host.name | Name of the host. It can contain what hostname returns on Unix systems, the fully qualified domain name (FQDN), or a name specified by the user. The recommended value is the lowercase FQDN of the host. | keyword | | input.type | Type of filebeat input. | keyword | @@ -863,35 +1361,34 @@ An example event for `audit` looks as following: { "@timestamp": "2024-03-11T21:28:17.000Z", "agent": { - "ephemeral_id": "f734b99d-fd67-4981-bb45-59ca1024a4bf", - "id": "ce1af407-b9ee-42ff-9448-8cd015c5ac91", - "name": "elastic-agent-94474", + "ephemeral_id": "976911ab-bf56-45ea-b463-1ee8c348bb5f", + "id": "ab1e36dd-3a4a-4a94-95c7-8b8250ae7ee3", + "name": "elastic-agent-27061", "type": "filebeat", - "version": "9.4.1" + "version": "9.4.3" }, "data_stream": { "dataset": "kolide.audit", - "namespace": "14195", + "namespace": "56604", "type": "logs" }, "ecs": { - "version": "9.3.0" + "version": "9.4.0" }, "elastic_agent": { - "id": "ce1af407-b9ee-42ff-9448-8cd015c5ac91", + "id": "ab1e36dd-3a4a-4a94-95c7-8b8250ae7ee3", "snapshot": false, - "version": "9.4.1" + "version": "9.4.3" }, "event": { - "action": "audit_log", + "action": "check_enabled", "agent_id_status": "verified", "category": [ - "iam", "configuration" ], "dataset": "kolide.audit", "id": "01JA67B1DYJCKJ1J73T0F5EWGR", - "ingested": "2026-06-17T18:35:10Z", + "ingested": "2026-07-13T16:59:33Z", "kind": "event", "module": "kolide", "original": "{\"actor_info\":{\"actor_email\":\"alice@example.com\",\"actor_name\":\"Alice Johnson\",\"actor_type\":\"User\"},\"actor_name\":\"Alice Johnson\",\"description\":\"Enabled check 'iTerm2 - Require Secure Keyboard Entry to Be Enabled'\",\"id\":\"01JA67B1DYJCKJ1J73T0F5EWGR\",\"timestamp\":\"2024-03-11T21:28:17Z\"}", @@ -904,6 +1401,7 @@ An example event for `audit` looks as following: }, "kolide": { "audit": { + "actor_automated": false, "actor_type": "User" } }, @@ -931,7 +1429,11 @@ An example event for `audit` looks as following: #### device_check -The `device_check` data stream provides Kolide device check-run results delivered through the Log Pipeline (S3). Unlike the `issues` data stream, which tracks the failure lifecycle, this stream records every check run — `passing`, `failing`, `inapplicable`, and `unknown`. +The `device_check` data stream provides Kolide device check-run results delivered through the Kolide Log Pipeline using an Amazon S3 bucket. You can configure this using Amazon SQS notifications or direct bucket polling. Unlike the `issues` data stream, which tracks the failure lifecycle, this stream records every check run, including these check statuses: +- `passing` +- `failing` +- `inapplicable` +- `unknown` ##### device_check fields @@ -939,24 +1441,27 @@ The `device_check` data stream provides Kolide device check-run results delivere | Field | Description | Type | |---|---|---| -| @timestamp | Event timestamp. | date | +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | | aws.s3.bucket.arn | The AWS S3 bucket ARN. | keyword | | aws.s3.bucket.name | The AWS S3 bucket name. | keyword | | aws.s3.object.key | The AWS S3 object key. | keyword | -| data_stream.dataset | Data stream dataset. | constant_keyword | -| data_stream.namespace | Data stream namespace. | constant_keyword | -| data_stream.type | Data stream type. | constant_keyword | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | | ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | | error.message | Error message. | match_only_text | | event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | | event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | -| event.dataset | Event dataset. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | | event.id | Unique ID to describe the event. | keyword | | event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | -| event.module | Event module. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | | event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | | event.outcome | This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense. | keyword | | event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| gcs.storage.bucket.name | The GCS bucket name. | keyword | +| gcs.storage.object.content_type | The content type of the GCS object. | keyword | +| gcs.storage.object.name | The GCS object name. | keyword | | host.id | Unique host id. As hostname is not always unique, use values that are meaningful in your environment. Example: The current usage of `beat.name`. | keyword | | input.type | Type of filebeat input. | keyword | | kolide.device_check.check_id | Numeric identifier of the check that was run. | long | @@ -979,24 +1484,27 @@ An example event for `device_check` looks as following: { "@timestamp": "2026-06-02T15:45:01.000Z", "agent": { - "ephemeral_id": "b2c4d6e8-f0a1-4b3c-8d7e-9f0a1b2c3d4e", - "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", - "name": "elastic-agent-12345", + "ephemeral_id": "7688604a-e3eb-4d25-a462-28596cd3c236", + "id": "c4e7e825-937b-4db3-a16a-67072d1169fa", + "name": "elastic-agent-75667", "type": "filebeat", - "version": "9.4.1" + "version": "9.4.3" + }, + "cloud": { + "provider": "google cloud" }, "data_stream": { "dataset": "kolide.device_check", - "namespace": "48291", + "namespace": "77666", "type": "logs" }, "ecs": { - "version": "9.3.0" + "version": "9.4.0" }, "elastic_agent": { - "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "id": "c4e7e825-937b-4db3-a16a-67072d1169fa", "snapshot": false, - "version": "9.4.1" + "version": "9.4.3" }, "event": { "action": "check_result", @@ -1005,8 +1513,8 @@ An example event for `device_check` looks as following: "host" ], "dataset": "kolide.device_check", - "id": "7386319-10-2026-06-02T15:45:01.000Z", - "ingested": "2026-06-17T18:40:00Z", + "id": "7386319-10-2026-06-02T15:45:01Z", + "ingested": "2026-07-13T16:43:34Z", "kind": "state", "module": "kolide", "original": "{\"type\":\"check_result\",\"timestamp\":\"2026-06-02T15:45:01Z\",\"data\":{\"check_id\":10,\"check_slug\":\"macos_file_sharing\",\"device_id\":7386319,\"status\":\"passing\",\"check_result_data\":[{\"file_sharing\":\"0\",\"current_os_version\":\"26.4.1\",\"KOLIDE_CHECK_STATUS\":\"PASS\"}]}}", @@ -1015,27 +1523,42 @@ An example event for `device_check` looks as following: "info" ] }, + "gcs": { + "storage": { + "bucket": { + "name": "kolide-device-check" + }, + "object": { + "content_type": "application/x-ndjson", + "name": "kolide-device-check.log" + } + } + }, "host": { "id": "7386319" }, "input": { - "type": "aws-s3" + "type": "gcs" }, "kolide": { "device_check": { "check_id": 10, - "check_result_data": [ - { - "KOLIDE_CHECK_STATUS": "PASS", - "current_os_version": "26.4.1", - "file_sharing": "0" - } - ], + "check_result_data": { + "KOLIDE_CHECK_STATUS": "PASS", + "current_os_version": "26.4.1", + "file_sharing": "0" + }, "check_slug": "macos_file_sharing", "device_id": 7386319, "status": "passing" } }, + "log": { + "file": { + "path": "gs://kolide-device-check/kolide-device-check.log" + }, + "offset": 1670 + }, "rule": { "id": "10", "name": "macos_file_sharing" @@ -1043,11 +1566,409 @@ An example event for `device_check` looks as following: "tags": [ "preserve_original_event", "forwarded", - "kolide-device-check-s3" + "kolide-device-check-gcs" ] } ``` +#### osquery_result + +The `osquery_result` data stream provides raw osquery Result Logs delivered through the Kolide Log Pipeline using Amazon S3 or Google Cloud Storage under the `kolide/results/` prefix. This includes both snapshot-query rows and differential (`added` and `removed`) rows. Per-query column data in `kolide.osquery_result.added`, `kolide.osquery_result.removed`, or `kolide.osquery_result.snapshot` is arbitrary and depends on the target osquery table or custom SQL, so it is stored as a flattened field rather than mapped per column. + +##### osquery_result fields + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| aws.s3.bucket.arn | The AWS S3 bucket ARN. | keyword | +| aws.s3.bucket.name | The AWS S3 bucket name. | keyword | +| aws.s3.object.key | The AWS S3 object key. | keyword | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| device.manufacturer | The vendor name of the device manufacturer. | keyword | +| device.model.name | The human readable marketing name of the device model. | keyword | +| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| error.message | Error message. | match_only_text | +| event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | +| event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.id | Unique ID to describe the event. | keyword | +| event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | +| event.sequence | Sequence number of the event. The sequence number is a value published by some event sources, to make the exact ordering of events unambiguous, regardless of the timestamp precision. | long | +| event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| gcs.storage.bucket.name | The GCS bucket name. | keyword | +| gcs.storage.object.content_type | The content type of the GCS object. | keyword | +| gcs.storage.object.name | The GCS object name. | keyword | +| host.geo.city_name | City name. | keyword | +| host.geo.continent_name | Name of the continent. | keyword | +| host.geo.country_iso_code | Country ISO code. | keyword | +| host.geo.country_name | Country name. | keyword | +| host.geo.location.lat | Longitude and latitude. | geo_point | +| host.geo.location.lon | Longitude and latitude. | geo_point | +| host.geo.region_iso_code | Region ISO code. | keyword | +| host.geo.region_name | Region name. | keyword | +| host.hostname | Hostname of the host. It normally contains what the `hostname` command returns on the host machine. | keyword | +| host.id | Unique host id. As hostname is not always unique, use values that are meaningful in your environment. Example: The current usage of `beat.name`. | keyword | +| host.ip | Host ip addresses. | ip | +| host.name | Name of the host. It can contain what hostname returns on Unix systems, the fully qualified domain name (FQDN), or a name specified by the user. The recommended value is the lowercase FQDN of the host. | keyword | +| input.type | Type of filebeat input. | keyword | +| kolide.osquery_result.added | Rows added since the last differential run (`diffResults.added`). The shape is arbitrary and depends on which osquery table or custom SQL the query targets, so it is stored as a flattened field rather than mapping each key. | flattened | +| kolide.osquery_result.calendar_time | Osquery's human-readable, locale-dependent timestamp string. `@timestamp` (derived from `unixTime`) is authoritative; this is kept only for reference. | keyword | +| kolide.osquery_result.counter | Osquery's per-epoch row counter, also copied to `event.sequence`. | long | +| kolide.osquery_result.device_registered_at | When the reporting device was registered to its owner in Kolide (`kolide_decorations.device_registered_at`). | date | +| kolide.osquery_result.device_serial | Serial number of the reporting device, from Kolide's device decoration (`kolide_decorations.serial_number`, falling back to `decorations.hardware_serial`). No ECS host-serial field exists, so this stays custom. | keyword | +| kolide.osquery_result.enrolled_at | When the reporting device enrolled with Kolide (`kolide_decorations.enrolled_at`). | date | +| kolide.osquery_result.epoch | Osquery's log-rotation epoch for this query. | long | +| kolide.osquery_result.hardware_uuid | Hardware UUID of the reporting device, from Kolide's device decoration (`kolide_decorations.hardware_uuid`, falling back to `decorations.uuid`). | keyword | +| kolide.osquery_result.hardware_version | Hardware version string from osquery's own decorator block (`decorations.hardware_version`). No ECS equivalent. | keyword | +| kolide.osquery_result.host_identifier | Osquery's own host identifier string (typically a UUID or hostname, depending on the host's `--host_identifier` configuration). Kept for correlation/debugging alongside the more reliable `host.id`/`host.name` sourced from Kolide's device decoration. | keyword | +| kolide.osquery_result.numerics | Whether osquery is configured to emit numeric-typed columns as native JSON numbers rather than strings (`numerics` envelope field). | boolean | +| kolide.osquery_result.pack_name | Name of the osquery pack (parsed from the `name` envelope field, e.g. `pack:kolide_log_pipeline:\:\`). | keyword | +| kolide.osquery_result.query_name | Name of the osquery query within the pack. Also mirrored to `rule.name`. | keyword | +| kolide.osquery_result.removed | Rows removed since the last differential run (`diffResults.removed`). Same arbitrary-shape rationale as `added`. | flattened | +| kolide.osquery_result.request_id | Kolide Log Pipeline request ID (a ULID) for this delivery. Unique per object, used as the deduplication key for `event.id`. | keyword | +| kolide.osquery_result.snapshot | The snapshot query's row values (an array of column-value objects). The shape is arbitrary and depends on which osquery table or custom SQL the query targets, so it is stored as a flattened field rather than mapping each key. | flattened | +| log.offset | Log offset. | long | +| related.hosts | All hostnames or other host identifiers seen on your event. Example identifiers include FQDNs, domain names, workstation names, or aliases. | keyword | +| related.ip | All of the IPs seen on your event. | ip | +| related.user | All the user names or other user identifiers seen on the event. | keyword | +| rule.name | The name of the rule or signature generating the event. | keyword | +| tags | List of keywords used to tag each event. | keyword | +| user.email | User email address. | keyword | +| user.full_name | User's full name, if available. | keyword | +| user.full_name.text | Multi-field of `user.full_name`. | match_only_text | +| user.id | Unique identifier of the user. | keyword | + + +##### osquery_result sample event + +An example event for `osquery_result` looks as following: + +```json +{ + "@timestamp": "2026-06-18T16:43:50.000Z", + "agent": { + "ephemeral_id": "53e3433b-e37f-4ae9-a175-ed2b4200692b", + "id": "86ee9ece-8678-4857-9f5c-d4900a1942de", + "name": "elastic-agent-75298", + "type": "filebeat", + "version": "9.4.3" + }, + "cloud": { + "provider": "google cloud" + }, + "data_stream": { + "dataset": "kolide.osquery_result", + "namespace": "20432", + "type": "logs" + }, + "device": { + "manufacturer": "Apple Inc.", + "model": { + "name": "Mac16,8" + } + }, + "ecs": { + "version": "9.4.0" + }, + "elastic_agent": { + "id": "86ee9ece-8678-4857-9f5c-d4900a1942de", + "snapshot": false, + "version": "9.4.3" + }, + "event": { + "action": "differential", + "agent_id_status": "verified", + "category": [ + "host" + ], + "dataset": "kolide.osquery_result", + "id": "01KVDSXT59W05PA85B3C24V2HV", + "ingested": "2026-07-13T16:46:33Z", + "kind": "event", + "module": "kolide", + "original": "{\"diffResults\": {\"removed\": [], \"added\": [{\"datetime\": \"2026-06-18T16:43:50Z\", \"day\": \"18\", \"hour\": \"16\", \"iso_8601\": \"2026-06-18T16:43:50Z\", \"local_timezone\": \"EDT\", \"minutes\": \"43\", \"month\": \"6\", \"seconds\": \"50\", \"timestamp\": \"Thu Jun 18 16:43:50 2026 UTC\", \"timezone\": \"UTC\", \"unix_time\": \"1781801030\", \"weekday\": \"Thursday\", \"year\": \"2026\"}]}, \"name\": \"pack:kolide_log_pipeline:example_noisy_pack:current_time\", \"hostIdentifier\": \"00000000-0000-0000-0000-000000000001\", \"calendarTime\": \"Thu Jun 18 16:43:50 2026 UTC\", \"unixTime\": 1781801030, \"epoch\": 1781800669, \"counter\": 0, \"numerics\": false, \"decorations\": {\"computer_name\": \"Test User's MacBook Pro\", \"hardware_model\": \"Mac16,8\", \"hardware_serial\": \"TESTSERIAL0001\", \"hardware_vendor\": \"Apple Inc.\", \"hardware_version\": \"\", \"hostname\": \"test-macbook-pro\", \"local_hostname\": \"test-macbook-pro\", \"uuid\": \"00000000-0000-0000-0000-000000000001\"}, \"kolide_decorations\": {\"device_id\": 9000000, \"device_display_name\": \"test-macbook-pro\", \"remote_ip\": \"203.0.113.5\", \"serial_number\": \"TESTSERIAL0001\", \"hardware_uuid\": \"00000000-0000-0000-0000-000000000001\", \"enrolled_at\": \"2026-06-18T16:37:49.943Z\", \"device_registered_owner_id\": 9100000, \"device_registered_owner_name\": \"Test User\", \"device_registered_owner_email\": \"test.user@example.com\", \"device_registered_at\": \"2026-06-18T16:38:12.195Z\"}, \"request_id\": \"01KVDSXT59W05PA85B3C24V2HV\", \"type\": \"results_log\"}", + "sequence": 0, + "type": [ + "change" + ] + }, + "gcs": { + "storage": { + "bucket": { + "name": "kolide-osquery-result" + }, + "object": { + "content_type": "application/x-ndjson", + "name": "kolide-osquery-result.log" + } + } + }, + "host": { + "geo": { + "city_name": "Madrid", + "continent_name": "Europe", + "country_iso_code": "ES", + "country_name": "Spain", + "location": { + "coordinates": [ + -3.702500034123659, + 40.416389987803996 + ], + "type": "Point" + }, + "region_iso_code": "ES-M", + "region_name": "Madrid" + }, + "hostname": "test-macbook-pro", + "id": "9000000", + "ip": [ + "203.0.113.5" + ], + "name": "test-macbook-pro" + }, + "input": { + "type": "gcs" + }, + "kolide": { + "osquery_result": { + "added": { + "datetime": "2026-06-18T16:43:50Z", + "day": "18", + "hour": "16", + "iso_8601": "2026-06-18T16:43:50Z", + "local_timezone": "EDT", + "minutes": "43", + "month": "6", + "seconds": "50", + "timestamp": "Thu Jun 18 16:43:50 2026 UTC", + "timezone": "UTC", + "unix_time": "1781801030", + "weekday": "Thursday", + "year": "2026" + }, + "calendar_time": "Thu Jun 18 16:43:50 2026 UTC", + "counter": 0, + "device_registered_at": "2026-06-18T16:38:12.195Z", + "device_serial": "TESTSERIAL0001", + "enrolled_at": "2026-06-18T16:37:49.943Z", + "epoch": 1781800669, + "hardware_uuid": "00000000-0000-0000-0000-000000000001", + "host_identifier": "00000000-0000-0000-0000-000000000001", + "numerics": false, + "pack_name": "example_noisy_pack", + "query_name": "current_time", + "request_id": "01KVDSXT59W05PA85B3C24V2HV" + } + }, + "log": { + "file": { + "path": "gs://kolide-osquery-result/kolide-osquery-result.log" + }, + "offset": 3529 + }, + "related": { + "hosts": [ + "test-macbook-pro" + ], + "ip": [ + "203.0.113.5" + ], + "user": [ + "test.user@example.com" + ] + }, + "rule": { + "name": "current_time" + }, + "tags": [ + "preserve_original_event", + "forwarded", + "kolide-osquery-result-gcs" + ], + "user": { + "email": "test.user@example.com", + "full_name": "Test User", + "id": "9100000" + } +} +``` + +#### osquery_status + +The `osquery_status` data stream provides raw osquery Status Logs, which contain GLOG-style telemetry about the osquery daemon itself, delivered through the Kolide Log Pipeline using Amazon S3 or Google Cloud Storage under the `kolide/status/` prefix. + +##### osquery_status fields + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| aws.s3.bucket.arn | The AWS S3 bucket ARN. | keyword | +| aws.s3.bucket.name | The AWS S3 bucket name. | keyword | +| aws.s3.object.key | The AWS S3 object key. | keyword | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| error.message | Error message. | match_only_text | +| event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | +| event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.id | Unique ID to describe the event. | keyword | +| event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword | +| event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | +| gcs.storage.bucket.name | The GCS bucket name. | keyword | +| gcs.storage.object.content_type | The content type of the GCS object. | keyword | +| gcs.storage.object.name | The GCS object name. | keyword | +| host.hostname | Hostname of the host. It normally contains what the `hostname` command returns on the host machine. | keyword | +| host.id | Unique host id. As hostname is not always unique, use values that are meaningful in your environment. Example: The current usage of `beat.name`. | keyword | +| host.ip | Host ip addresses. | ip | +| host.name | Name of the host. It can contain what hostname returns on Unix systems, the fully qualified domain name (FQDN), or a name specified by the user. The recommended value is the lowercase FQDN of the host. | keyword | +| input.type | Type of filebeat input. | keyword | +| kolide.osquery_status.device_registered_at | When the reporting device was registered to its owner in Kolide (`kolide_decorations.device_registered_at`). | date | +| kolide.osquery_status.device_serial | Serial number of the reporting device, from Kolide's device decoration (`kolide_decorations.serial_number`). No ECS host-serial field exists, so this stays custom. | keyword | +| kolide.osquery_status.enrolled_at | When the reporting device enrolled with Kolide (`kolide_decorations.enrolled_at`). | date | +| kolide.osquery_status.hardware_uuid | Hardware UUID of the reporting device, from Kolide's device decoration (`kolide_decorations.hardware_uuid`). | keyword | +| kolide.osquery_status.host_identifier | Osquery's own host identifier string (typically a UUID or hostname, depending on the host's `--host_identifier` configuration). Kept for correlation/debugging alongside the more reliable `host.id`/`host.name` sourced from Kolide's device decoration. | keyword | +| kolide.osquery_status.request_id | Kolide Log Pipeline request ID (a ULID) for this delivery. Unique per object, used as the deduplication key for `event.id`. | keyword | +| kolide.osquery_status.severity | Raw GLOG severity level (0=INFO, 1=WARNING, 2=ERROR, 3=FATAL), alongside the derived `log.level`. | keyword | +| log.level | Original log level of the log event. If the source of the event provides a log level or textual severity, this is the one that goes in `log.level`. If your source doesn't specify one, you may put your event transport's severity here (e.g. Syslog severity). Some examples are `warn`, `err`, `i`, `informational`. | keyword | +| log.offset | Log offset. | long | +| log.origin.file.line | The line number of the file containing the source code which originated the log event. | long | +| log.origin.file.name | The name of the file containing the source code which originated the log event. Note that this field is not meant to capture the log file. The correct field to capture the log file is `log.file.path`. | keyword | +| message | For log events the message field contains the log message, optimized for viewing in a log viewer. For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. If multiple messages exist, they can be combined into one message. | match_only_text | +| related.hosts | All hostnames or other host identifiers seen on your event. Example identifiers include FQDNs, domain names, workstation names, or aliases. | keyword | +| related.ip | All of the IPs seen on your event. | ip | +| tags | List of keywords used to tag each event. | keyword | +| user.email | User email address. | keyword | +| user.full_name | User's full name, if available. | keyword | +| user.full_name.text | Multi-field of `user.full_name`. | match_only_text | +| user.id | Unique identifier of the user. | keyword | + + +##### osquery_status sample event + +An example event for `osquery_status` looks as following: + +```json +{ + "@timestamp": "2026-06-18T19:00:26.000Z", + "agent": { + "ephemeral_id": "9f74f21b-f382-453b-b998-382eb95ec979", + "id": "4bb46e82-a5cd-4ba2-8ca9-c78cc61c4f1b", + "name": "elastic-agent-47155", + "type": "filebeat", + "version": "9.4.3" + }, + "cloud": { + "provider": "google cloud" + }, + "data_stream": { + "dataset": "kolide.osquery_status", + "namespace": "68723", + "type": "logs" + }, + "ecs": { + "version": "9.4.0" + }, + "elastic_agent": { + "id": "4bb46e82-a5cd-4ba2-8ca9-c78cc61c4f1b", + "snapshot": false, + "version": "9.4.3" + }, + "event": { + "action": "osquery_status", + "agent_id_status": "verified", + "category": [ + "process" + ], + "dataset": "kolide.osquery_status", + "id": "01KVE1Q4W257B537D5PJD6DN7F", + "ingested": "2026-07-13T16:48:43Z", + "kind": "event", + "module": "kolide", + "original": "{\"s\": 0, \"f\": \"preferences.cpp\", \"i\": 318, \"m\": \"Cannot find/read defaults plist from path: /Library/Preferences/com.apple.TimeMachine.plist\", \"h\": \"00000000-0000-0000-0000-000000000001\", \"c\": \"Thu Jun 18 19:00:26 2026 UTC\", \"u\": 1781809226, \"kolide_decorations\": {\"device_id\": 9000000, \"device_display_name\": \"test-macbook-pro\", \"remote_ip\": \"203.0.113.5\", \"serial_number\": \"TESTSERIAL0001\", \"hardware_uuid\": \"00000000-0000-0000-0000-000000000001\", \"enrolled_at\": \"2026-06-18T16:37:49.943Z\", \"device_registered_owner_id\": 9100000, \"device_registered_owner_name\": \"Test User\", \"device_registered_owner_email\": \"test.user@example.com\", \"device_registered_at\": \"2026-06-18T16:38:12.195Z\"}, \"request_id\": \"01KVE1Q4W257B537D5PJD6DN7F\", \"type\": \"status_log\"}", + "type": [ + "info" + ] + }, + "gcs": { + "storage": { + "bucket": { + "name": "kolide-osquery-status" + }, + "object": { + "content_type": "application/x-ndjson", + "name": "kolide-osquery-status.log" + } + } + }, + "host": { + "hostname": "test-macbook-pro", + "id": "9000000", + "ip": [ + "203.0.113.5" + ], + "name": "test-macbook-pro" + }, + "input": { + "type": "gcs" + }, + "kolide": { + "osquery_status": { + "device_registered_at": "2026-06-18T16:38:12.195Z", + "device_serial": "TESTSERIAL0001", + "enrolled_at": "2026-06-18T16:37:49.943Z", + "hardware_uuid": "00000000-0000-0000-0000-000000000001", + "host_identifier": "00000000-0000-0000-0000-000000000001", + "request_id": "01KVE1Q4W257B537D5PJD6DN7F", + "severity": "0" + } + }, + "log": { + "file": { + "path": "gs://kolide-osquery-status/kolide-osquery-status.log" + }, + "level": "info", + "offset": 689, + "origin": { + "file": { + "line": 318, + "name": "preferences.cpp" + } + } + }, + "message": "Cannot find/read defaults plist from path: /Library/Preferences/com.apple.TimeMachine.plist", + "related": { + "hosts": [ + "test-macbook-pro" + ], + "ip": [ + "203.0.113.5" + ] + }, + "tags": [ + "preserve_original_event", + "forwarded", + "kolide-osquery-status-gcs" + ], + "user": { + "email": "test.user@example.com", + "full_name": "Test User", + "id": "9100000" + } +} +``` + ### Data streams using ILM policies diff --git a/packages/kolide/kibana/dashboard/kolide-56facae3-56fb-4637-aac5-961c69b0b4af.json b/packages/kolide/kibana/dashboard/kolide-56facae3-56fb-4637-aac5-961c69b0b4af.json index ab0ec804e42..e721a74de1d 100644 --- a/packages/kolide/kibana/dashboard/kolide-56facae3-56fb-4637-aac5-961c69b0b4af.json +++ b/packages/kolide/kibana/dashboard/kolide-56facae3-56fb-4637-aac5-961c69b0b4af.json @@ -27,11 +27,16 @@ "key": "data_stream.dataset", "negate": false, "params": [ - "kolide.auth", "kolide.audit", + "kolide.auth", "kolide.device", "kolide.device_check", + "kolide.deprovisioned_person", "kolide.issues", + "kolide.osquery_result", + "kolide.osquery_status", + "kolide.people", + "kolide.request", "kolide.webhook" ], "type": "phrases" @@ -42,12 +47,12 @@ "should": [ { "match_phrase": { - "data_stream.dataset": "kolide.auth" + "data_stream.dataset": "kolide.audit" } }, { "match_phrase": { - "data_stream.dataset": "kolide.audit" + "data_stream.dataset": "kolide.auth" } }, { @@ -60,11 +65,36 @@ "data_stream.dataset": "kolide.device_check" } }, + { + "match_phrase": { + "data_stream.dataset": "kolide.deprovisioned_person" + } + }, { "match_phrase": { "data_stream.dataset": "kolide.issues" } }, + { + "match_phrase": { + "data_stream.dataset": "kolide.osquery_result" + } + }, + { + "match_phrase": { + "data_stream.dataset": "kolide.osquery_status" + } + }, + { + "match_phrase": { + "data_stream.dataset": "kolide.people" + } + }, + { + "match_phrase": { + "data_stream.dataset": "kolide.request" + } + }, { "match_phrase": { "data_stream.dataset": "kolide.webhook" @@ -178,12 +208,12 @@ }, "gridData": { "h": 5, - "i": "22b9a37e-24a2-442f-9821-65b80efc5eba", + "i": "f7f3db2f-d628-4b30-b42a-01154de2e9f4", "w": 8, "x": 0, "y": 0 }, - "panelIndex": "22b9a37e-24a2-442f-9821-65b80efc5eba", + "panelIndex": "f7f3db2f-d628-4b30-b42a-01154de2e9f4", "type": "lens" }, { @@ -278,12 +308,12 @@ }, "gridData": { "h": 5, - "i": "0fb1121a-754a-4765-bc92-e1e5a99794ff", + "i": "cd631299-ca88-41c5-9f34-6de027c03803", "w": 8, "x": 8, "y": 0 }, - "panelIndex": "0fb1121a-754a-4765-bc92-e1e5a99794ff", + "panelIndex": "cd631299-ca88-41c5-9f34-6de027c03803", "type": "lens" }, { @@ -378,12 +408,12 @@ }, "gridData": { "h": 5, - "i": "ef5394e3-d617-4e6e-bce6-02183ee912a7", + "i": "bf6b7b6c-9062-4907-8144-809ff28d6d60", "w": 8, "x": 16, "y": 0 }, - "panelIndex": "ef5394e3-d617-4e6e-bce6-02183ee912a7", + "panelIndex": "bf6b7b6c-9062-4907-8144-809ff28d6d60", "type": "lens" }, { @@ -478,12 +508,12 @@ }, "gridData": { "h": 5, - "i": "1e03b371-f347-4db0-adc1-f3fb11ac3456", + "i": "cae8d5dd-906d-4600-8c5f-23abe66b293f", "w": 8, "x": 24, "y": 0 }, - "panelIndex": "1e03b371-f347-4db0-adc1-f3fb11ac3456", + "panelIndex": "cae8d5dd-906d-4600-8c5f-23abe66b293f", "type": "lens" }, { @@ -593,12 +623,12 @@ }, "gridData": { "h": 5, - "i": "8d667e8f-0c09-4775-9181-7aab8f120a07", + "i": "79c595fe-4e4f-4643-b5df-36df7f28d34c", "w": 5, "x": 32, "y": 0 }, - "panelIndex": "8d667e8f-0c09-4775-9181-7aab8f120a07", + "panelIndex": "79c595fe-4e4f-4643-b5df-36df7f28d34c", "type": "lens" }, { @@ -820,12 +850,12 @@ }, "gridData": { "h": 5, - "i": "347b869d-198b-461e-a1a2-74d9502cdb4b", + "i": "796b7ff5-5cff-4d9a-98cc-8aa0ed91941d", "w": 11, "x": 37, "y": 0 }, - "panelIndex": "347b869d-198b-461e-a1a2-74d9502cdb4b", + "panelIndex": "796b7ff5-5cff-4d9a-98cc-8aa0ed91941d", "type": "lens" }, { @@ -875,7 +905,7 @@ }, "orderDirection": "desc", "otherBucket": true, - "size": 6 + "size": 11 }, "sourceField": "data_stream.dataset" }, @@ -960,12 +990,12 @@ }, "gridData": { "h": 10, - "i": "1d19dd2c-a14e-4fab-88fd-d28967a5bd4d", + "i": "7a8cdb6e-aec4-414c-9e43-b111c34bdc55", "w": 32, "x": 0, "y": 5 }, - "panelIndex": "1d19dd2c-a14e-4fab-88fd-d28967a5bd4d", + "panelIndex": "7a8cdb6e-aec4-414c-9e43-b111c34bdc55", "type": "lens" }, { @@ -1081,12 +1111,12 @@ }, "gridData": { "h": 10, - "i": "f75c8e08-4e9b-4f13-a72e-5e524c558e07", + "i": "7161edad-6a3a-47a2-92a8-5cff9e1efdae", "w": 16, "x": 32, "y": 5 }, - "panelIndex": "f75c8e08-4e9b-4f13-a72e-5e524c558e07", + "panelIndex": "7161edad-6a3a-47a2-92a8-5cff9e1efdae", "type": "lens" }, { @@ -1221,12 +1251,12 @@ }, "gridData": { "h": 10, - "i": "77009d3d-9a61-4ec8-912a-c3c10b16cfd4", + "i": "11b656cc-cc99-4c3b-9418-faab6d2bc6ee", "w": 24, "x": 0, "y": 15 }, - "panelIndex": "77009d3d-9a61-4ec8-912a-c3c10b16cfd4", + "panelIndex": "11b656cc-cc99-4c3b-9418-faab6d2bc6ee", "type": "lens" }, { @@ -1368,12 +1398,12 @@ }, "gridData": { "h": 18, - "i": "c5e7038c-e8d7-4aed-a1e3-c6ae1a2a3e98", + "i": "3ab3acd7-2591-4515-9e15-0c4a97e4ea1d", "w": 48, "x": 0, "y": 25 }, - "panelIndex": "c5e7038c-e8d7-4aed-a1e3-c6ae1a2a3e98", + "panelIndex": "3ab3acd7-2591-4515-9e15-0c4a97e4ea1d", "type": "lens" }, { @@ -1502,82 +1532,1007 @@ }, "gridData": { "h": 10, - "i": "4a7c6785-09b8-4b41-8531-6bfad9f66d0d", + "i": "2dac652b-1bc6-4b77-8fa6-61c1ae954b10", "w": 24, "x": 24, "y": 15 }, - "panelIndex": "4a7c6785-09b8-4b41-8531-6bfad9f66d0d", + "panelIndex": "2dac652b-1bc6-4b77-8fa6-61c1ae954b10", "type": "lens" - } - ], - "timeRestore": false, - "title": "[Logs Kolide] Overview", - "version": 3 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-23T17:40:45.330Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "kolide-56facae3-56fb-4637-aac5-961c69b0b4af", - "references": [ - { - "id": "logs-*", - "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": { + "logs-kolide.request-*": { + "allowHidden": false, + "allowNoIndex": false, + "fieldAttrs": {}, + "fieldFormats": {}, + "id": "logs-kolide.request-*", + "name": "logs-kolide.request-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "logs-kolide.request-*" + } + }, + "datasourceStates": { + "formBased": { + "layers": { + "layer_0": { + "columnOrder": [ + "metric_col", + "metric_colX0" + ], + "columns": { + "metric_col": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Open Requests", + "operationType": "formula", + "params": { + "formula": "unique_count(kolide.request.id, kql='kolide.request.state: (\"pending\" or \"open\")')", + "isFormulaBroken": false + }, + "references": [ + "metric_colX0" + ] + }, + "metric_colX0": { + "customLabel": true, + "dataType": "number", + "filter": { + "language": "kuery", + "query": "kolide.request.state: (\"pending\" or \"open\")" + }, + "isBucketed": false, + "label": "Part of Open Requests", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "sourceField": "kolide.request.id" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layerId": "layer_0", + "layerType": "data", + "metricAccessor": "metric_col", + "secondaryTrend": { + "type": "none" + } + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "hidePanelTitles": true, + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "title": "Open Requests" + }, + "gridData": { + "h": 5, + "i": "849dc8de-058d-433a-8d91-24b4f2adfc46", + "w": 12, + "x": 0, + "y": 43 + }, + "panelIndex": "849dc8de-058d-433a-8d91-24b4f2adfc46", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "33d8f47d-56d8-41e5-ba43-1e2ab3c82e12", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": { + "logs-kolide.people-*": { + "allowHidden": false, + "allowNoIndex": false, + "fieldAttrs": {}, + "fieldFormats": {}, + "id": "logs-kolide.people-*", + "name": "logs-kolide.people-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "logs-kolide.people-*" + } + }, + "datasourceStates": { + "formBased": { + "layers": { + "layer_0": { + "columnOrder": [ + "metric_col", + "metric_colX0" + ], + "columns": { + "metric_col": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Active People", + "operationType": "formula", + "params": { + "formula": "unique_count(user.id)", + "isFormulaBroken": false + }, + "references": [ + "metric_colX0" + ] + }, + "metric_colX0": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Part of Active People", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "sourceField": "user.id" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "33d8f47d-56d8-41e5-ba43-1e2ab3c82e12", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "kolide.people" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "kolide.people" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layerId": "layer_0", + "layerType": "data", + "metricAccessor": "metric_col", + "secondaryTrend": { + "type": "none" + } + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "33d8f47d-56d8-41e5-ba43-1e2ab3c82e12", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "kolide.people" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "kolide.people" + } + } + } + ], + "hidePanelTitles": true, + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "title": "Active People" + }, + "gridData": { + "h": 5, + "i": "7f6e3cdc-c4f2-44b6-a53e-c18a4289dd49", + "w": 12, + "x": 12, + "y": 43 + }, + "panelIndex": "7f6e3cdc-c4f2-44b6-a53e-c18a4289dd49", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "ca9a799c-52bf-49d6-be0f-f5f2db5b60ce", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": { + "logs-kolide.people-*": { + "allowHidden": false, + "allowNoIndex": false, + "fieldAttrs": {}, + "fieldFormats": {}, + "id": "logs-kolide.people-*", + "name": "logs-kolide.people-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "logs-kolide.people-*" + } + }, + "datasourceStates": { + "formBased": { + "layers": { + "layer_0": { + "columnOrder": [ + "metric_col", + "metric_colX0" + ], + "columns": { + "metric_col": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "People Without Registered Device", + "operationType": "formula", + "params": { + "formula": "unique_count(user.id, kql='kolide.people.has_registered_device: false')", + "isFormulaBroken": false + }, + "references": [ + "metric_colX0" + ] + }, + "metric_colX0": { + "customLabel": true, + "dataType": "number", + "filter": { + "language": "kuery", + "query": "kolide.people.has_registered_device: false" + }, + "isBucketed": false, + "label": "Part of People Without Registered Device", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "sourceField": "user.id" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "ca9a799c-52bf-49d6-be0f-f5f2db5b60ce", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "kolide.people" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "kolide.people" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layerId": "layer_0", + "layerType": "data", + "metricAccessor": "metric_col", + "secondaryTrend": { + "type": "none" + } + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "ca9a799c-52bf-49d6-be0f-f5f2db5b60ce", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "kolide.people" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "kolide.people" + } + } + } + ], + "hidePanelTitles": true, + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "title": "People Without Registered Device" + }, + "gridData": { + "h": 5, + "i": "aa487236-865a-4072-8f64-476881b5a476", + "w": 12, + "x": 24, + "y": 43 + }, + "panelIndex": "aa487236-865a-4072-8f64-476881b5a476", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "2433ab5e-8e63-491b-b603-466f91eb15b2", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": { + "logs-kolide.deprovisioned_person-*": { + "allowHidden": false, + "allowNoIndex": false, + "fieldAttrs": {}, + "fieldFormats": {}, + "id": "logs-kolide.deprovisioned_person-*", + "name": "logs-kolide.deprovisioned_person-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "logs-kolide.deprovisioned_person-*" + } + }, + "datasourceStates": { + "formBased": { + "layers": { + "layer_0": { + "columnOrder": [ + "metric_col" + ], + "columns": { + "metric_col": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Deprovisioned People", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "sourceField": "user.id" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "2433ab5e-8e63-491b-b603-466f91eb15b2", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "kolide.deprovisioned_person" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "kolide.deprovisioned_person" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layerId": "layer_0", + "layerType": "data", + "metricAccessor": "metric_col", + "secondaryTrend": { + "type": "none" + } + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "2433ab5e-8e63-491b-b603-466f91eb15b2", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "kolide.deprovisioned_person" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "kolide.deprovisioned_person" + } + } + } + ], + "hidePanelTitles": true, + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "title": "Deprovisioned People" + }, + "gridData": { + "h": 5, + "i": "1de0c329-e847-45bd-845d-274383efff78", + "w": 12, + "x": 36, + "y": 43 + }, + "panelIndex": "1de0c329-e847-45bd-845d-274383efff78", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": { + "logs-kolide.request-*": { + "allowHidden": false, + "allowNoIndex": false, + "fieldAttrs": {}, + "fieldFormats": {}, + "id": "logs-kolide.request-*", + "name": "logs-kolide.request-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "logs-kolide.request-*" + } + }, + "datasourceStates": { + "formBased": { + "layers": { + "layer_0": { + "columnOrder": [ + "x_col", + "breakdown_col", + "y_col" + ], + "columns": { + "breakdown_col": { + "dataType": "string", + "isBucketed": true, + "label": "State", + "operationType": "terms", + "params": { + "orderBy": { + "columnId": "y_col", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "size": 10 + }, + "sourceField": "kolide.request.state" + }, + "x_col": { + "dataType": "string", + "isBucketed": true, + "label": "Request type", + "operationType": "terms", + "params": { + "accuracyMode": true, + "orderBy": { + "columnId": "y_col", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "size": 5 + }, + "sourceField": "kolide.request.type" + }, + "y_col": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Unique requests", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "sourceField": "kolide.request.id" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": false, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "y_col" + ], + "layerId": "layer_0", + "layerType": "data", + "seriesType": "bar_horizontal", + "splitAccessor": "breakdown_col", + "xAccessor": "x_col" + } + ], + "legend": { + "isVisible": true, + "position": "right", + "showSingleSeries": false + }, + "preferredSeriesType": "bar_horizontal", + "valueLabels": "hide", + "xTitle": "Request type" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsXY" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "title": "Requests by Type and State" + }, + "gridData": { + "h": 10, + "i": "cdcde96f-5ab9-4645-bc6a-641d517a3a45", + "w": 24, + "x": 0, + "y": 48 + }, + "panelIndex": "cdcde96f-5ab9-4645-bc6a-641d517a3a45", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": { + "logs-kolide.osquery_status-*": { + "allowHidden": false, + "allowNoIndex": false, + "fieldAttrs": {}, + "fieldFormats": {}, + "id": "logs-kolide.osquery_status-*", + "name": "logs-kolide.osquery_status-*", + "runtimeFieldMap": {}, + "sourceFilters": [], + "timeFieldName": "@timestamp", + "title": "logs-kolide.osquery_status-*" + } + }, + "datasourceStates": { + "formBased": { + "layers": { + "layer_0": { + "columnOrder": [ + "x_col", + "y_col" + ], + "columns": { + "x_col": { + "dataType": "string", + "isBucketed": true, + "label": "Log level", + "operationType": "terms", + "params": { + "accuracyMode": true, + "orderBy": { + "columnId": "y_col", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "size": 10 + }, + "sourceField": "log.level" + }, + "y_col": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "sourceField": "___records___" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": false, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "y_col" + ], + "layerId": "layer_0", + "layerType": "data", + "seriesType": "bar_horizontal", + "xAccessor": "x_col" + } + ], + "legend": { + "isVisible": false, + "position": "right", + "showSingleSeries": false + }, + "preferredSeriesType": "bar_horizontal", + "valueLabels": "hide", + "xTitle": "Log level" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsXY" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "title": "Osquery Status by Severity" + }, + "gridData": { + "h": 10, + "i": "8df75243-8046-4a8f-b891-57485d3005f7", + "w": 24, + "x": 24, + "y": 48 + }, + "panelIndex": "8df75243-8046-4a8f-b891-57485d3005f7", + "type": "lens" + } + ], + "timeRestore": false, + "title": "[Logs Kolide] Overview", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-09T15:16:59.232Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "kolide-56facae3-56fb-4637-aac5-961c69b0b4af", + "references": [ + { + "id": "logs-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "f7f3db2f-d628-4b30-b42a-01154de2e9f4:indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "cd631299-ca88-41c5-9f34-6de027c03803:indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "bf6b7b6c-9062-4907-8144-809ff28d6d60:indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "cae8d5dd-906d-4600-8c5f-23abe66b293f:indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "79c595fe-4e4f-4643-b5df-36df7f28d34c:indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "796b7ff5-5cff-4d9a-98cc-8aa0ed91941d:indexpattern-datasource-layer-364703ba-9ff6-44a6-bc95-544961c64548", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "7a8cdb6e-aec4-414c-9e43-b111c34bdc55:indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "7161edad-6a3a-47a2-92a8-5cff9e1efdae:indexpattern-datasource-layer-layer_0", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "11b656cc-cc99-4c3b-9418-faab6d2bc6ee:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "22b9a37e-24a2-442f-9821-65b80efc5eba:indexpattern-datasource-layer-layer_0", + "name": "3ab3acd7-2591-4515-9e15-0c4a97e4ea1d:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "0fb1121a-754a-4765-bc92-e1e5a99794ff:indexpattern-datasource-layer-layer_0", + "name": "2dac652b-1bc6-4b77-8fa6-61c1ae954b10:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "ef5394e3-d617-4e6e-bce6-02183ee912a7:indexpattern-datasource-layer-layer_0", + "name": "849dc8de-058d-433a-8d91-24b4f2adfc46:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "1e03b371-f347-4db0-adc1-f3fb11ac3456:indexpattern-datasource-layer-layer_0", + "name": "7f6e3cdc-c4f2-44b6-a53e-c18a4289dd49:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "8d667e8f-0c09-4775-9181-7aab8f120a07:indexpattern-datasource-layer-layer_0", + "name": "7f6e3cdc-c4f2-44b6-a53e-c18a4289dd49:33d8f47d-56d8-41e5-ba43-1e2ab3c82e12", "type": "index-pattern" }, { "id": "logs-*", - "name": "347b869d-198b-461e-a1a2-74d9502cdb4b:indexpattern-datasource-layer-364703ba-9ff6-44a6-bc95-544961c64548", + "name": "aa487236-865a-4072-8f64-476881b5a476:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "1d19dd2c-a14e-4fab-88fd-d28967a5bd4d:indexpattern-datasource-layer-layer_0", + "name": "aa487236-865a-4072-8f64-476881b5a476:ca9a799c-52bf-49d6-be0f-f5f2db5b60ce", "type": "index-pattern" }, { "id": "logs-*", - "name": "f75c8e08-4e9b-4f13-a72e-5e524c558e07:indexpattern-datasource-layer-layer_0", + "name": "1de0c329-e847-45bd-845d-274383efff78:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "77009d3d-9a61-4ec8-912a-c3c10b16cfd4:indexpattern-datasource-layer-layer_0", + "name": "1de0c329-e847-45bd-845d-274383efff78:2433ab5e-8e63-491b-b603-466f91eb15b2", "type": "index-pattern" }, { "id": "logs-*", - "name": "c5e7038c-e8d7-4aed-a1e3-c6ae1a2a3e98:indexpattern-datasource-layer-layer_0", + "name": "cdcde96f-5ab9-4645-bc6a-641d517a3a45:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { "id": "logs-*", - "name": "4a7c6785-09b8-4b41-8531-6bfad9f66d0d:indexpattern-datasource-layer-layer_0", + "name": "8df75243-8046-4a8f-b891-57485d3005f7:indexpattern-datasource-layer-layer_0", "type": "index-pattern" }, { diff --git a/packages/kolide/manifest.yml b/packages/kolide/manifest.yml index 22fc1f19e54..2f8fac15f3f 100644 --- a/packages/kolide/manifest.yml +++ b/packages/kolide/manifest.yml @@ -1,7 +1,7 @@ format_version: "3.4.2" name: kolide title: "Kolide" -version: "0.1.2" +version: "0.2.0" source: license: "Elastic-2.0" description: "Collect logs from Kolide (by 1Password) Device Trust with Elastic Agent." @@ -25,7 +25,7 @@ screenshots: policy_templates: - name: kolide title: Kolide logs - description: Collect logs from Kolide via webhooks (HTTP endpoint) and the REST API. + description: Collect logs from Kolide via webhooks (HTTP endpoint), the REST API, and the Log Pipeline (AWS S3 or Google Cloud Storage). deployment_modes: default: enabled: true @@ -61,7 +61,7 @@ policy_templates: - type: aws-s3 title: Collect Kolide Log Pipeline data from AWS S3 description: >- - Collect Kolide Log Pipeline data (authentication logs, audit logs, and device check-run results) that Kolide writes to a customer-owned S3 bucket, via direct bucket polling or SQS notifications. + Collect Kolide Log Pipeline data (authentication logs, audit logs, device check-run results, and raw osquery result/status logs) that Kolide writes to a customer-owned S3 bucket, via direct bucket polling or SQS notifications. vars: - name: shared_credential_file type: text @@ -122,6 +122,36 @@ policy_templates: description: URL to proxy AWS API connections, in the form of `http[s]://:@:`. required: false show_user: false + - type: gcs + title: Collect Kolide Log Pipeline data from Google Cloud Storage + description: >- + Collect Kolide Log Pipeline data (authentication logs, audit logs, device check-run results, and raw osquery result/status logs) that Kolide writes to a customer-owned GCS bucket, via bucket polling. + vars: + - name: project_id + type: text + title: Project ID + description: The GCP project ID the GCS bucket belongs to. Required to collect via GCS. + required: true + show_user: true + - name: service_account_key + type: password + title: Service Account Key + description: The GCP service account JSON key contents the Elastic Agent uses to read from the bucket. The service account only needs read access (for example, the `Storage Object Viewer` role). Alternative to the Service Account File; leave both empty to use Application Default Credentials (Workload Identity). + secret: true + required: false + show_user: true + - name: service_account_file + type: text + title: Service Account File + description: Path on the Elastic Agent host to a GCP service account JSON key file used to read from the bucket. Alternative to the Service Account Key. + required: false + show_user: false + - name: alternative_host + type: text + title: Alternative Host + description: Overrides the default host for the storage client (default is `storage.googleapis.com`). Used for testing against GCS emulators. + required: false + show_user: false owner: github: elastic/integration-experience type: elastic diff --git a/packages/osquery_manager/changelog.yml b/packages/osquery_manager/changelog.yml index 85efa174c98..ca9ae5b9580 100644 --- a/packages/osquery_manager/changelog.yml +++ b/packages/osquery_manager/changelog.yml @@ -1,4 +1,15 @@ # newer versions go on top +- version: "1.31.0" + changes: + - description: Add `query_profile` data stream and a Kibana dashboard for query profile events (Fleet stream `osquery_manager.query_profile`, Lens on `logs-*`). + type: enhancement + link: https://github.com/elastic/integrations/pull/18608 + - description: Add an ingest pipeline for `query_profile` that sets data stream values, copies `agent.id` to `agent_id`, consolidates the query identity into a single `query.name` across scheduled, RRULE, and live profiles, and drops the redundant top-level `type` discriminator. + type: enhancement + link: https://github.com/elastic/integrations/pull/18608 + - description: Expand the query profiles dashboard with top queries, top hosts, breakdown by profile source, and a drill-down executions table plus interactive filter controls. + type: enhancement + link: https://github.com/elastic/integrations/pull/18608 - version: "1.30.1" changes: - description: Add `pack_name` and `query_name` fields to the result and action_responses data streams for scheduled pack queries. diff --git a/packages/osquery_manager/manifest.yml b/packages/osquery_manager/manifest.yml index 0a7807a4a3d..a69a105b9d8 100644 --- a/packages/osquery_manager/manifest.yml +++ b/packages/osquery_manager/manifest.yml @@ -1,7 +1,7 @@ format_version: 3.5.8 name: osquery_manager title: Osquery Manager -version: 1.30.1 +version: 1.31.0 description: Deploy Osquery with Elastic Agent, then run and schedule queries in Kibana type: integration categories: @@ -17,6 +17,11 @@ icons: title: logo osquery size: 32x32 type: image/svg+xml +screenshots: + - src: /img/osquery-manager-query-profiles-dashboard.png + title: Osquery Manager query profiles dashboard + size: 1920x1688 + type: image/png policy_templates: - name: osquery_manager title: Osquery Manager diff --git a/packages/qualys_vmdr/changelog.yml b/packages/qualys_vmdr/changelog.yml index ef9763913ba..242723800a1 100644 --- a/packages/qualys_vmdr/changelog.yml +++ b/packages/qualys_vmdr/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "6.19.1" + changes: + - description: Record missing KB entries in `knowledge_base.status` instead of `error.message`, so they no longer mark documents as `pipeline_error`. + type: bugfix + link: https://github.com/elastic/integrations/pull/20052 - version: "6.19.0" changes: - description: Use new `release` field for agentless deployment mode to establish as beta. diff --git a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json index d19343c116f..edef6ec7c52 100644 --- a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json +++ b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json @@ -5,6 +5,12 @@ "interval_id": "86fae5c8-3209-4b86-ac48-4b5ba6e7adb5", "interval_start": "2025-05-20T22:57:42.484Z", "message": "{\"DETECTION_LIST\":{\"FIRST_FOUND_DATETIME\":\"2019-11-06T09:41:57Z\",\"IS_DISABLED\":\"0\",\"IS_IGNORED\":\"0\",\"LAST_FOUND_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_PROCESSED_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_TEST_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_UPDATE_DATETIME\":\"2019-11-12T15:00:26Z\",\"QID\":\"256716\",\"RESULTS\":\"Package\\tInstalled Version\\tRequired Version;;rsync\\t3.1.2-12.el7_9.tuxcare.els1.x86_64\\t3.1.2-12.el7_9.tuxcare.els2;;CentOS Linux release 7.9 (Final, ELS by Cloudlinux)\",\"SEVERITY\":\"4\",\"SSL\":\"0\",\"STATUS\":\"Active\",\"TIMES_FOUND\":\"10\",\"TYPE\":\"Confirmed\",\"UNIQUE_VULN_ID\":\"2029338482\"},\"DNS\":\"user-staging.example.net\",\"DNS_DATA\":{\"DOMAIN\":\"example.net\",\"FQDN\":\"user-staging.example.net\",\"HOSTNAME\":\"user-staging\"},\"ID\":\"117163093\",\"IP\":\"81.2.69.192\",\"KNOWLEDGE_BASE\":{\"CATEGORY\":\"CentOS\",\"CODE_MODIFIED_DATETIME\":\"2019-11-04T10:48:40Z\",\"CONSEQUENCE\":\"This vulnerability could be exploited to gain complete access to sensitive information. Malicious users could also use this vulnerability to change all the contents or configuration on the system. Additionally this vulnerability can also be used to cause a complete denial of service and could render the resource completely unavailable.\",\"CORRELATION\":{\"EXPLOITS\":{\"EXPLT_SRC\":[{\"EXPLT_LIST\":{\"EXPLT\":[{\"DESC\":\"A buffer overflow flaw was found, in versions from 2.6.34 to 5.2.x, in the way Linux kernel's vhost functionality that translates virtqueue buffers to IOVs, logged the buffer descriptors during migration. A privileged guest user able to pass descriptors with invalid length to the host when migration is underway, could use this flaw to increase their privileges on the host.\",\"LINK\":\"https://www.openwall.com/lists/oss-security/2019/09/17/1\",\"REF\":\"CVE-2019-14835\"}]},\"SRC_NAME\":\"nist-nvd2\"},{\"EXPLT_LIST\":{\"EXPLT\":[{\"DESC\":\"A buffer overflow flaw was found, in versions from 2.6.34 to 5.2.x, in the way Linux kernel's vhost functionality that translates virtqueue buffers to IOVs, logged the buffer descriptors during migration. A privileged guest user able to pass descriptors with invalid length to the host when migration is underway, could use this flaw to increase their privileges on the host.\",\"LINK\":\"https://www.openwall.com/lists/oss-security/2019/09/17/1\",\"REF\":\"CVE-2019-14835\"}]},\"SRC_NAME\":\"nvd\"}]}},\"CVE_LIST\":[\"CVE-2019-14835\"],\"CVSS\":{\"BASE\":\"7.2\",\"TEMPORAL\":\"5.6\",\"VECTOR_STRING\":\"CVSS:2.0/AV:L/AC:L/Au:N/C:C/I:C/A:C/E:POC/RL:OF/RC:C\"},\"CVSS_V3\":{\"BASE\":\"7.8\",\"CVSS3_VERSION\":\"3.1\",\"TEMPORAL\":\"7.0\",\"VECTOR_STRING\":\"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:P/RL:O/RC:C\"},\"DIAGNOSIS\":\"CentOS has released security update for kernel to fix the vulnerabilities.

      Affected Products:

      centos 7\",\"DISCOVERY\":{\"ADDITIONAL_INFO\":\"Patch Available, Exploit Available\",\"AUTH_TYPE_LIST\":{\"AUTH_TYPE\":[\"Unix\"]},\"REMOTE\":\"0\"},\"LAST_SERVICE_MODIFICATION_DATETIME\":\"2024-03-01T00:00:02Z\",\"PATCHABLE\":\"1\",\"PCI_FLAG\":\"1\",\"PUBLISHED_DATETIME\":\"2019-11-04T10:48:40Z\",\"QID\":\"256716\",\"SEVERITY_LEVEL\":\"4\",\"SOFTWARE_LIST\":{\"SOFTWARE\":[{\"PRODUCT\":\"kernel\",\"VENDOR\":\"centos\"}]},\"SOLUTION\":\"To resolve this issue, upgrade to the latest packages which contain a patch. Refer to CentOS advisory
      centos 7 for updates and patch information.\\n

      Patch:
      \\nFollowing are links for downloading patches to fix the vulnerabilities:\\n

      CESA-2019:2829:centos 7\",\"THREAT_INTELLIGENCE\":{\"THREAT_INTEL\":[{\"#text\":\"Exploit_Public\",\"id\":\"2\"},{\"#text\":\"High_Lateral_Movement\",\"id\":\"4\"},{\"#text\":\"Easy_Exploit\",\"id\":\"5\"},{\"#text\":\"High_Data_Loss\",\"id\":\"6\"},{\"#text\":\"Denial_of_Service\",\"id\":\"7\"}]},\"TITLE\":\"CentOS Security Update for kernel (CESA-2019:2829)\",\"VENDOR_REFERENCE_LIST\":{\"VENDOR_REFERENCE\":[{\"ID\":\"CESA-2019:2829 centos 7\",\"URL\":\"https://lists.centos.org/pipermail/centos-announce/2019-October/023457.html\"}]},\"VULN_TYPE\":\"Vulnerability\"},\"LAST_PC_SCANNED_DATE\":\"2019-11-11T22:25:02Z\",\"LAST_SCAN_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_VM_AUTH_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"LAST_VM_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"NETWORK_ID\":\"0\",\"OS\":\"CentOS Linux 7.4.1708\",\"QG_HOSTID\":\"19260abb-8547-467e-928d-73c13f13ea3c\",\"TRACKING_METHOD\":\"AGENT\"}" + }, + { + "@timestamp": "2025-12-01T10:15:00.000Z", + "interval_id": "9d69b1dc-8e86-4946-809e-577433b1d999", + "interval_start": "2025-12-01T10:15:00Z", + "message": "{\"DETECTION_LIST\":{\"FIRST_FOUND_DATETIME\":\"2019-11-06T09:41:57Z\",\"IS_DISABLED\":\"0\",\"IS_IGNORED\":\"0\",\"LAST_FOUND_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_PROCESSED_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_TEST_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_UPDATE_DATETIME\":\"2019-11-12T15:00:26Z\",\"QID\":\"256716\",\"SEVERITY\":\"4\",\"SSL\":\"0\",\"STATUS\":\"Active\",\"TIMES_FOUND\":\"10\",\"TYPE\":\"Confirmed\",\"UNIQUE_VULN_ID\":\"2029338483\"},\"DNS\":\"user-noKB.example.net\",\"DNS_DATA\":{\"DOMAIN\":\"example.net\",\"FQDN\":\"user-noKB.example.net\",\"HOSTNAME\":\"user-noKB\"},\"ID\":\"117163099\",\"IP\":\"81.2.69.193\",\"LAST_PC_SCANNED_DATE\":\"2019-11-11T22:25:02Z\",\"LAST_SCAN_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_VM_AUTH_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"LAST_VM_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"NETWORK_ID\":\"0\",\"OS\":\"CentOS Linux 7.4.1708\",\"QG_HOSTID\":\"19260abb-8547-467e-928d-73c13f13ea3d\",\"TRACKING_METHOD\":\"AGENT\"}" } ] } \ No newline at end of file diff --git a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json-expected.json b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json-expected.json index fb3921d37fd..3f538c05923 100644 --- a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json-expected.json +++ b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection-events.json-expected.json @@ -139,6 +139,7 @@ "solution": { "value": "To resolve this issue, upgrade to the latest packages which contain a patch. Refer to CentOS advisory centos 7 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      CESA-2019:2829:centos 7" }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -261,6 +262,110 @@ "severity": "High", "title": "CentOS Security Update for kernel (CESA-2019:2829)" } + }, + { + "@timestamp": "2025-12-01T10:15:00.000Z", + "cloud": { + "instance": { + "name": "user-noKB" + } + }, + "ecs": { + "version": "8.11.0" + }, + "event": { + "category": [ + "vulnerability" + ], + "id": "2029338483", + "kind": "alert", + "original": "{\"DETECTION_LIST\":{\"FIRST_FOUND_DATETIME\":\"2019-11-06T09:41:57Z\",\"IS_DISABLED\":\"0\",\"IS_IGNORED\":\"0\",\"LAST_FOUND_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_PROCESSED_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_TEST_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_UPDATE_DATETIME\":\"2019-11-12T15:00:26Z\",\"QID\":\"256716\",\"SEVERITY\":\"4\",\"SSL\":\"0\",\"STATUS\":\"Active\",\"TIMES_FOUND\":\"10\",\"TYPE\":\"Confirmed\",\"UNIQUE_VULN_ID\":\"2029338483\"},\"DNS\":\"user-noKB.example.net\",\"DNS_DATA\":{\"DOMAIN\":\"example.net\",\"FQDN\":\"user-noKB.example.net\",\"HOSTNAME\":\"user-noKB\"},\"ID\":\"117163099\",\"IP\":\"81.2.69.193\",\"LAST_PC_SCANNED_DATE\":\"2019-11-11T22:25:02Z\",\"LAST_SCAN_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_VM_AUTH_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"LAST_VM_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"NETWORK_ID\":\"0\",\"OS\":\"CentOS Linux 7.4.1708\",\"QG_HOSTID\":\"19260abb-8547-467e-928d-73c13f13ea3d\",\"TRACKING_METHOD\":\"AGENT\"}", + "type": [ + "info" + ] + }, + "host": { + "hostname": "user-noKB", + "id": "117163099", + "ip": [ + "81.2.69.193" + ], + "name": "user-noKB.example.net", + "os": { + "full": "CentOS Linux 7.4.1708", + "platform": "linux", + "type": "linux" + } + }, + "observer": { + "vendor": "Qualys VMDR" + }, + "qualys_vmdr": { + "asset_host_detection": { + "dns": "user-noKB.example.net", + "dns_data": { + "domain": "example.net", + "fqdn": "user-noKB.example.net", + "hostname": "user-noKB" + }, + "id": "117163099", + "interval_id": "9d69b1dc-8e86-4946-809e-577433b1d999", + "interval_start": "2025-12-01T10:15:00.000Z", + "ip": "81.2.69.193", + "knowledge_base": { + "status": "not_found" + }, + "last_pc_scanned_date": "2019-11-11T22:25:02.000Z", + "last_scan_datetime": "2019-11-12T15:00:26.000Z", + "last_vm_auth_scanned_date": "2019-11-11T23:29:53.000Z", + "last_vm_scanned_date": "2019-11-11T23:29:53.000Z", + "network_id": "0", + "os": "CentOS Linux 7.4.1708", + "qg_hostid": "19260abb-8547-467e-928d-73c13f13ea3d", + "tracking_method": "AGENT", + "vulnerability": { + "first_found_datetime": "2019-11-06T09:41:57.000Z", + "is_disabled": false, + "is_ignored": false, + "last_found_datetime": "2019-11-11T23:29:53.000Z", + "last_processed_datetime": "2019-11-12T15:00:26.000Z", + "last_test_datetime": "2019-11-11T23:29:53.000Z", + "last_update_datetime": "2019-11-12T15:00:26.000Z", + "qid": 256716, + "severity": 4, + "ssl": "0", + "status": "Active", + "times_found": 10, + "type": "Confirmed", + "unique_vuln_id": "2029338483" + } + } + }, + "related": { + "hosts": [ + "user-noKB", + "user-noKB.example.net", + "117163099", + "19260abb-8547-467e-928d-73c13f13ea3d" + ], + "ip": [ + "81.2.69.193" + ] + }, + "resource": { + "id": "117163099", + "name": "user-noKB.example.net" + }, + "tags": [ + "preserve_original_event", + "preserve_duplicate_custom_fields", + "provider_cloud_data" + ], + "vulnerability": { + "scanner": { + "vendor": "Qualys" + } + } } ] } diff --git a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log index 9076a5324dd..1a9dd3ff0c3 100644 --- a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log +++ b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log @@ -6,3 +6,4 @@ {"interval_id":"9d69b1dc-abcd-4946-1234-577abcdef843","interval_start":"2025-06-10T14:29:00Z","DETECTION_LIST":{"FIRST_FOUND_DATETIME":"2019-11-06T09:41:57Z","IS_DISABLED":"0","IS_IGNORED":"0","LAST_FOUND_DATETIME":"2019-11-11T23:29:53Z","LAST_PROCESSED_DATETIME":"2019-11-12T15:00:26Z","LAST_TEST_DATETIME":"2019-11-11T23:29:53Z","LAST_UPDATE_DATETIME":"2019-11-12T15:00:26Z","QID":"212346","RESULTS":"Package\tInstalled Version\tRequired Version\nkernel-devel\t3.10.0-1062.1.1.el7.x86_64\t3.10.0-1062.1.2.el7\nkernel\t3.10.0-1062.1.1.el7.x86_64\t3.10.0-1062.1.2.el7","SEVERITY":"4","SSL":"0","STATUS":"Active","TIMES_FOUND":"10","TYPE":"Confirmed","UNIQUE_VULN_ID":"2012345682"},"DNS":"user-staging.example.net","DNS_DATA":{"DOMAIN":"example.net","FQDN":"user-staging.example.net","HOSTNAME":"user-staging"},"ID":"111234563","IP":"175.16.199.1","KNOWLEDGE_BASE":{"CATEGORY":"CentOS","CODE_MODIFIED_DATETIME":"2019-11-04T10:48:40Z","CONSEQUENCE":"This vulnerability could be exploited to gain complete access to sensitive information. Malicious users could also use this vulnerability to change all the contents or configuration on the system. Additionally this vulnerability can also be used to cause a complete denial of service and could render the resource completely unavailable.","CORRELATION":{"EXPLOITS":{"EXPLT_SRC":[{"EXPLT_LIST":{"EXPLT":[{"DESC":"A buffer overflow flaw was found, in versions from 2.6.34 to 5.2.x, in the way Linux kernel's vhost functionality that translates virtqueue buffers to IOVs, logged the buffer descriptors during migration. A privileged guest user able to pass descriptors with invalid length to the host when migration is underway, could use this flaw to increase their privileges on the host.","LINK":"https://www.openwall.com/lists/oss-security/2019/09/17/1","REF":"CVE-2019-14835"}]},"SRC_NAME":"nist-nvd2"},{"EXPLT_LIST":{"EXPLT":[{"DESC":"A buffer overflow flaw was found, in versions from 2.6.34 to 5.2.x, in the way Linux kernel's vhost functionality that translates virtqueue buffers to IOVs, logged the buffer descriptors during migration. A privileged guest user able to pass descriptors with invalid length to the host when migration is underway, could use this flaw to increase their privileges on the host.","LINK":"https://www.openwall.com/lists/oss-security/2019/09/17/1","REF":"CVE-2019-14835"}]},"SRC_NAME":"nvd"}]}},"CVE_LIST":["CVE-2019-14835"],"CVSS":{"BASE":"7.2","TEMPORAL":"5.6","VECTOR_STRING":"CVSS:2.0/AV:L/AC:L/Au:N/C:C/I:C/A:C/E:POC/RL:OF/RC:C"},"DIAGNOSIS":"CentOS has released security update for kernel to fix the vulnerabilities.

      Affected Products:

      centos 7","DISCOVERY":{"ADDITIONAL_INFO":"Patch Available, Exploit Available","AUTH_TYPE_LIST":{"AUTH_TYPE":["Unix"]},"REMOTE":"0"},"LAST_SERVICE_MODIFICATION_DATETIME":"2024-05-01T00:00:02Z","PATCHABLE":"1","PCI_FLAG":"1","PUBLISHED_DATETIME":"2019-11-04T10:48:40Z","QID":"212346","SEVERITY_LEVEL":"4","SOFTWARE_LIST":{"SOFTWARE":[{"PRODUCT":"kernel","VENDOR":"centos"}]},"SOLUTION":"To resolve this issue, upgrade to the latest packages which contain a patch. Refer to CentOS advisory centos 7 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      CESA-2019:2829:centos 7","THREAT_INTELLIGENCE":{"THREAT_INTEL":[{"#text":"Exploit_Public","id":"2"},{"#text":"High_Lateral_Movement","id":"4"},{"#text":"Easy_Exploit","id":"5"},{"#text":"High_Data_Loss","id":"6"},{"#text":"Denial_of_Service","id":"7"}]},"TITLE":"CentOS Security Update for kernel (CESA-2019:2829)","VENDOR_REFERENCE_LIST":{"VENDOR_REFERENCE":[{"ID":"CESA-2019:2829 centos 7","URL":"https://lists.centos.org/pipermail/centos-announce/2019-October/023457.html"}]},"VULN_TYPE":"Vulnerability"},"LAST_PC_SCANNED_DATE":"2019-11-11T22:25:02Z","LAST_SCAN_DATETIME":"2019-11-12T15:00:26Z","LAST_VM_AUTH_SCANNED_DATE":"2019-11-11T23:29:53Z","LAST_VM_SCANNED_DATE":"2019-11-11T23:29:53Z","NETWORK_ID":"0","OS":"CentOS Linux 7.4.1708","QG_HOSTID":"19260abb-1234-5678-9012-73cabcdefa3c","TRACKING_METHOD":"AGENT"} {"DETECTION_LIST":{"FIRST_FOUND_DATETIME":"2025-07-22T19:57:38Z","IS_DISABLED":"0","IS_IGNORED":"0","LAST_FOUND_DATETIME":"2025-07-24T09:57:38Z","LAST_PROCESSED_DATETIME":"2025-07-24T09:57:38Z","LAST_TEST_DATETIME":"2025-07-24T09:57:38Z","LAST_UPDATE_DATETIME":"2025-07-24T09:57:38Z","QDS":{"#text":"35","severity":"LOW"},"QDS_FACTORS":{"QDS_FACTOR":[{"#text":"No_Patch,High_Data_Loss,High_Lateral_Movement","name":"RTI"},{"#text":"7.3","name":"CVSS"},{"#text":"v2","name":"CVSS_version"},{"#text":"3.0","name":"QID_severity"}]},"QID":"12345","RESULTS":"HKLM\\System\\CurrentControlSet\\Services\\LanManWorkstation\\Parameters requiresecuritysignature = 0","SEVERITY":"3","SSL":"0","STATUS":"Active","TIMES_FOUND":"4","TYPE":"Confirmed","UNIQUE_VULN_ID":"10123456787"},"DNS":"es-pabcde02","DNS_DATA":{"DOMAIN":"","FQDN":"","HOSTNAME":"es-pabcde02"},"ID":"1123456787","IP":"1.128.0.1","KNOWLEDGE_BASE":{"CATEGORY":"Windows","CODE_MODIFIED_DATETIME":"2023-04-26T06:24:46Z","CONSEQUENCE":"Unauthorized users sniffing the network could catch many challenge/response exchanges and replay the whole thing to grab particular session keys, and then authenticate on the Domain Controller.","CVE_LIST":[],"CVSS":{"BASE":{"#text":"7.3","source":"service"},"TEMPORAL":"5.9","VECTOR_STRING":"CVSS:2.0/AV:A/AC:M/Au:N/C:C/I:C/A:N/E:U/RL:W/RC:C"},"DIAGNOSIS":"This host does not seem to be using SMB (Server Message Block) signing. SMB signing is a security mechanism in the SMB protocol and is also known as security signatures. SMB signing is designed to help improve the security of the SMB protocol.\n

      \nSMB signing adds security to a network using NetBIOS, avoiding man-in-the-middle attacks.\n

      \nWhen SMB signing is enabled on both the client and server SMB sessions are authenticated between the machines on a packet by packet basis.

      \n\nQID Detection Logic:
      \nThis checks from the registry value of RequireSecuritySignature and EnableSecuritySignature from HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters for client and HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\LanmanServer\\Parameters for servers to check if SMB signing is required or enabled or disabled.

      \n\nNote: On 5/28/2020 the QID was updated to check for client SMB signing behavior via the registry key HKEY_LOCAL_MACHINE\\SystemCurrent\\ControlSetServices\\LanmanWorkStation\\Parameters. The complete detection logic is explained above.

      ","DISCOVERY":{"AUTH_TYPE_LIST":{"AUTH_TYPE":["Windows"]},"REMOTE":"1"},"LAST_SERVICE_MODIFICATION_DATETIME":"2024-10-25T05:00:01Z","PATCHABLE":"0","PCI_FLAG":"1","PUBLISHED_DATETIME":"1999-01-01T08:00:00Z","QID":"12345","SEVERITY_LEVEL":"3","SOFTWARE_LIST":{"SOFTWARE":[{"PRODUCT":"smb","VENDOR":"multi-vendor"}]},"SOLUTION":"Without SMB signing, a device could intercept SMB network packets from an originating computer, alter their contents, and broadcast them to the destination computer. Since, digitally signing the packets enables the recipient of the packets to confirm their point of origination and their authenticity, it is recommended that SMB signing is enabled and required.\n

      \nPlease refer to Microsoft's article 887429 and The Basics of SMB Signing (covering both SMB1 and SMB2) for information on enabling SMB signing. \n

      \nFor Windows Server 2008 R2, Windows Server 2012, please refer to Microsoft's article Require SMB Security Signatures for information on enabling SMB signing. For group policies please refer to Microsoft's article Modify Security Policies in Default Domain Controllers Policy\n

      \nFor UNIX systems

      \n\nTo require samba clients running "smbclient" to use packet signing, add the following to the "[global]" section of the Samba configuration file:

      \n\nclient signing = mandatory\n

      ","THREAT_INTELLIGENCE":{"THREAT_INTEL":[{"#text":"High_Lateral_Movement","id":"4"},{"#text":"High_Data_Loss","id":"6"},{"#text":"No_Patch","id":"8"}]},"TITLE":"SMB Signing Disabled or SMB Signing Not Required","VULN_TYPE":"Vulnerability"},"LAST_SCAN_DATETIME":"2025-07-24T09:57:38Z","LAST_VM_AUTH_SCANNED_DATE":"2025-07-24T09:57:38Z","LAST_VM_SCANNED_DATE":"2025-07-24T09:57:38Z","LAST_VM_SCANNED_DURATION":"175","NETBIOS":"ES-pabcde02","NETWORK_ID":"0","OS":"Windows 11 Pro 64 bit Edition Version 22H2","QG_HOSTID":"69abcde8-1234-4134-5678-19abcdeffa0a","TRACKING_METHOD":"AGENT","interval_id":"f10d9ca1-1234-4e4f-9546-f4ab94dc901d","interval_start":"2025-07-24T13:19:37.031904353Z"} {"DETECTION_LIST":{"CVE":"CVE-2023-48161,CVE-2024-21208,CVE-2024-21210,CVE-2024-21217,CVE-2024-21235","FIRST_FOUND_DATETIME":"2025-11-22T19:57:38Z","IS_DISABLED":"0","IS_IGNORED":"0","LAST_FOUND_DATETIME":"2025-11-24T09:57:38Z","LAST_PROCESSED_DATETIME":"2025-11-24T09:57:38Z","LAST_TEST_DATETIME":"2025-11-24T09:57:38Z","LAST_UPDATE_DATETIME":"2025-11-24T09:57:38Z","LATEST_VULNERABILITY_DETECTION_SOURCE":"Cloud Agent","MITRE_TACTIC_NAME":"lateral-movement, privilege-escalation","MITRE_TECHNIQUE_NAME":"Exploitation of Remote Services, Exploitation for Privilege Escalation","MITRE_TACTIC_ID":"TA0008, TA0004","MITRE_TECHNIQUE_ID":"T1210, T1068","QDS":{"#text":"35","severity":"LOW"},"QDS_FACTORS":{"QDS_FACTOR":[{"#text":"No_Patch,High_Data_Loss,High_Lateral_Movement","name":"RTI"},{"#text":"7.3","name":"CVSS"},{"#text":"v2","name":"CVSS_version"},{"#text":"3.0","name":"QID_severity"}]},"QID":"33335","RESULTS":"HKLM\\System\\CurrentControlSet\\Services\\LanManWorkstation\\Parameters requiresecuritysignature = 0","SEVERITY":"3","SSL":"0","STATUS":"Active","TIMES_FOUND":"4","TYPE":"Confirmed","UNIQUE_VULN_ID":"10333356787","VULNERABILITY_DETECTION_SOURCES":"Cloud Agent,Internal Scanner"},"DNS":"es-abcde03","DNS_DATA":{"DOMAIN":"","FQDN":"","HOSTNAME":"es-abcde03"},"ID":"1333356787","IP":"1.128.0.1","KNOWLEDGE_BASE":{"CATEGORY":"Windows","CODE_MODIFIED_DATETIME":"2023-04-26T06:24:46Z","CONSEQUENCE":"Unauthorized users sniffing the network could catch many challenge/response exchanges and replay the whole thing to grab particular session keys, and then authenticate on the Domain Controller.","CVE_LIST":[],"CVSS":{"BASE":{"#text":"7.3","source":"service"},"TEMPORAL":"5.9","VECTOR_STRING":"CVSS:2.0/AV:A/AC:M/Au:N/C:C/I:C/A:N/E:U/RL:W/RC:C"},"DIAGNOSIS":"This host does not seem to be using SMB (Server Message Block) signing. SMB signing is a security mechanism in the SMB protocol and is also known as security signatures. SMB signing is designed to help improve the security of the SMB protocol.\n

      \nSMB signing adds security to a network using NetBIOS, avoiding man-in-the-middle attacks.\n

      \nWhen SMB signing is enabled on both the client and server SMB sessions are authenticated between the machines on a packet by packet basis.

      \n\nQID Detection Logic:
      \nThis checks from the registry value of RequireSecuritySignature and EnableSecuritySignature from HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters for client and HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\LanmanServer\\Parameters for servers to check if SMB signing is required or enabled or disabled.

      \n\nNote: On 5/28/2020 the QID was updated to check for client SMB signing behavior via the registry key HKEY_LOCAL_MACHINE\\SystemCurrent\\ControlSetServices\\LanmanWorkStation\\Parameters. The complete detection logic is explained above.

      ","DISCOVERY":{"AUTH_TYPE_LIST":{"AUTH_TYPE":["Windows"]},"REMOTE":"1"},"LAST_SERVICE_MODIFICATION_DATETIME":"2024-10-25T05:00:01Z","PATCHABLE":"0","PCI_FLAG":"1","PUBLISHED_DATETIME":"1999-01-01T08:00:00Z","QID":"33335","SEVERITY_LEVEL":"3","SOFTWARE_LIST":{"SOFTWARE":[{"PRODUCT":"smb","VENDOR":"multi-vendor"}]},"SOLUTION":"Without SMB signing, a device could intercept SMB network packets from an originating computer, alter their contents, and broadcast them to the destination computer. Since, digitally signing the packets enables the recipient of the packets to confirm their point of origination and their authenticity, it is recommended that SMB signing is enabled and required.\n

      \nPlease refer to Microsoft's article 887429 and The Basics of SMB Signing (covering both SMB1 and SMB2) for information on enabling SMB signing. \n

      \nFor Windows Server 2008 R2, Windows Server 2012, please refer to Microsoft's article Require SMB Security Signatures for information on enabling SMB signing. For group policies please refer to Microsoft's article Modify Security Policies in Default Domain Controllers Policy\n

      \nFor UNIX systems

      \n\nTo require samba clients running "smbclient" to use packet signing, add the following to the "[global]" section of the Samba configuration file:

      \n\nclient signing = mandatory\n

      ","THREAT_INTELLIGENCE":{"THREAT_INTEL":[{"#text":"High_Lateral_Movement","id":"4"},{"#text":"High_Data_Loss","id":"6"},{"#text":"No_Patch","id":"8"}]},"TITLE":"SMB Signing Disabled or SMB Signing Not Required","VULN_TYPE":"Vulnerability"},"LAST_SCAN_DATETIME":"2025-11-24T09:57:38Z","LAST_VM_AUTH_SCANNED_DATE":"2025-11-24T09:57:38Z","LAST_VM_SCANNED_DATE":"2025-11-24T09:57:38Z","LAST_VM_SCANNED_DURATION":"175","NETBIOS":"ES-abcde03","NETWORK_ID":"0","OS":"Windows 11 Pro 64 bit Edition Version 22H2","QG_HOSTID":"69abcde8-3333-4134-5678-19abcdeffa0a","TRACKING_METHOD":"AGENT","interval_id":"f10d9ab1-3333-4e4f-9546-f4ab94dc901d","interval_start":"2025-11-24T13:19:37.031904353Z"} +{"interval_id":"9d69b1dc-8e86-4946-809e-577433b1d999","interval_start":"2025-12-01T10:15:00Z","DETECTION_LIST":{"FIRST_FOUND_DATETIME":"2019-11-06T09:41:57Z","IS_DISABLED":"0","IS_IGNORED":"0","LAST_FOUND_DATETIME":"2019-11-11T23:29:53Z","LAST_PROCESSED_DATETIME":"2019-11-12T15:00:26Z","LAST_TEST_DATETIME":"2019-11-11T23:29:53Z","LAST_UPDATE_DATETIME":"2019-11-12T15:00:26Z","QID":"256716","SEVERITY":"4","SSL":"0","STATUS":"Active","TIMES_FOUND":"10","TYPE":"Confirmed","UNIQUE_VULN_ID":"2029338483"},"DNS":"user-noKB.example.net","DNS_DATA":{"DOMAIN":"example.net","FQDN":"user-noKB.example.net","HOSTNAME":"user-noKB"},"ID":"117163099","IP":"81.2.69.193","LAST_PC_SCANNED_DATE":"2019-11-11T22:25:02Z","LAST_SCAN_DATETIME":"2019-11-12T15:00:26Z","LAST_VM_AUTH_SCANNED_DATE":"2019-11-11T23:29:53Z","LAST_VM_SCANNED_DATE":"2019-11-11T23:29:53Z","NETWORK_ID":"0","OS":"CentOS Linux 7.4.1708","QG_HOSTID":"19260abb-8547-467e-928d-73c13f13ea3d","TRACKING_METHOD":"AGENT"} diff --git a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log-expected.json b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log-expected.json index 7ea71664bf7..7dfe4de15c9 100644 --- a/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log-expected.json +++ b/packages/qualys_vmdr/data_stream/asset_host_detection/_dev/test/pipeline/test-asset-host-detection.log-expected.json @@ -140,6 +140,7 @@ "solution": { "value": "To resolve this issue, upgrade to the latest packages which contain a patch. Refer to CentOS advisory centos 7 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      CESA-2019:2829:centos 7" }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -413,6 +414,7 @@ "solution": { "value": "Refer to Ubuntu security advisory USN-7022-1 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      USN-7022-1:Ubuntu Linux" }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -1127,6 +1129,7 @@ "solution": { "value": "Refer to Ubuntu security advisory USN-6605-1 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      USN-6605-1:Ubuntu Linux" }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -1806,6 +1809,7 @@ "solution": { "value": "To resolve this issue, upgrade to the latest packages which contain a patch. Refer to CentOS advisory centos 7 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      CESA-2019:2829:centos 7" }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -2068,6 +2072,7 @@ "solution": { "value": "To resolve this issue, upgrade to the latest packages which contain a patch. Refer to CentOS advisory centos 7 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      CESA-2019:2829:centos 7" }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -2332,6 +2337,7 @@ "solution": { "value": "To resolve this issue, upgrade to the latest packages which contain a patch. Refer to CentOS advisory centos 7 for updates and patch information.\n

      Patch:
      \nFollowing are links for downloading patches to fix the vulnerabilities:\n

      CESA-2019:2829:centos 7" }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -2550,6 +2556,7 @@ "solution": { "value": "Without SMB signing, a device could intercept SMB network packets from an originating computer, alter their contents, and broadcast them to the destination computer. Since, digitally signing the packets enables the recipient of the packets to confirm their point of origination and their authenticity, it is recommended that SMB signing is enabled and required.\n

      \nPlease refer to Microsoft's article 887429 and The Basics of SMB Signing (covering both SMB1 and SMB2) for information on enabling SMB signing. \n

      \nFor Windows Server 2008 R2, Windows Server 2012, please refer to Microsoft's article Require SMB Security Signatures for information on enabling SMB signing. For group policies please refer to Microsoft's article Modify Security Policies in Default Domain Controllers Policy\n

      \nFor UNIX systems

      \n\nTo require samba clients running "smbclient" to use packet signing, add the following to the "[global]" section of the Samba configuration file:

      \n\nclient signing = mandatory\n

      " }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -2745,6 +2752,7 @@ "solution": { "value": "Without SMB signing, a device could intercept SMB network packets from an originating computer, alter their contents, and broadcast them to the destination computer. Since, digitally signing the packets enables the recipient of the packets to confirm their point of origination and their authenticity, it is recommended that SMB signing is enabled and required.\n

      \nPlease refer to Microsoft's article 887429 and The Basics of SMB Signing (covering both SMB1 and SMB2) for information on enabling SMB signing. \n

      \nFor Windows Server 2008 R2, Windows Server 2012, please refer to Microsoft's article Require SMB Security Signatures for information on enabling SMB signing. For group policies please refer to Microsoft's article Modify Security Policies in Default Domain Controllers Policy\n

      \nFor UNIX systems

      \n\nTo require samba clients running "smbclient" to use packet signing, add the following to the "[global]" section of the Samba configuration file:

      \n\nclient signing = mandatory\n

      " }, + "status": "found", "threat_intelligence": { "intel": [ { @@ -2879,6 +2887,109 @@ "severity": "High", "title": "SMB Signing Disabled or SMB Signing Not Required" } + }, + { + "cloud": { + "instance": { + "name": "user-noKB" + } + }, + "ecs": { + "version": "8.11.0" + }, + "event": { + "category": [ + "vulnerability" + ], + "id": "2029338483", + "kind": "alert", + "original": "{\"interval_id\":\"9d69b1dc-8e86-4946-809e-577433b1d999\",\"interval_start\":\"2025-12-01T10:15:00Z\",\"DETECTION_LIST\":{\"FIRST_FOUND_DATETIME\":\"2019-11-06T09:41:57Z\",\"IS_DISABLED\":\"0\",\"IS_IGNORED\":\"0\",\"LAST_FOUND_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_PROCESSED_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_TEST_DATETIME\":\"2019-11-11T23:29:53Z\",\"LAST_UPDATE_DATETIME\":\"2019-11-12T15:00:26Z\",\"QID\":\"256716\",\"SEVERITY\":\"4\",\"SSL\":\"0\",\"STATUS\":\"Active\",\"TIMES_FOUND\":\"10\",\"TYPE\":\"Confirmed\",\"UNIQUE_VULN_ID\":\"2029338483\"},\"DNS\":\"user-noKB.example.net\",\"DNS_DATA\":{\"DOMAIN\":\"example.net\",\"FQDN\":\"user-noKB.example.net\",\"HOSTNAME\":\"user-noKB\"},\"ID\":\"117163099\",\"IP\":\"81.2.69.193\",\"LAST_PC_SCANNED_DATE\":\"2019-11-11T22:25:02Z\",\"LAST_SCAN_DATETIME\":\"2019-11-12T15:00:26Z\",\"LAST_VM_AUTH_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"LAST_VM_SCANNED_DATE\":\"2019-11-11T23:29:53Z\",\"NETWORK_ID\":\"0\",\"OS\":\"CentOS Linux 7.4.1708\",\"QG_HOSTID\":\"19260abb-8547-467e-928d-73c13f13ea3d\",\"TRACKING_METHOD\":\"AGENT\"}", + "type": [ + "info" + ] + }, + "host": { + "hostname": "user-noKB", + "id": "117163099", + "ip": [ + "81.2.69.193" + ], + "name": "user-noKB.example.net", + "os": { + "full": "CentOS Linux 7.4.1708", + "platform": "linux", + "type": "linux" + } + }, + "observer": { + "vendor": "Qualys VMDR" + }, + "qualys_vmdr": { + "asset_host_detection": { + "dns": "user-noKB.example.net", + "dns_data": { + "domain": "example.net", + "fqdn": "user-noKB.example.net", + "hostname": "user-noKB" + }, + "id": "117163099", + "interval_id": "9d69b1dc-8e86-4946-809e-577433b1d999", + "interval_start": "2025-12-01T10:15:00.000Z", + "ip": "81.2.69.193", + "knowledge_base": { + "status": "not_found" + }, + "last_pc_scanned_date": "2019-11-11T22:25:02.000Z", + "last_scan_datetime": "2019-11-12T15:00:26.000Z", + "last_vm_auth_scanned_date": "2019-11-11T23:29:53.000Z", + "last_vm_scanned_date": "2019-11-11T23:29:53.000Z", + "network_id": "0", + "os": "CentOS Linux 7.4.1708", + "qg_hostid": "19260abb-8547-467e-928d-73c13f13ea3d", + "tracking_method": "AGENT", + "vulnerability": { + "first_found_datetime": "2019-11-06T09:41:57.000Z", + "is_disabled": false, + "is_ignored": false, + "last_found_datetime": "2019-11-11T23:29:53.000Z", + "last_processed_datetime": "2019-11-12T15:00:26.000Z", + "last_test_datetime": "2019-11-11T23:29:53.000Z", + "last_update_datetime": "2019-11-12T15:00:26.000Z", + "qid": 256716, + "severity": 4, + "ssl": "0", + "status": "Active", + "times_found": 10, + "type": "Confirmed", + "unique_vuln_id": "2029338483" + } + } + }, + "related": { + "hosts": [ + "user-noKB", + "user-noKB.example.net", + "117163099", + "19260abb-8547-467e-928d-73c13f13ea3d" + ], + "ip": [ + "81.2.69.193" + ] + }, + "resource": { + "id": "117163099", + "name": "user-noKB.example.net" + }, + "tags": [ + "preserve_original_event", + "preserve_duplicate_custom_fields", + "provider_cloud_data" + ], + "vulnerability": { + "scanner": { + "vendor": "Qualys" + } + } } ] } diff --git a/packages/qualys_vmdr/data_stream/asset_host_detection/elasticsearch/ingest_pipeline/default.yml b/packages/qualys_vmdr/data_stream/asset_host_detection/elasticsearch/ingest_pipeline/default.yml index 319f210e6b8..ed260c6e062 100644 --- a/packages/qualys_vmdr/data_stream/asset_host_detection/elasticsearch/ingest_pipeline/default.yml +++ b/packages/qualys_vmdr/data_stream/asset_host_detection/elasticsearch/ingest_pipeline/default.yml @@ -1672,15 +1672,21 @@ processors: target_field: qualys_vmdr.asset_host_detection.vulnerability.qds_factors.text ignore_missing: true # Handle KNOWLEDGE_BASE - - append: - field: error.message - if: ctx.json?.KNOWLEDGE_BASE == null || ctx.json.KNOWLEDGE_BASE.size() == 0 - value: 'Qualys QID not found in the Knowledge Base' - pipeline: name: '{{ IngestPipeline "pipeline_knowledge_base" }}' if: ctx.json?.KNOWLEDGE_BASE != null && ctx.json.KNOWLEDGE_BASE.size() > 0 tag: pipeline_knowledge_base ignore_missing_pipeline: true + - set: + field: qualys_vmdr.asset_host_detection.knowledge_base.status + tag: set_knowledge_base_status_found + value: found + if: ctx.qualys_vmdr?.asset_host_detection?.knowledge_base != null + - set: + field: qualys_vmdr.asset_host_detection.knowledge_base.status + tag: set_knowledge_base_status_not_found + value: not_found + if: ctx.qualys_vmdr?.asset_host_detection?.knowledge_base == null - set: field: vulnerability.score.base tag: set_vulnerability_score_base_from_knowledge_base_cvss_v3_base @@ -1776,10 +1782,10 @@ processors: - fingerprint: tag: fingerprint_event_original description: > - When deduplication is enabled, fingerprint the event.original value + When deduplication is enabled, fingerprint the event.original value in attempt to prevent the same event from being indexed more than once. if: ctx.event?.original != null && ctx._conf?.enable_deduplication == true - fields: + fields: - event.original target_field: _id - set: diff --git a/packages/qualys_vmdr/data_stream/asset_host_detection/fields/fields.yml b/packages/qualys_vmdr/data_stream/asset_host_detection/fields/fields.yml index 8621c972fcb..a56607efc5b 100644 --- a/packages/qualys_vmdr/data_stream/asset_host_detection/fields/fields.yml +++ b/packages/qualys_vmdr/data_stream/asset_host_detection/fields/fields.yml @@ -537,3 +537,6 @@ type: keyword - name: vuln_type type: keyword + - name: status + type: keyword + description: Indicates whether the QID was found in the Knowledge Base (`found`) or not (`not_found`). diff --git a/packages/qualys_vmdr/docs/README.md b/packages/qualys_vmdr/docs/README.md index 42dd78f0c86..e3da005e7aa 100644 --- a/packages/qualys_vmdr/docs/README.md +++ b/packages/qualys_vmdr/docs/README.md @@ -537,6 +537,7 @@ An example event for `asset_host_detection` looks as following: | qualys_vmdr.asset_host_detection.knowledge_base.software_list.vendor | | keyword | | qualys_vmdr.asset_host_detection.knowledge_base.solution.comment | | match_only_text | | qualys_vmdr.asset_host_detection.knowledge_base.solution.value | | match_only_text | +| qualys_vmdr.asset_host_detection.knowledge_base.status | Indicates whether the QID was found in the Knowledge Base (`found`) or not (`not_found`). | keyword | | qualys_vmdr.asset_host_detection.knowledge_base.supported_modules | | keyword | | qualys_vmdr.asset_host_detection.knowledge_base.threat_intelligence.intel.id | | keyword | | qualys_vmdr.asset_host_detection.knowledge_base.threat_intelligence.intel.text | | keyword | diff --git a/packages/qualys_vmdr/elasticsearch/transform/latest_cdr_vulnerabilities/fields/fields.yml b/packages/qualys_vmdr/elasticsearch/transform/latest_cdr_vulnerabilities/fields/fields.yml index 6f587c07243..2d95eec1729 100644 --- a/packages/qualys_vmdr/elasticsearch/transform/latest_cdr_vulnerabilities/fields/fields.yml +++ b/packages/qualys_vmdr/elasticsearch/transform/latest_cdr_vulnerabilities/fields/fields.yml @@ -521,6 +521,9 @@ type: match_only_text - name: value type: match_only_text + - name: status + type: keyword + description: Indicates whether the QID was found in the Knowledge Base (`found`) or not (`not_found`). - name: supported_modules type: keyword - name: threat_intelligence diff --git a/packages/qualys_vmdr/manifest.yml b/packages/qualys_vmdr/manifest.yml index f7a82f3f8ba..24f84cfc317 100644 --- a/packages/qualys_vmdr/manifest.yml +++ b/packages/qualys_vmdr/manifest.yml @@ -1,7 +1,7 @@ format_version: "3.4.0" name: qualys_vmdr title: Qualys VMDR -version: "6.19.0" +version: "6.19.1" description: Collect data from Qualys VMDR platform with Elastic Agent. type: integration categories: diff --git a/packages/stormshield/_dev/build/docs/README.md b/packages/stormshield/_dev/build/docs/README.md index b7d36d070ed..ad187d0bf90 100644 --- a/packages/stormshield/_dev/build/docs/README.md +++ b/packages/stormshield/_dev/build/docs/README.md @@ -207,6 +207,40 @@ For more information on architectures that can be used for scaling this integrat You'll find events from Stormshield SNS logs in the `log` data stream. This data stream includes logs of the following types: traffic, filter, protection, and system events. +##### ECS event categorization + +Each log family (identified by the `logtype` field) is mapped to the ECS categorization fields. Alarms raised by the intrusion prevention engine produce `event.kind: alert`. The periodic statistics families (`monitor`, `filterstat`, `count`, `routerstat`, `authstat`, `ipsecstat`) produce `event.kind: metric`, so health telemetry can be excluded from detection rule scopes with a single filter. All other families produce `event.kind: event`. + +| logtype | event.kind | event.category | event.type | +|---|---|---|---| +| alarm | alert | intrusion_detection, network | info | +| auth | event | authentication | start | +| authstat | metric | authentication | info | +| connection | event | network, session | connection, end | +| count, filterstat, ipsecstat, routerstat | metric | network | info | +| date | event | host | change | +| dmrouting, routing | event | network, host | change | +| filter | event | network | connection | +| ftp | event | network | info | +| monitor | metric | host | info | +| plugin | event | network | protocol | +| pop3, smtp | event | email, network | info | +| pvm | event | vulnerability | info | +| restapi | event | web, configuration | access | +| sandboxing | event | network | info | +| server | event | configuration | access | +| ssl | event | network | connection | +| system | event | host | info | +| vpn | event | network | info | +| web | event | web, network | access | +| xvpn | event | network, session | connection | + +For the families that carry a rule action, `event.type` additionally receives `allowed` when the action is `pass` and `denied` when the action is `block` (matched case-insensitively). An empty action field corresponds to a rule set to Log, and no modifier is added. Unknown log families fall back to `event.kind: event` without `event.category` or `event.type`, so a family missing from the table is visible instead of being mislabeled. + +For alarm logs, `event.code` carries the Stormshield alarm identifier, `event.risk_score` the `risk` field (1-100), and `event.severity` the vendor alarm level from `pri`, where 1 is a major alarm and 4 a minor alarm. This scale is specific to the alarm family. In most other families, the appliance hardcodes the `pri` field to 5. + +`network.direction` is computed from the source and destination IP addresses, treating private (RFC 1918) address ranges as internal networks. + ##### `log` fields You'll find a list of all exported fields in the following table: diff --git a/packages/stormshield/changelog.yml b/packages/stormshield/changelog.yml index 7cc80809f3f..381c594d6bb 100644 --- a/packages/stormshield/changelog.yml +++ b/packages/stormshield/changelog.yml @@ -1,4 +1,21 @@ # newer versions go on top +- version: "1.6.0" + changes: + - description: Set ECS event categorization fields (`event.kind`, `event.category`, `event.type`) for every log family, including `event.kind` `metric` for the periodic statistics families. + type: enhancement + link: https://github.com/elastic/integrations/pull/20031 + - description: Map `rcvd` to `destination.bytes`, sum `network.bytes`, map interface fields to `observer.ingress` and `observer.egress`, compute `network.direction`, and populate `related.hosts`. + type: enhancement + link: https://github.com/elastic/integrations/pull/20031 + - description: Map alarm identifiers and levels to `event.code`, `event.risk_score` and `event.severity`, and HTTP proxy fields to `url.original` and `url.domain`. + type: enhancement + link: https://github.com/elastic/integrations/pull/20031 + - description: Fix the count sub-pipeline, which failed with a Painless runtime error on every count log, and skip malformed counters instead of failing the whole document. + type: bugfix + link: https://github.com/elastic/integrations/pull/20031 + - description: Add an Alarms dashboard and pipeline test samples for the alarm, auth, web, vpn, xvpn, count and filter log families. + type: enhancement + link: https://github.com/elastic/integrations/pull/20031 - version: "1.5.3" changes: - description: Fix ingest pipeline descriptions and remove field definitions that never appear in events (`stormshield.tz`, `stormshield.duration`, `stormshield.msg`, `stormshield.origdst`, `stormshield.origdstport`). diff --git a/packages/stormshield/data_stream/log/_dev/test/pipeline/test-firewall.log-expected.json b/packages/stormshield/data_stream/log/_dev/test/pipeline/test-firewall.log-expected.json index 3baa9b1deaa..deea33719c5 100644 --- a/packages/stormshield/data_stream/log/_dev/test/pipeline/test-firewall.log-expected.json +++ b/packages/stormshield/data_stream/log/_dev/test/pipeline/test-firewall.log-expected.json @@ -6,9 +6,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "network" + ], + "kind": "metric", "original": "id=firewall time=\"2024-03-08 17:29:51\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 17:29:51\" SavedEvaluation=621 DynamicMem=0 HostMem=0 FragMem=0 ICMPMem=0 ConnMem=0 AssocMem=0 EtherStateMem=0 IPStateMem=0 DTrackMem=0 Logged=11 LogOverflow=0 HostrepMax=0 HostrepScore=0 HostrepRequests=0 PvmFacts=0 PvmOverflow=0 Accepted=105 Blocked=0 Byte(i/o)=10592/14285 Fragmented=0 TCPPacket=0 TCPByte(i/o)=0/0 TCPConn=0 TCPConnNatSrc=0 TCPConnNatDst=0 TCPConnNoNatSrc=0 TCPConnNoNatDst=0 UDPPacket=104 UDPByte(i/o)=10283/14285 UDPConn=0 UDPConnNatSrc=0 UDPConnNatDst=0 UDPConnNoNatSrc=0 UDPConnNoNatDst=0 ICMPPacket=1 ICMPByte(i/o)=309/0 IPStatePacket=0 IPStateByte(i/o)=0/0 IPStateConn=0 IPStateConnNatSrc=0 IPStateConnNatDst=0 IPStateConnNoNatSrc=0 IPStateConnNoNatDst=0 SCTPAssocPacket=0 SCTPAssocByte(i/o)=0/0 SCTPAssoc=0 EtherStatePacket=0 EtherStateByte(i/o)=0/0 EtherStateConn=0 TLSCertCacheEntriesNb=0 TLSCertCacheLookup(miss/total)=0/0 TLSCertCacheInsert=0 TLSCertCacheFlushOp=0 TLSCertCachePurgeOp=0 TLSCertCacheFlushedNb=0 TLSCertCachePurgedNb=0 TLSCertCacheExpiredNb=0 logtype=\"filterstat\"", "start": "2024-03-08T17:29:51.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "observer": { "name": "stormy-1", @@ -121,6 +128,7 @@ "name": "Bredband2 AB" } }, + "bytes": 48, "domain": "ntp2.stormshieldcs.eu", "geo": { "city_name": "Linköping", @@ -146,22 +154,44 @@ }, "event": { "action": "pass", + "category": [ + "network", + "session" + ], "duration": 90000000, + "kind": "event", "original": "id=firewall time=\"2024-03-08 17:29:30\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 12:27:28\" pri=5 confid=01 slotlevel=0 ruleid=7 ipproto=udp dstif=\"Ethernet0\" dstifname=\"out\" proto=ntp src=192.168.197.134 srcport=123 srcportname=ntp srcname=Firewall_out dst=1.128.0.1 dstport=123 dstportname=ntp dstname=ntp2.stormshieldcs.eu dstcontinent=\"eu\" dstcountry=\"fr\" modsrc=192.168.197.134 modsrcport=123 origdst=89.160.20.182 origdstport=123 ipv=4 sent=48 rcvd=48 duration=0.09 action=pass logtype=\"connection\"", "start": "2024-03-08T12:27:28.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "connection", + "end", + "allowed" + ] }, "network": { + "bytes": 96, + "direction": "outbound", "protocol": "ntp", "transport": "udp", "type": "ipv4" }, "observer": { + "egress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "Firewall_out", + "ntp2.stormshieldcs.eu" + ], "ip": [ "192.168.197.134", "89.160.20.182", @@ -207,9 +237,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "authentication" + ], + "kind": "metric", "original": "id=firewall time=\"2024-03-08 17:30:58\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 17:30:58\" auth=0 authtotp=0 authcaptive=0 authwebadmin=0 authsslvpn=0 authipsec=0 authconsole=0 logtype=\"authstat\"", "start": "2024-03-08T17:30:58.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "observer": { "name": "stormy-1", @@ -242,9 +279,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "kind": "metric", "original": "id=firewall time=\"2024-03-08 17:31:09\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 17:31:09\" security=0 system=0 CPU=1,1,1 Pvm=0,0,0,0,0,0,0,0,0,0,0 sslvpn1=sslvpn_udp,0,0,0,0,0,0 sslvpn0=sslvpn,0,0,0,0,0,0 ipsec=ipsec,0,0,0,0,0,0 Ethernet1=in,8,40,8,40,0,0 Ethernet0=out,86,424,177,536,75,0 Qid0=BYPASS_out,0,16032,0,0,82,0 Qid1=BYPASS_in,0,656,0,0,0,0 Qid2=BYPASS_ipsec,0,0,0,0,0,0 mem=0,0,0,0,0,0,0,0 logtype=\"monitor\"", "start": "2024-03-08T17:31:09.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "observer": { "name": "stormy-1", @@ -371,9 +415,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 18:14:59\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 18:14:59\" pri=5 service=userreqd msg=\"reloading daemon configuration (reason: SIGHUP)\" logtype=\"system\"", "start": "2024-03-08T18:14:59.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "reloading daemon configuration (reason: SIGHUP)", "observer": { @@ -402,9 +453,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 18:15:00\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 18:15:00\" pri=5 service=routerd msg=\"routerd daemon configuration reloaded, modules: pbr_route, ip_version: all (reason: Refresh)\" logtype=\"system\"", "start": "2024-03-08T18:15:00.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "routerd daemon configuration reloaded, modules: pbr_route, ip_version: all (reason: Refresh)", "observer": { @@ -430,6 +488,7 @@ { "@timestamp": "2019-02-24T16:38:01.000+01:00", "destination": { + "bytes": 0, "ip": "10.10.10.10", "port": 1900 }, @@ -438,22 +497,41 @@ }, "event": { "action": "pass", + "category": [ + "network" + ], "duration": 0, + "kind": "event", "original": "id=firewall time=\"2019-02-24 16:38:01\" fw=\"SN310A17B0323A7\" tz=+0100 startime=\"2019-02-24 16:38:00\" pri=5 confid=00 slotlevel=2 ruleid=4 rulename=\"1690fb96019_7\" srcif=\"Ethernet0\" srcifname=\"out\" ipproto=udp proto=ssdp src=10.11.11.11 srcport=49907 srcportname=ephemeral_fw_udp srcname=user1 srcmac=11:11:11:11:11:11 dst=10.10.10.10 dstport=1900 dstportname=sdp ipv=4 sent=0 rcvd=0 duration=0.00 action=pass logtype=\"filter\"", "start": "2019-02-24T16:38:00.000+01:00", - "timezone": "+01:00" + "timezone": "+01:00", + "type": [ + "connection", + "allowed" + ] }, "network": { + "bytes": 0, + "direction": "internal", "protocol": "ssdp", "transport": "udp", "type": "ipv4" }, "observer": { + "ingress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, "name": "SN310A17B0323A7", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "user1" + ], "ip": [ "10.11.11.11", "10.10.10.10" @@ -498,9 +576,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"CONFIG LOG SHOW\" logtype=\"server\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "CONFIG LOG SHOW", "observer": { @@ -538,9 +623,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"PKI SEARCH scope=local type=ca\" logtype=\"server\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "PKI SEARCH scope=local type=ca", "observer": { @@ -575,6 +667,7 @@ { "@timestamp": "2024-03-08T10:14:08.000Z", "destination": { + "bytes": 3614, "domain": "Firewall_out", "ip": "192.168.197.134", "port": 443 @@ -584,22 +677,43 @@ }, "event": { "action": "pass", + "category": [ + "network", + "session" + ], "duration": 10000000, + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" pri=5 confid=00 slotlevel=0 ruleid=4 srcif=\"Ethernet0\" srcifname=\"out\" ipproto=tcp proto=ssl version=TLSv1.3 src=192.168.197.1 srcport=61549 srcportname=ad2008-dyn_tcp srcmac=00:50:56:c0:00:08 dst=192.168.197.134 dstport=443 dstportname=https dstname=Firewall_out modsrc=192.168.197.1 modsrcport=61549 origdst=192.168.197.134 origdstport=443 ipv=4 sent=605 rcvd=3614 duration=0.01 action=pass logtype=\"connection\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "connection", + "end", + "allowed" + ] }, "network": { + "bytes": 4219, + "direction": "internal", "protocol": "ssl", "transport": "tcp", "type": "ipv4" }, "observer": { + "ingress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "Firewall_out" + ], "ip": [ "192.168.197.1", "192.168.197.134" @@ -643,9 +757,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"SYSTEM LOGDISK LIST\" logtype=\"server\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "SYSTEM LOGDISK LIST", "observer": { @@ -683,9 +804,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"CONFIG COMMUNICATION SYSLOG PROFILE SHOW index=0\" logtype=\"server\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "CONFIG COMMUNICATION SYSLOG PROFILE SHOW index=0", "observer": { @@ -720,6 +848,7 @@ { "@timestamp": "2024-03-08T10:14:08.000Z", "destination": { + "bytes": 3614, "domain": "Firewall_out", "ip": "192.168.197.134", "port": 443 @@ -729,22 +858,43 @@ }, "event": { "action": "pass", + "category": [ + "network", + "session" + ], "duration": 320000000, + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" pri=5 confid=00 slotlevel=0 ruleid=4 srcif=\"Ethernet0\" srcifname=\"out\" ipproto=tcp proto=ssl version=TLSv1.3 src=192.168.197.1 srcport=61548 srcportname=ad2008-dyn_tcp srcmac=00:50:56:c0:00:08 dst=192.168.197.134 dstport=443 dstportname=https dstname=Firewall_out modsrc=192.168.197.1 modsrcport=61548 origdst=192.168.197.134 origdstport=443 ipv=4 sent=573 rcvd=3614 duration=0.32 action=pass logtype=\"connection\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "connection", + "end", + "allowed" + ] }, "network": { + "bytes": 4187, + "direction": "internal", "protocol": "ssl", "transport": "tcp", "type": "ipv4" }, "observer": { + "ingress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "Firewall_out" + ], "ip": [ "192.168.197.1", "192.168.197.134" @@ -785,6 +935,7 @@ { "@timestamp": "2024-03-08T10:14:08.000Z", "destination": { + "bytes": 3614, "domain": "Firewall_out", "ip": "192.168.197.134", "port": 443 @@ -794,22 +945,43 @@ }, "event": { "action": "pass", + "category": [ + "network", + "session" + ], "duration": 320000000, + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" pri=5 confid=00 slotlevel=0 ruleid=4 srcif=\"Ethernet0\" srcifname=\"out\" ipproto=tcp proto=ssl version=TLSv1.3 src=192.168.197.1 srcport=61550 srcportname=ad2008-dyn_tcp srcmac=00:50:56:c0:00:08 dst=192.168.197.134 dstport=443 dstportname=https dstname=Firewall_out modsrc=192.168.197.1 modsrcport=61550 origdst=192.168.197.134 origdstport=443 ipv=4 sent=605 rcvd=3614 duration=0.32 action=pass logtype=\"connection\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "connection", + "end", + "allowed" + ] }, "network": { + "bytes": 4219, + "direction": "internal", "protocol": "ssl", "transport": "tcp", "type": "ipv4" }, "observer": { + "ingress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "Firewall_out" + ], "ip": [ "192.168.197.1", "192.168.197.134" @@ -850,6 +1022,7 @@ { "@timestamp": "2024-03-08T10:14:09.000Z", "destination": { + "bytes": 300, "ip": "192.168.236.254", "port": 67 }, @@ -858,22 +1031,43 @@ }, "event": { "action": "pass", + "category": [ + "network", + "session" + ], "duration": 0, + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:09\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:12:09\" pri=5 confid=01 slotlevel=0 ruleid=7 ipproto=udp dstif=\"Ethernet1\" dstifname=\"in\" proto=bootps src=192.168.236.131 srcport=68 srcportname=bootpc srcname=Firewall_in dst=192.168.236.254 dstport=67 dstportname=bootps modsrc=192.168.236.131 modsrcport=68 origdst=192.168.236.254 origdstport=67 ipv=4 sent=300 rcvd=300 duration=0.00 action=pass logtype=\"connection\"", "start": "2024-03-08T10:12:09.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "connection", + "end", + "allowed" + ] }, "network": { + "bytes": 600, + "direction": "internal", "protocol": "bootps", "transport": "udp", "type": "ipv4" }, "observer": { + "egress": { + "interface": { + "id": "Ethernet1", + "name": "in" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "Firewall_in" + ], "ip": [ "192.168.236.131", "192.168.236.254" @@ -916,9 +1110,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:11\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:11\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"CONFIG ACTIVATE cancelall\" logtype=\"server\"", "start": "2024-03-08T10:14:11.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "CONFIG ACTIVATE cancelall", "observer": { @@ -956,9 +1157,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:11\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:11\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"SYSTEM IDENT\" logtype=\"server\"", "start": "2024-03-08T10:14:11.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "SYSTEM IDENT", "observer": { @@ -996,9 +1204,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:11\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:11\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"SYSTEM LANGUAGE\" logtype=\"server\"", "start": "2024-03-08T10:14:11.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "SYSTEM LANGUAGE", "observer": { @@ -1036,9 +1251,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:48\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 15:14:48\" pri=5 service=routerd msg=\"The gateway of the router is now used for routing router:Firewall_out_router gateway:Firewall_out_router ipv:4 (192.168.197.2)\" logtype=\"system\"", "start": "2024-03-08T15:14:48.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "The gateway of the router is now used for routing router:Firewall_out_router gateway:Firewall_out_router ipv:4 (192.168.197.2)", "observer": { @@ -1067,9 +1289,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:48\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 15:14:48\" pri=5 service=routerd msg=\"routerd daemon configuration reloaded, modules: pbr_route, ip_version: all (reason: Refresh)\" logtype=\"system\"", "start": "2024-03-08T15:14:48.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "routerd daemon configuration reloaded, modules: pbr_route, ip_version: all (reason: Refresh)", "observer": { @@ -1098,9 +1327,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:48\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 15:14:48\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"CONFIG DNS ACTIVATE\" logtype=\"server\"", "start": "2024-03-08T15:14:48.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "CONFIG DNS ACTIVATE", "observer": { @@ -1141,11 +1377,22 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "code": "82", + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:49\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 15:14:48\" pri=5 src=192.168.197.2 dst=0.0.0.0 msg=\"Remote host reachable: through Firewall_out_router(192.168.197.2) on router Firewall_out_router\" service=sysevent alarmid=82 logtype=\"system\"", "start": "2024-03-08T15:14:48.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "Remote host reachable: through Firewall_out_router(192.168.197.2) on router Firewall_out_router", + "network": { + "direction": "outbound" + }, "observer": { "name": "stormy-1", "type": "firewall", @@ -1182,9 +1429,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "network" + ], + "kind": "metric", "original": "id=firewall time=\"2024-03-08 15:14:51\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 15:14:51\" SavedEvaluation=153 DynamicMem=0 HostMem=0 FragMem=0 ICMPMem=0 ConnMem=0 AssocMem=0 EtherStateMem=0 IPStateMem=0 DTrackMem=0 Logged=10 LogOverflow=0 HostrepMax=0 HostrepScore=0 HostrepRequests=0 PvmFacts=0 PvmOverflow=0 Accepted=289 Blocked=0 Byte(i/o)=97364/145065 Fragmented=0 TCPPacket=178 TCPByte(i/o)=86297/116839 TCPConn=3 TCPConnNatSrc=0 TCPConnNatDst=0 TCPConnNoNatSrc=0 TCPConnNoNatDst=0 UDPPacket=111 UDPByte(i/o)=11067/28226 UDPConn=0 UDPConnNatSrc=0 UDPConnNatDst=0 UDPConnNoNatSrc=0 UDPConnNoNatDst=0 ICMPPacket=0 ICMPByte(i/o)=0/0 IPStatePacket=0 IPStateByte(i/o)=0/0 IPStateConn=0 IPStateConnNatSrc=0 IPStateConnNatDst=0 IPStateConnNoNatSrc=0 IPStateConnNoNatDst=0 SCTPAssocPacket=0 SCTPAssocByte(i/o)=0/0 SCTPAssoc=0 EtherStatePacket=0 EtherStateByte(i/o)=0/0 EtherStateConn=0 TLSCertCacheEntriesNb=0 TLSCertCacheLookup(miss/total)=0/0 TLSCertCacheInsert=0 TLSCertCacheFlushOp=0 TLSCertCachePurgeOp=0 TLSCertCacheFlushedNb=0 TLSCertCachePurgedNb=0 TLSCertCacheExpiredNb=0 logtype=\"filterstat\"", "start": "2024-03-08T15:14:51.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "observer": { "name": "stormy-1", @@ -1294,9 +1548,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:54\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 15:14:54\" pri=5 service=userreqd msg=\"reloading daemon configuration (reason: SIGHUP)\" logtype=\"system\"", "start": "2024-03-08T15:14:54.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "reloading daemon configuration (reason: SIGHUP)", "observer": { @@ -1325,9 +1586,17 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "code": "41", + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:55\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:54\" pri=5 msg=\"Active Update: update successful IPData\" service=sysevent alarmid=41 logtype=\"system\"", "start": "2024-03-08T10:14:54.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "Active Update: update successful IPData", "observer": { @@ -1357,9 +1626,16 @@ "version": "8.17.0" }, "event": { + "category": [ + "configuration" + ], + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:56\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 15:14:56\" error=1 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"QUIT\" logtype=\"server\"", "start": "2024-03-08T15:14:56.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "message": "QUIT", "observer": { @@ -1397,9 +1673,19 @@ "version": "8.17.0" }, "event": { + "category": [ + "intrusion_detection", + "network" + ], + "code": "3", + "kind": "alert", "original": "id=firewall time=\"2024-03-08 15:14:57\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:56\" pri=4 msg=\"Connection terminated for webadmin (timeout)\" class=system alarmid=3 logtype=\"alarm\"", + "severity": 4, "start": "2024-03-08T10:14:56.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "Connection terminated for webadmin (timeout)", "observer": { @@ -1426,6 +1712,7 @@ { "@timestamp": "2024-03-08T15:14:57.000Z", "destination": { + "bytes": 921861, "domain": "update2-sns.stormshieldcs.eu", "geo": { "country_iso_code": "fr" @@ -1438,22 +1725,44 @@ }, "event": { "action": "pass", + "category": [ + "network", + "session" + ], "duration": 2147483647, + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:57\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:51\" pri=5 confid=01 slotlevel=0 ruleid=7 ipproto=tcp dstif=\"Ethernet0\" dstifname=\"out\" proto=https src=192.168.197.134 srcport=19883 srcname=Firewall_out dst=192.168.36.20 dstport=443 dstportname=https dstname=update2-sns.stormshieldcs.eu dstcontinent=\"eu\" dstcountry=\"fr\" modsrc=192.168.197.134 modsrcport=19883 origdst=192.168.36.20 origdstport=443 ipv=4 sent=3721 rcvd=921861 duration=5.52 action=pass logtype=\"connection\"", "start": "2024-03-08T10:14:51.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "connection", + "end", + "allowed" + ] }, "network": { + "bytes": 925582, + "direction": "internal", "protocol": "https", "transport": "tcp", "type": "ipv4" }, "observer": { + "egress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "Firewall_out", + "update2-sns.stormshieldcs.eu" + ], "ip": [ "192.168.197.134", "192.168.36.20" @@ -1493,6 +1802,7 @@ { "@timestamp": "2024-03-08T15:14:57.000Z", "destination": { + "bytes": 4863757, "domain": "update1-sns.stormshieldcs.eu", "geo": { "country_iso_code": "fr" @@ -1505,22 +1815,44 @@ }, "event": { "action": "pass", + "category": [ + "network", + "session" + ], "duration": 2147483647, + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:57\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:54\" pri=5 confid=01 slotlevel=0 ruleid=7 ipproto=tcp dstif=\"Ethernet0\" dstifname=\"out\" proto=https src=192.168.197.134 srcport=15908 srcname=Firewall_out dst=192.168.36.4 dstport=443 dstportname=https dstname=update1-sns.stormshieldcs.eu dstcontinent=\"eu\" dstcountry=\"fr\" modsrc=192.168.197.134 modsrcport=15908 origdst=192.168.36.4 origdstport=443 ipv=4 sent=1467 rcvd=4863757 duration=2.98 action=pass logtype=\"connection\"", "start": "2024-03-08T10:14:54.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "connection", + "end", + "allowed" + ] }, "network": { + "bytes": 4865224, + "direction": "internal", "protocol": "https", "transport": "tcp", "type": "ipv4" }, "observer": { + "egress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "Firewall_out", + "update1-sns.stormshieldcs.eu" + ], "ip": [ "192.168.197.134", "192.168.36.4" @@ -1563,9 +1895,17 @@ "version": "8.17.0" }, "event": { + "category": [ + "host" + ], + "code": "41", + "kind": "event", "original": "id=firewall time=\"2024-03-08 15:14:58\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:56\" pri=5 msg=\"Active Update: update successful CompromisedUrls\" service=sysevent logtype=\"system\" alarmid=41", "start": "2024-03-08T10:14:56.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "info" + ] }, "message": "Active Update: update successful CompromisedUrls", "observer": { @@ -1598,6 +1938,7 @@ "name": "Telstra Pty Ltd" } }, + "bytes": 177, "domain": "connectivity-check.ubuntu.com", "geo": { "country_iso_code": "us" @@ -1610,22 +1951,48 @@ }, "event": { "action": "pass", + "category": [ + "network" + ], "duration": 60000000, + "kind": "event", "original": "id=firewall time=\"2024-06-07 18:46:18\" fw=\"stormy-1\" tz=+0000 startime=\"2024-06-07 10:40:42\" pri=5 confid=01 slotlevel=2 ruleid=7 srcif=\"Ethernet1\" srcifname=\"segment0\" ipproto=tcp dstif=\"Ethernet0\" dstifname=\"out\" proto=http src=89.160.20.128 srcport=55008 srcportname=ephemeral_fw_tcp srcname=vm-internal srcmac=00:0c:29:8d:6c:55 srccontinent=\"eu\" srccountry=\"se\" dst=1.128.91.48 dstport=80 dstportname=http dstname=connectivity-check.ubuntu.com dstcontinent=\"na\" dstcountry=\"us\" modsrc=192.168.197.134 modsrcport=55008 origdst=1.128.91.48 origdstport=80 ipv=4 sent=77 rcvd=177 duration=0.06 action=pass op=GET result=204 arg=\"/\" logtype=\"plugin\"", "start": "2024-06-07T10:40:42.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "protocol", + "allowed" + ] }, "network": { + "bytes": 254, + "direction": "external", "protocol": "http", "transport": "tcp", "type": "ipv4" }, "observer": { + "egress": { + "interface": { + "id": "Ethernet0", + "name": "out" + } + }, + "ingress": { + "interface": { + "id": "Ethernet1", + "name": "segment0" + } + }, "name": "stormy-1", "type": "firewall", "vendor": "Stormshield" }, "related": { + "hosts": [ + "vm-internal", + "connectivity-check.ubuntu.com" + ], "ip": [ "89.160.20.128", "192.168.197.134", diff --git a/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/count.yml b/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/count.yml index 90c5f22565d..277e8f61f72 100644 --- a/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/count.yml +++ b/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/count.yml @@ -4,7 +4,7 @@ processors: - script: tag: script_process_devices lang: painless - description: Process device stat fields. + description: Process device stat fields, skipping counters that do not parse. params: devices: - Rule @@ -16,35 +16,53 @@ processors: - Global NAT Rule - Local NAT Rule source: >- - def ruleStats = [:]; + boolean isNumeric(def s) { + if (!(s instanceof String) || s.isEmpty() || s.length() > 18) { + return false; + } + for (int i = 0; i < s.length(); i++) { + if (Character.isDigit(s.charAt(i)) == false) { + return false; + } + } + return true; + } + def ruleStats = []; + def ruleKeys = []; def str = "Rule"; ctx.stormshield.forEach((k, v) -> { - if (k.startsWith(str)) { - def joined = k.substring(str.length()); - def parts = joined.splitByToken(":", 2); - ruleStats["original"] = k; - ruleStats["byte_count"] = v; - ruleStats["category"] = params.stats[Long.parseLong(parts[0])]; - ruleStats["rule_number"] = Long.parseLong(parts[1]); + if (k.startsWith(str) && k.indexOf(":") > str.length()) { + ruleKeys.add(k); + def parts = k.substring(str.length()).splitOnToken(":"); + if (parts.length == 2 && isNumeric(v) && isNumeric(parts[1]) && parts[0].length() == 1 && isNumeric(parts[0])) { + int category = Integer.parseInt(parts[0]); + if (category < params.stats.size()) { + def item = [:]; + item["original"] = k; + item["byte_count"] = Long.parseLong(v); + item["category"] = params.stats[category]; + item["rule_number"] = Long.parseLong(parts[1]); + ruleStats.add(item); + } + } } - + return true; }); + for (k in ruleKeys) { + ctx.stormshield.remove(k); + } + if (ruleStats.isEmpty()) { return; } - for (entry in ruleStats.entrySet()) { - ruleStats[entry.getKey()].sort((a, b) -> a["original"].compareTo(b["original"])); - } + ruleStats.sort((a, b) -> a["original"].compareTo(b["original"])); if (!ctx.stormshield.containsKey("metadata")) { ctx.stormshield.metadata = [:]; } ctx.stormshield.metadata.rule_stats = ruleStats; - for (entry in ruleStats.entrySet()) { - ctx.stormshield.remove(entry.getValue()["original"]); - } on_failure: - append: field: error.message diff --git a/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/default.yml b/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/default.yml index b3dddc52f73..8960336661e 100644 --- a/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/default.yml +++ b/packages/stormshield/data_stream/log/elasticsearch/ingest_pipeline/default.yml @@ -139,6 +139,27 @@ processors: copy_from: stormshield.id if: ctx.stormshield?.id != null + - set: + tag: set_observer_ingress_interface_id + field: observer.ingress.interface.id + copy_from: stormshield.srcif + ignore_empty_value: true + - set: + tag: set_observer_ingress_interface_name + field: observer.ingress.interface.name + copy_from: stormshield.srcifname + ignore_empty_value: true + - set: + tag: set_observer_egress_interface_id + field: observer.egress.interface.id + copy_from: stormshield.dstif + ignore_empty_value: true + - set: + tag: set_observer_egress_interface_name + field: observer.egress.interface.name + copy_from: stormshield.dstifname + ignore_empty_value: true + - convert: tag: convert_stormshield_modsrc_to_source_nat_ip_cf7c07ec field: stormshield.modsrc @@ -222,7 +243,7 @@ processors: properties: - asn - organization_name - ignore_missing: true + if: ctx.destination?.ip != null - rename: tag: rename_destination_as_asn_to_destination_as_number_3b459fcd field: destination.as.asn @@ -246,7 +267,7 @@ processors: properties: - asn - organization_name - ignore_missing: true + if: ctx.source?.ip != null - rename: tag: rename_source_as_asn_to_source_as_number_a917047d field: source.as.asn @@ -295,6 +316,25 @@ processors: type: long ignore_missing: true + - convert: + tag: convert_stormshield_rcvd_to_destination_bytes + field: stormshield.rcvd + target_field: destination.bytes + type: long + ignore_missing: true + + - script: + tag: script_sum_network_bytes + lang: painless + description: Sum source and destination bytes into network.bytes. + if: ctx.source?.bytes != null && ctx.destination?.bytes != null + ignore_failure: true + source: >- + if (ctx.network == null) { + ctx.network = [:]; + } + ctx.network.bytes = ctx.source.bytes + ctx.destination.bytes; + - rename: tag: rename_stormshield_dstname_to_destination_domain_675a68da field: stormshield.dstname @@ -446,6 +486,54 @@ processors: } + # Promote fields raised by the intrusion prevention engine before they are + # moved under stormshield.metadata. + - set: + tag: set_event_code_from_alarmid + field: event.code + copy_from: stormshield.alarmid + ignore_empty_value: true + - convert: + tag: convert_stormshield_risk_to_event_risk_score + field: stormshield.risk + target_field: event.risk_score + type: float + ignore_missing: true + on_failure: + - remove: + tag: remove_event_risk_score + field: event.risk_score + ignore_missing: true + # The pri field of alarm logs carries the alarm level (1 = major, 4 = minor), + # unlike other log families where it is a syslog-like severity hardcoded to 5. + - convert: + tag: convert_alarm_pri_to_event_severity + field: stormshield.pri + target_field: event.severity + type: long + if: ctx.stormshield?.logtype == 'alarm' && ctx.stormshield.pri != null + ignore_failure: true + + # Promote HTTP proxy fields. + - set: + tag: set_url_original_from_arg + field: url.original + copy_from: stormshield.arg + ignore_empty_value: true + if: ctx.stormshield?.logtype == 'web' && ctx.stormshield.arg != null + - set: + tag: set_url_domain_from_destination_domain + field: url.domain + copy_from: destination.domain + if: ctx.stormshield?.logtype == 'web' && ctx.destination?.domain != null + + - append: + tag: append_related_hosts_srcname + field: related.hosts + value: "{{{stormshield.srcname}}}" + if: ctx.stormshield?.srcname != null && ctx.stormshield.srcname != '' + allow_duplicates: false + - script: tag: script_move_things lang: painless @@ -463,30 +551,65 @@ processors: - authsslvpn - authtotp - authwebadmin + - cat_site - class + - classification + - clientappid - confid + - contentpolicy + - cookie_i + - cookie_r + - datechange + - domain - dstcontinent - dstcountry - dstportname - error + - filename + - filetype + - groupid + - icmpcode + - icmptype - id + - ikev + - localnet - mem + - method - modsrc - modsrcport - op + - phase - pri - rcvd + - remoteid + - remotenet + - repeat - result + - risk + - ruletype + - sandboxing + - sandboxinglevel - security + - sensible - sent + - serverappid - sessionid + - side - slotlevel - slotname + - spamlevel + - spi_in + - spi_out - srccontinent - srccountry - srcname - srcportname + - target + - totp + - urlruleid + - usergroup - version + - virus source: >- if (!ctx.stormshield.containsKey("metadata")) { ctx.stormshield.metadata = [:]; @@ -512,6 +635,87 @@ processors: type: long ignore_missing: true + # ------------------------------------------------------------ + # ECS categorization + - remove: + tag: remove_empty_event_action + description: An empty action field means the traffic matched a rule set to Log. + field: event.action + if: ctx.event?.action != null && ctx.event.action == '' + + - network_direction: + tag: network_direction + internal_networks: + - private + if: ctx.source?.ip != null && ctx.destination?.ip != null + ignore_failure: true + + - script: + tag: script_ecs_categorization + lang: painless + description: Set the ECS categorization fields from the log family and the rule action. + if: ctx.error == null + params: + logtypes: + alarm: { kind: alert, category: [intrusion_detection, network], type: [info] } + auth: { kind: event, category: [authentication], type: [start] } + authstat: { kind: metric, category: [authentication], type: [info] } + connection: { kind: event, category: [network, session], type: [connection, end] } + count: { kind: metric, category: [network], type: [info] } + date: { kind: event, category: [host], type: [change] } + dmrouting: { kind: event, category: [network, host], type: [change] } + filter: { kind: event, category: [network], type: [connection] } + filterstat: { kind: metric, category: [network], type: [info] } + ftp: { kind: event, category: [network], type: [info] } + ipsecstat: { kind: metric, category: [network], type: [info] } + monitor: { kind: metric, category: [host], type: [info] } + plugin: { kind: event, category: [network], type: [protocol] } + pop3: { kind: event, category: [email, network], type: [info] } + pvm: { kind: event, category: [vulnerability], type: [info] } + restapi: { kind: event, category: [web, configuration], type: [access] } + routerstat: { kind: metric, category: [network], type: [info] } + routing: { kind: event, category: [network, host], type: [change] } + sandboxing: { kind: event, category: [network], type: [info] } + server: { kind: event, category: [configuration], type: [access] } + smtp: { kind: event, category: [email, network], type: [info] } + ssl: { kind: event, category: [network], type: [connection] } + system: { kind: event, category: [host], type: [info] } + vpn: { kind: event, category: [network], type: [info] } + web: { kind: event, category: [web, network], type: [access] } + xvpn: { kind: event, category: [network, session], type: [connection] } + action_types: + pass: allowed + block: denied + action_logtypes: + - alarm + - connection + - filter + - ftp + - plugin + - pop3 + - smtp + - ssl + - web + source: >- + def logtype = ctx.stormshield?.logtype; + def entry = params.logtypes[logtype]; + if (ctx.event == null) { + ctx.event = [:]; + } + if (entry == null) { + ctx.event.kind = 'event'; + } else { + ctx.event.kind = entry.kind; + ctx.event.category = new ArrayList(entry.category); + ctx.event.type = new ArrayList(entry.type); + if (params.action_logtypes.contains(logtype) && ctx.event.action instanceof String) { + def mapped = params.action_types[ctx.event.action.toLowerCase()]; + if (mapped != null && !ctx.event.type.contains(mapped)) { + ctx.event.type.add(mapped); + } + } + } + # ------------------------------------------------------------ # Add the 'related' fields - append: @@ -549,6 +753,13 @@ processors: if: ctx.user?.name != null allow_duplicates: false + - append: + tag: append_related_hosts_destination_domain + field: related.hosts + value: "{{{destination.domain}}}" + if: ctx.destination?.domain != null + allow_duplicates: false + # ------------------------------------------------------------ # Cleanup - remove: diff --git a/packages/stormshield/data_stream/log/fields/ecs.yml b/packages/stormshield/data_stream/log/fields/ecs.yml index f979a751479..69fe5a28969 100644 --- a/packages/stormshield/data_stream/log/fields/ecs.yml +++ b/packages/stormshield/data_stream/log/fields/ecs.yml @@ -104,11 +104,45 @@ name: rule.name - external: ecs name: source.bytes +- external: ecs + name: destination.bytes +- external: ecs + name: network.bytes +- external: ecs + name: network.direction +- external: ecs + name: observer.ingress.interface.id +- external: ecs + name: observer.ingress.interface.name +- external: ecs + name: observer.egress.interface.id +- external: ecs + name: observer.egress.interface.name +- external: ecs + name: event.action - external: ecs name: event.duration +- external: ecs + name: event.kind +- external: ecs + name: event.category +- external: ecs + name: event.type +- external: ecs + name: event.code +- external: ecs + name: event.risk_score +- external: ecs + name: event.severity +- external: ecs + name: url.original +- external: ecs + name: url.domain - external: ecs name: related.ip - external: ecs name: related.user +- external: ecs + name: related.hosts - external: ecs name: user.name diff --git a/packages/stormshield/data_stream/log/sample_event.json b/packages/stormshield/data_stream/log/sample_event.json index f368f0770ea..d0f9951be78 100644 --- a/packages/stormshield/data_stream/log/sample_event.json +++ b/packages/stormshield/data_stream/log/sample_event.json @@ -1,39 +1,46 @@ { "@timestamp": "2024-03-08T10:14:08.000Z", "agent": { - "ephemeral_id": "fbc0ca2c-7300-45ce-84b1-6ece2bc46905", - "id": "e0b60804-99ad-435e-865c-35384901d186", - "name": "elastic-agent-45518", + "ephemeral_id": "19c5155e-5f61-4dc1-b23c-cd84e946b455", + "id": "63ff8a64-ec88-4856-ba1c-8653054b4358", + "name": "elastic-agent-17632", "type": "filebeat", - "version": "8.14.1" + "version": "9.4.3" }, "data_stream": { "dataset": "stormshield.log", - "namespace": "65295", + "namespace": "52256", "type": "logs" }, "ecs": { "version": "8.17.0" }, "elastic_agent": { - "id": "e0b60804-99ad-435e-865c-35384901d186", + "id": "63ff8a64-ec88-4856-ba1c-8653054b4358", "snapshot": false, - "version": "8.14.1" + "version": "9.4.3" }, "event": { "agent_id_status": "verified", + "category": [ + "configuration" + ], "dataset": "stormshield.log", - "ingested": "2024-09-18T14:01:36Z", + "ingested": "2026-07-08T10:05:22Z", + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"PKI SEARCH scope=local type=ca\" logtype=\"server\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "input": { "type": "tcp" }, "log": { "source": { - "address": "172.27.0.3:40024" + "address": "172.21.0.3:49430" }, "syslog": { "appname": "serverd", @@ -80,4 +87,4 @@ "user": { "name": "admin" } -} \ No newline at end of file +} diff --git a/packages/stormshield/docs/README.md b/packages/stormshield/docs/README.md index f56d3892238..7d09fbb057a 100644 --- a/packages/stormshield/docs/README.md +++ b/packages/stormshield/docs/README.md @@ -270,6 +270,40 @@ To collect logs via UDP, select **Collect logs via UDP** and configure the follo You'll find events from Stormshield SNS logs in the `log` data stream. This data stream includes logs of the following types: traffic, filter, protection, and system events. +##### ECS event categorization + +Each log family (identified by the `logtype` field) is mapped to the ECS categorization fields. Alarms raised by the intrusion prevention engine produce `event.kind: alert`. The periodic statistics families (`monitor`, `filterstat`, `count`, `routerstat`, `authstat`, `ipsecstat`) produce `event.kind: metric`, so health telemetry can be excluded from detection rule scopes with a single filter. All other families produce `event.kind: event`. + +| logtype | event.kind | event.category | event.type | +|---|---|---|---| +| alarm | alert | intrusion_detection, network | info | +| auth | event | authentication | start | +| authstat | metric | authentication | info | +| connection | event | network, session | connection, end | +| count, filterstat, ipsecstat, routerstat | metric | network | info | +| date | event | host | change | +| dmrouting, routing | event | network, host | change | +| filter | event | network | connection | +| ftp | event | network | info | +| monitor | metric | host | info | +| plugin | event | network | protocol | +| pop3, smtp | event | email, network | info | +| pvm | event | vulnerability | info | +| restapi | event | web, configuration | access | +| sandboxing | event | network | info | +| server | event | configuration | access | +| ssl | event | network | connection | +| system | event | host | info | +| vpn | event | network | info | +| web | event | web, network | access | +| xvpn | event | network, session | connection | + +For the families that carry a rule action, `event.type` additionally receives `allowed` when the action is `pass` and `denied` when the action is `block` (matched case-insensitively). An empty action field corresponds to a rule set to Log, and no modifier is added. Unknown log families fall back to `event.kind: event` without `event.category` or `event.type`, so a family missing from the table is visible instead of being mislabeled. + +For alarm logs, `event.code` carries the Stormshield alarm identifier, `event.risk_score` the `risk` field (1-100), and `event.severity` the vendor alarm level from `pri`, where 1 is a major alarm and 4 a minor alarm. This scale is specific to the alarm family. In most other families, the appliance hardcodes the `pri` field to 5. + +`network.direction` is computed from the source and destination IP addresses, treating private (RFC 1918) address ranges as internal networks. + ##### `log` fields You'll find a list of all exported fields in the following table: @@ -285,6 +319,7 @@ You'll find a list of all exported fields in the following table: | destination.as.number | Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. | long | | destination.as.organization.name | Organization name. | keyword | | destination.as.organization.name.text | Multi-field of `destination.as.organization.name`. | match_only_text | +| destination.bytes | Bytes sent from the destination to the source. | long | | destination.domain | The domain name of the destination system. This value may be a host name, a fully qualified domain name, or another host naming format. The value may derive from the original event or be added from enrichment. | keyword | | destination.geo.city_name | City name. | keyword | | destination.geo.continent_name | Name of the continent. | keyword | @@ -300,7 +335,14 @@ You'll find a list of all exported fields in the following table: | destination.nat.port | Port the source session is translated to by NAT Device. Typically used with load balancers, firewalls, or routers. | long | | destination.port | Port of the destination. | long | | ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| event.action | The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. | keyword | +| event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword | +| event.code | Identification code for this event, if one exists. Some event sources use event codes to identify messages unambiguously, regardless of message language or wording adjustments over time. An example of this is the Windows Event ID. | keyword | | event.duration | Duration of the event in nanoseconds. If `event.start` and `event.end` are known this value should be the difference between the end and start time. | long | +| event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword | +| event.risk_score | Risk score or priority of the event (e.g. security solutions). Use your system's original value here. | float | +| event.severity | The numeric severity of the event according to your event source. What the different severity values mean can be different between sources and use cases. It's up to the implementer to make sure severities are consistent across events from the same source. The Syslog severity belongs in `log.syslog.severity.code`. `event.severity` is meant to represent the severity according to the event source (e.g. firewall, IDS). If the event source does not publish its own severity, you may optionally copy the `log.syslog.severity.code` to `event.severity`. | long | +| event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword | | input.type | Type of input. | keyword | | log.source.address | Source address for the log. | keyword | | log.syslog.appname | The device or application that originated the Syslog message, if available. | keyword | @@ -312,15 +354,22 @@ You'll find a list of all exported fields in the following table: | log.syslog.severity.name | The Syslog numeric severity of the log event, if available. If the event source publishing via Syslog provides a different severity value (e.g. firewall, IDS), your source's text severity should go to `log.level`. If the event source does not specify a distinct severity, you can optionally copy the Syslog severity to `log.level`. | keyword | | log.syslog.version | The version of the Syslog protocol specification. Only applicable for RFC 5424 messages. | keyword | | message | For log events the message field contains the log message, optimized for viewing in a log viewer. For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. If multiple messages exist, they can be combined into one message. | match_only_text | +| network.bytes | Total bytes transferred in both directions. If `source.bytes` and `destination.bytes` are known, `network.bytes` is their sum. | long | +| network.direction | Direction of the network traffic. When mapping events from a host-based monitoring context, populate this field from the host's point of view, using the values "ingress" or "egress". When mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of the network perimeter, using the values "inbound", "outbound", "internal" or "external". Note that "internal" is not crossing perimeter boundaries, and is meant to describe communication between two hosts within the perimeter. Note also that "external" is meant to describe traffic between two hosts that are external to the perimeter. This could for example be useful for ISPs or VPN service providers. | keyword | | network.protocol | In the OSI Model this would be the Application Layer protocol. For example, `http`, `dns`, or `ssh`. The field value must be normalized to lowercase for querying. | keyword | | network.transport | Same as network.iana_number, but instead using the Keyword name of the transport layer (udp, tcp, ipv6-icmp, etc.) The field value must be normalized to lowercase for querying. | keyword | | network.type | In the OSI Model this would be the Network Layer. ipv4, ipv6, ipsec, pim, etc The field value must be normalized to lowercase for querying. | keyword | +| observer.egress.interface.id | Interface ID as reported by an observer (typically SNMP interface ID). | keyword | +| observer.egress.interface.name | Interface name as reported by the system. | keyword | +| observer.ingress.interface.id | Interface ID as reported by an observer (typically SNMP interface ID). | keyword | +| observer.ingress.interface.name | Interface name as reported by the system. | keyword | | observer.name | Custom name of the observer. This is a name that can be given to an observer. This can be helpful for example if multiple firewalls of the same model are used in an organization. If no custom name is needed, the field can be left empty. | keyword | | observer.product | The product name of the observer. | keyword | | observer.type | The type of the observer the data is coming from. There is no predefined list of observer types. Some examples are `forwarder`, `firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`. | keyword | | observer.vendor | Vendor name of the observer. | keyword | | process.name | Process name. Sometimes called program name or similar. | keyword | | process.name.text | Multi-field of `process.name`. | match_only_text | +| related.hosts | All hostnames or other host identifiers seen on your event. Example identifiers include FQDNs, domain names, workstation names, or aliases. | keyword | | related.ip | All of the IPs seen on your event. | ip | | related.user | All the user names or other user identifiers seen on the event. | keyword | | rule.id | A rule ID that is unique within the scope of an agent, observer, or other entity using the rule for detection of this event. | keyword | @@ -357,6 +406,9 @@ You'll find a list of all exported fields in the following table: | stormshield.system | Indicator of the Firewalls system status. This value is used by the fleet management tool (Stormshield Network Unified Manager) to provide information on the system status (available RAM, CPU use, bandwidth, interfaces, fullness of audit logs, and so on). Decimal format representing a percentage. | keyword | | stormshield.time | Local time at which the log was recorded in the log file (time configured on the Firewall). String in YYYY-MM-DD HH:MM:SS format. Available from: SNS v1.0.0. | keyword | | tags | List of keywords used to tag each event. | keyword | +| url.domain | Domain of the url, such as "www.elastic.co". In some cases a URL may refer to an IP and/or port directly, without a domain name. In this case, the IP address would go to the `domain` field. If the URL contains a literal IPv6 address enclosed by `[` and `]` (IETF RFC 2732), the `[` and `]` characters should also be captured in the `domain` field. | keyword | +| url.original | Unmodified original url as seen in the event source. Note that in network monitoring, the observed URL may be a full URL, whereas in access logs, the URL is often just represented as a path. This field is meant to represent the URL as it was observed, complete or not. | wildcard | +| url.original.text | Multi-field of `url.original`. | match_only_text | | user.name | Short name or login of the user. | keyword | | user.name.text | Multi-field of `user.name`. | match_only_text | @@ -371,39 +423,46 @@ An example event for `log` looks as following: { "@timestamp": "2024-03-08T10:14:08.000Z", "agent": { - "ephemeral_id": "fbc0ca2c-7300-45ce-84b1-6ece2bc46905", - "id": "e0b60804-99ad-435e-865c-35384901d186", - "name": "elastic-agent-45518", + "ephemeral_id": "19c5155e-5f61-4dc1-b23c-cd84e946b455", + "id": "63ff8a64-ec88-4856-ba1c-8653054b4358", + "name": "elastic-agent-17632", "type": "filebeat", - "version": "8.14.1" + "version": "9.4.3" }, "data_stream": { "dataset": "stormshield.log", - "namespace": "65295", + "namespace": "52256", "type": "logs" }, "ecs": { "version": "8.17.0" }, "elastic_agent": { - "id": "e0b60804-99ad-435e-865c-35384901d186", + "id": "63ff8a64-ec88-4856-ba1c-8653054b4358", "snapshot": false, - "version": "8.14.1" + "version": "9.4.3" }, "event": { "agent_id_status": "verified", + "category": [ + "configuration" + ], "dataset": "stormshield.log", - "ingested": "2024-09-18T14:01:36Z", + "ingested": "2026-07-08T10:05:22Z", + "kind": "event", "original": "id=firewall time=\"2024-03-08 10:14:08\" fw=\"stormy-1\" tz=+0000 startime=\"2024-03-08 10:14:08\" error=0 user=\"admin\" address=192.168.197.1 sessionid=1 msg=\"PKI SEARCH scope=local type=ca\" logtype=\"server\"", "start": "2024-03-08T10:14:08.000Z", - "timezone": "+00:00" + "timezone": "+00:00", + "type": [ + "access" + ] }, "input": { "type": "tcp" }, "log": { "source": { - "address": "172.27.0.3:40024" + "address": "172.21.0.3:49430" }, "syslog": { "appname": "serverd", diff --git a/packages/stormshield/manifest.yml b/packages/stormshield/manifest.yml index 126f4aeff80..ec04fa73705 100644 --- a/packages/stormshield/manifest.yml +++ b/packages/stormshield/manifest.yml @@ -1,7 +1,7 @@ format_version: 3.1.1 name: stormshield title: "StormShield SNS" -version: "1.5.3" +version: "1.6.0" source: license: "Elastic-2.0" description: "Stormshield SNS integration." diff --git a/packages/ti_anomali/_dev/deploy/docker/files/intelligence-api-config.yml b/packages/ti_anomali/_dev/deploy/docker/files/intelligence-api-config.yml index 81ba1944bf1..dd0f4b083e4 100644 --- a/packages/ti_anomali/_dev/deploy/docker/files/intelligence-api-config.yml +++ b/packages/ti_anomali/_dev/deploy/docker/files/intelligence-api-config.yml @@ -1,4 +1,60 @@ rules: + # Rules for advanced query (q parameter) with search_after pagination. + # These use search_after in the next URL rather than update_id__gt, + # matching how the real Anomali API behaves with advanced queries. + - path: /api/v2/intelligence/ + methods: ["GET"] + request_headers: + Authorization: "apikey test_username:test_api_key" + query_params: + search_after: "{search_after:.*}" + limit: "3" + q: "test_query" + responses: + - status_code: 200 + body: |- + { + "objects": [ + {"update_id":200000004,"target_industry":[],"source":"Analyst","threatscore":0,"threat_type":"apt","trusted_circle_ids":null,"description":null,"workgroups":[],"sort":[467408247],"resource_uri":"/api/v2/intelligence/235548934/","modified_ts":"2021-04-29T16:01:13.662Z","source_reported_confidence":-1,"type":"url","uuid":"8031fe34-3eb4-47f5-b0c8-e85fa1d1195d","feed_id":0,"retina_confidence":-1,"created_ts":"2021-04-29T16:01:13.662Z","id":235548934,"value":"http://www.bnmv3.com/","itype":"apt_url","org":"","confidence":-1,"expiration_ts":"9999-12-31T00:00:00.000Z","owner_organization_id":70,"meta":{"severity":"very-high","detail2":"imported by user 142"},"is_anonymous":false,"is_public":true,"asn":"","status":"active","tags":null,"can_add_public_tags":true,"subtype":null,"tlp":null,"created_by":null,"rdns":null,"is_editable":false,"locations":[],"source_locations":[]}, + {"update_id":200000005,"target_industry":[],"source":"Default Organization","threatscore":25,"threat_type":"bot","trusted_circle_ids":[10015],"description":null,"workgroups":[],"sort":[376544052],"resource_uri":"/api/v2/intelligence/184983050/","modified_ts":"2020-10-09T18:30:14.901Z","country":"CN","source_reported_confidence":100,"latitude":34.7725,"type":"ip","uuid":"c7e4fd9e-b4c0-4c20-83f2-9415ff671a19","feed_id":0,"retina_confidence":-1,"created_ts":"2020-10-09T18:30:14.901Z","id":184983050,"value":"216.160.83.63","itype":"bot_ip","org":"","ip":"216.160.83.63","confidence":100,"expiration_ts":"2318-07-09T20:41:16.995Z","owner_organization_id":1,"meta":{"severity":"low","detail2":"imported by user 1"},"is_anonymous":false,"is_public":false,"asn":"","status":"active","tags":null,"can_add_public_tags":true,"subtype":null,"tlp":null,"created_by":null,"rdns":null,"is_editable":false,"locations":[],"source_locations":[]}, + {"update_id":200000006,"target_industry":[],"source":"Default Organization","threatscore":70,"threat_type":"c2","trusted_circle_ids":[10015],"description":null,"workgroups":[],"sort":[376540078],"resource_uri":"/api/v2/intelligence/184979083/","modified_ts":"2020-10-09T18:14:39.498Z","source_reported_confidence":100,"latitude":43.1479,"type":"domain","uuid":"435d7aa2-93ce-4178-9eaf-6b70be95800e","feed_id":0,"retina_confidence":-1,"created_ts":"2020-10-09T18:14:39.498Z","id":184979083,"value":"www.poledancepoint.com","itype":"c2_domain","org":"","ip":"175.16.199.143","confidence":100,"expiration_ts":"2318-07-09T20:41:16.995Z","owner_organization_id":1,"meta":{"severity":"high","detail2":"imported by user 1"},"is_anonymous":false,"is_public":false,"asn":"","status":"active","tags":[{"id":"wg7","name":"MalSpam"}],"can_add_public_tags":true,"subtype":null,"tlp":null,"created_by":null,"rdns":null,"is_editable":false,"locations":[],"source_locations":[]} + ], + "meta": { + "offset": 0, + "limit": 3, + "total_count": 6, + "next": null, + "took": 1 + } + } + - path: /api/v2/intelligence/ + methods: ["GET"] + request_headers: + Authorization: "apikey test_username:test_api_key" + query_params: + order_by: update_id + modified_ts__lt: "{modified_ts__lt:.*}" + modified_ts__gt: "{modified_ts__gt:.*}" + limit: "3" + q: "test_query" + responses: + - status_code: 200 + body: |- + { + "objects": [ + {"update_id":200000001,"target_industry":[],"source":"Analyst","threatscore":54,"threat_type":"apt","trusted_circle_ids":null,"description":null,"workgroups":[],"sort":[455403032],"resource_uri":"/api/v2/intelligence/232020126/","modified_ts":"2021-04-06T09:56:22.915Z","source_reported_confidence":60,"type":"domain","uuid":"0921be47-9cc2-4265-b896-c62a7cb91042","feed_id":0,"retina_confidence":-1,"created_ts":"2021-04-06T09:56:22.915Z","id":232020126,"value":"gen1xyz.com","itype":"apt_domain","org":"","confidence":60,"expiration_ts":"9999-12-31T00:00:00.000Z","owner_organization_id":67,"meta":{"severity":"very-high","detail2":"imported by user 136"},"is_anonymous":false,"is_public":true,"asn":"","status":"active","tags":null,"can_add_public_tags":true,"subtype":null,"tlp":null,"created_by":null,"rdns":null,"is_editable":false,"locations":[],"source_locations":[]}, + {"update_id":200000002,"target_industry":[],"source":"Analyst","threatscore":9,"threat_type":"apt","trusted_circle_ids":null,"description":null,"workgroups":[],"sort":[467407026],"resource_uri":"/api/v2/intelligence/235548914/","modified_ts":"2021-04-29T16:00:35.529Z","source_reported_confidence":12,"type":"email","uuid":"bc5a223e-f7a1-4acb-b50b-c81395e34218","feed_id":0,"retina_confidence":-1,"created_ts":"2021-04-29T16:00:35.529Z","id":235548914,"value":"edc2@wsx.com","itype":"apt_email","org":"","confidence":12,"expiration_ts":"9999-12-31T00:00:00.000Z","owner_organization_id":70,"meta":{"severity":"medium","detail2":"imported by user 142"},"is_anonymous":false,"is_public":true,"asn":"","status":"active","tags":null,"can_add_public_tags":true,"subtype":null,"tlp":null,"created_by":null,"rdns":null,"is_editable":false,"locations":[],"source_locations":[]}, + {"update_id":200000003,"target_industry":[],"source":"Analyst","threatscore":0,"threat_type":"apt","trusted_circle_ids":null,"description":null,"workgroups":[],"sort":[467409119],"resource_uri":"/api/v2/intelligence/235549247/","modified_ts":"2021-04-29T16:02:17.558Z","source_reported_confidence":-1,"type":"ip","uuid":"463f01f8-7675-4caa-a6aa-db2fb3787b09","feed_id":0,"retina_confidence":-1,"created_ts":"2021-04-29T16:02:17.558Z","id":235549247,"value":"89.160.20.176","itype":"apt_ip","org":"","ip":"89.160.20.176","confidence":-1,"expiration_ts":"9999-12-31T00:00:00.000Z","owner_organization_id":70,"meta":{"severity":"very-high","detail2":"imported by user 142"},"is_anonymous":false,"is_public":true,"asn":"","status":"active","tags":null,"can_add_public_tags":true,"subtype":null,"tlp":null,"created_by":null,"rdns":null,"is_editable":false,"locations":[],"source_locations":[]} + ], + "meta": { + "offset": 0, + "limit": 3, + "total_count": 6, + "next": "/api/v2/intelligence/?search_after=1693750222045%2C200000003&limit=3&q=test_query", + "took": 1 + } + } + # Rules for standard pagination (no q parameter) using update_id__gt. - path: /api/v2/intelligence/ methods: ["GET"] request_headers: diff --git a/packages/ti_anomali/changelog.yml b/packages/ti_anomali/changelog.yml index 4ca45072462..6a5f68b6fd9 100644 --- a/packages/ti_anomali/changelog.yml +++ b/packages/ti_anomali/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "2.8.2" + changes: + - description: Fix pagination when using an advanced search query. The integration now follows the API's next URL for pagination instead of reconstructing the request, which failed when the API used a different cursor format (e.g. search_after) with advanced queries. + type: bugfix + link: https://github.com/elastic/integrations/pull/20146 - version: "2.8.1" changes: - description: Fix transform destination to use keyword for data_stream.namespace, allowing multi-namespace deployments. diff --git a/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-all.expected b/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-all.expected index 9fa7435e0ac..4bb5a9ad768 100644 --- a/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-all.expected +++ b/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-all.expected @@ -26,9 +26,10 @@ inputs: - production target: environment program: |- - state.with( - request( - "GET", + ( + state.want_more ? + state.url.trim_right("/") + state.cursor.next_page + : state.url.trim_right("/") + "/api/v2/intelligence/?" + { "order_by": ["update_id"], "modified_ts__lt": [(now - duration(state.delay)).format(time_layout.RFC3339)], @@ -38,49 +39,53 @@ inputs: ?"remote_api": state.remote_api_true ? optional.of(["true"]) : optional.none(), // never set remote_api=false, only true or absent ?"q": (state.?query.orValue("") != "") ? optional.of([state.query]) : optional.none(), }.format_query() - ).with( - { - "Header": { - "Authorization": ["apikey " + state.username + ":" + state.api_key], - }, - } - ).do_request().as(resp, - (resp.StatusCode == 200) ? - resp.Body.decode_json().as(body, - { - "events": body.objects.map(obj, - { - "json": obj, - ?"event": state.?preserve_original_event.orValue(false) ? - optional.of({"original": obj.encode_json()}) - : - optional.none(), - } - ), - "want_more": body.meta.next != null, - "cursor": (has(state.cursor) ? state.cursor : {}).with( - { - ?"last_update_id": (body.objects.size() > 0) ? optional.of(body.objects[body.objects.size() - 1].update_id) : optional.none(), - } - ), - } - ) - : + ).as(url, + state.with( + request("GET", url).with( { - "events": { - "error": { - "code": string(resp.StatusCode), - "id": string(resp.Status), - "message": "GET " + state.url.trim_right("/") + "/api/v2/intelligence/: " + ( - (size(resp.Body) != 0) ? - string(resp.Body) - : - string(resp.Status) + " (" + string(resp.StatusCode) + ")" - ), - }, + "Header": { + "Authorization": ["apikey " + state.username + ":" + state.api_key], }, - "want_more": false, } + ).do_request().as(resp, + (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + { + "events": body.objects.map(obj, + { + "json": obj, + ?"event": state.?preserve_original_event.orValue(false) ? + optional.of({"original": obj.encode_json()}) + : + optional.none(), + } + ), + "want_more": body.meta.next != null, + "cursor": state.?cursor.orValue({}).with( + { + ?"last_update_id": (body.objects.size() > 0) ? optional.of(body.objects[body.objects.size() - 1].update_id) : optional.none(), + ?"next_page": (body.meta.next != null) ? optional.of(body.meta.next) : optional.none(), + } + ), + } + ) + : + { + "events": { + "error": { + "code": string(resp.StatusCode), + "id": resp.Status, + "message": "GET " + state.url.trim_right("/") + "/api/v2/intelligence/: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + resp.Status + " (" + string(resp.StatusCode) + ")" + ), + }, + }, + "want_more": false, + } + ) ) ) publisher_pipeline.disable_host: true diff --git a/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-default.expected b/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-default.expected index fa964117a1c..55abda82107 100644 --- a/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-default.expected +++ b/packages/ti_anomali/data_stream/intelligence/_dev/test/policy/test-default.expected @@ -15,9 +15,10 @@ inputs: fields_under_root: true interval: 5m program: |- - state.with( - request( - "GET", + ( + state.want_more ? + state.url.trim_right("/") + state.cursor.next_page + : state.url.trim_right("/") + "/api/v2/intelligence/?" + { "order_by": ["update_id"], "modified_ts__lt": [(now - duration(state.delay)).format(time_layout.RFC3339)], @@ -27,49 +28,53 @@ inputs: ?"remote_api": state.remote_api_true ? optional.of(["true"]) : optional.none(), // never set remote_api=false, only true or absent ?"q": (state.?query.orValue("") != "") ? optional.of([state.query]) : optional.none(), }.format_query() - ).with( - { - "Header": { - "Authorization": ["apikey " + state.username + ":" + state.api_key], - }, - } - ).do_request().as(resp, - (resp.StatusCode == 200) ? - resp.Body.decode_json().as(body, - { - "events": body.objects.map(obj, - { - "json": obj, - ?"event": state.?preserve_original_event.orValue(false) ? - optional.of({"original": obj.encode_json()}) - : - optional.none(), - } - ), - "want_more": body.meta.next != null, - "cursor": (has(state.cursor) ? state.cursor : {}).with( - { - ?"last_update_id": (body.objects.size() > 0) ? optional.of(body.objects[body.objects.size() - 1].update_id) : optional.none(), - } - ), - } - ) - : + ).as(url, + state.with( + request("GET", url).with( { - "events": { - "error": { - "code": string(resp.StatusCode), - "id": string(resp.Status), - "message": "GET " + state.url.trim_right("/") + "/api/v2/intelligence/: " + ( - (size(resp.Body) != 0) ? - string(resp.Body) - : - string(resp.Status) + " (" + string(resp.StatusCode) + ")" - ), - }, + "Header": { + "Authorization": ["apikey " + state.username + ":" + state.api_key], }, - "want_more": false, } + ).do_request().as(resp, + (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + { + "events": body.objects.map(obj, + { + "json": obj, + ?"event": state.?preserve_original_event.orValue(false) ? + optional.of({"original": obj.encode_json()}) + : + optional.none(), + } + ), + "want_more": body.meta.next != null, + "cursor": state.?cursor.orValue({}).with( + { + ?"last_update_id": (body.objects.size() > 0) ? optional.of(body.objects[body.objects.size() - 1].update_id) : optional.none(), + ?"next_page": (body.meta.next != null) ? optional.of(body.meta.next) : optional.none(), + } + ), + } + ) + : + { + "events": { + "error": { + "code": string(resp.StatusCode), + "id": resp.Status, + "message": "GET " + state.url.trim_right("/") + "/api/v2/intelligence/: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + resp.Status + " (" + string(resp.StatusCode) + ")" + ), + }, + }, + "want_more": false, + } + ) ) ) publisher_pipeline.disable_host: true diff --git a/packages/ti_anomali/data_stream/intelligence/agent/stream/cel.yml.hbs b/packages/ti_anomali/data_stream/intelligence/agent/stream/cel.yml.hbs index ccde1841a63..f292fb8c0ff 100644 --- a/packages/ti_anomali/data_stream/intelligence/agent/stream/cel.yml.hbs +++ b/packages/ti_anomali/data_stream/intelligence/agent/stream/cel.yml.hbs @@ -36,9 +36,10 @@ redact: fields: - api_key program: |- - state.with( - request( - "GET", + ( + state.want_more ? + state.url.trim_right("/") + state.cursor.next_page + : state.url.trim_right("/") + "/api/v2/intelligence/?" + { "order_by": ["update_id"], "modified_ts__lt": [(now - duration(state.delay)).format(time_layout.RFC3339)], @@ -48,49 +49,53 @@ program: |- ?"remote_api": state.remote_api_true ? optional.of(["true"]) : optional.none(), // never set remote_api=false, only true or absent ?"q": (state.?query.orValue("") != "") ? optional.of([state.query]) : optional.none(), }.format_query() - ).with( - { - "Header": { - "Authorization": ["apikey " + state.username + ":" + state.api_key], - }, - } - ).do_request().as(resp, - (resp.StatusCode == 200) ? - resp.Body.decode_json().as(body, - { - "events": body.objects.map(obj, - { - "json": obj, - ?"event": state.?preserve_original_event.orValue(false) ? - optional.of({"original": obj.encode_json()}) - : - optional.none(), - } - ), - "want_more": body.meta.next != null, - "cursor": (has(state.cursor) ? state.cursor : {}).with( - { - ?"last_update_id": (body.objects.size() > 0) ? optional.of(body.objects[body.objects.size() - 1].update_id) : optional.none(), - } - ), - } - ) - : + ).as(url, + state.with( + request("GET", url).with( { - "events": { - "error": { - "code": string(resp.StatusCode), - "id": string(resp.Status), - "message": "GET " + state.url.trim_right("/") + "/api/v2/intelligence/: " + ( - (size(resp.Body) != 0) ? - string(resp.Body) - : - string(resp.Status) + " (" + string(resp.StatusCode) + ")" - ), - }, + "Header": { + "Authorization": ["apikey " + state.username + ":" + state.api_key], }, - "want_more": false, } + ).do_request().as(resp, + (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + { + "events": body.objects.map(obj, + { + "json": obj, + ?"event": state.?preserve_original_event.orValue(false) ? + optional.of({"original": obj.encode_json()}) + : + optional.none(), + } + ), + "want_more": body.meta.next != null, + "cursor": state.?cursor.orValue({}).with( + { + ?"last_update_id": (body.objects.size() > 0) ? optional.of(body.objects[body.objects.size() - 1].update_id) : optional.none(), + ?"next_page": (body.meta.next != null) ? optional.of(body.meta.next) : optional.none(), + } + ), + } + ) + : + { + "events": { + "error": { + "code": string(resp.StatusCode), + "id": resp.Status, + "message": "GET " + state.url.trim_right("/") + "/api/v2/intelligence/: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + resp.Status + " (" + string(resp.StatusCode) + ")" + ), + }, + }, + "want_more": false, + } + ) ) ) tags: diff --git a/packages/ti_anomali/manifest.yml b/packages/ti_anomali/manifest.yml index 5cfb33946ae..b988d39f511 100644 --- a/packages/ti_anomali/manifest.yml +++ b/packages/ti_anomali/manifest.yml @@ -1,6 +1,6 @@ name: ti_anomali title: Anomali ThreatStream -version: "2.8.1" +version: "2.8.2" description: Ingest threat intelligence indicators from Anomali ThreatStream with Elastic Agent. type: integration format_version: 3.3.2 diff --git a/packages/ti_opencti/data_stream/indicator/_dev/test/policy/test-multi-values.yml b/packages/ti_opencti/data_stream/indicator/_dev/test/policy/test-multi-values.yml index ffcd95638f6..6c38a117d3b 100644 --- a/packages/ti_opencti/data_stream/indicator/_dev/test/policy/test-multi-values.yml +++ b/packages/ti_opencti/data_stream/indicator/_dev/test/policy/test-multi-values.yml @@ -27,8 +27,8 @@ data_stream: marking_ids: - marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9 - marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da - valid_from_start: "2024-01-01T00:00:00Z" - valid_until_end: "2024-12-31T23:59:59Z" + valid_from_start: "2024-01-01T00:00:00.000Z" + valid_until_end: "2024-12-31T23:59:59.000Z" confidence_min: 50 - created_after: "2024-01-01T00:00:00Z" - modified_after: "2024-06-01T00:00:00Z" + created_after: "2024-01-01T00:00:00.000Z" + modified_after: "2024-06-01T00:00:00.000Z" diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_changelog.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_changelog.cpython-314.pyc deleted file mode 100644 index ca6586deba5a3248a28f7e19b15a614309fc1ea6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2226 zcmb_dO-vg{6rTNqHQ10JNE$-05s>0ioQfbhf~KY+2}ErS*@BZ+4%5wgus5uC-Pv(e zP!3TK4eF(-Dz&8-dgviYkZQE0N=`Aftse0<0wHGH5QhMmD_s!ck z@4b2R=6lb5O_2r!qa%6z@`QxYBmNN#rOIsH0OlH+L7H#|jSEbOa$Y zWPete(uz8fChbR>d{LPU2M%lVAne5ltG}pf%CQRwMKJanOS&MK*Ix`A{W+!ZNlA2dYtUt!)je=uamXST_808|d znVX%Y&Shc%GxhH1_(U3?E9*8Z7xAc5Eb4X+pRpOqQ=Q{1Td~Iv&keLRlq0TqhhDBK<^kaC$P}aK5Q_TG+jv+ygiIk`=LvK{DYM!BV}MAN*oKoc z?RHf@3cJ(&_c=ZO>wY1XuJx@CELbQfxYjll{d^b|nW@+6Dc zUSnlJBYE;+T%kOBULBNZ&H`)00kqpJs5A^bHHqsfoSAod=QzyILw9kr7>7J2R|uW2 zLf$u+#|7QRJa8}ZEa+dP&x3KV0)cvnG=F;jlk+#G)?0g5TYGPI-Kk%XjQkuK`Qh}& zzVP_utR29Vjd|ZK&aOHM*)szm>j8uf>jj zckY3jeAL>tcxofOYdze)8gBn;`hNGRhvCzk657}OB*Hzx7XP@75Wub7Ct8#rTN+Pv zhvK52WXk{3c>97D#d{XCs0NISPOj{?t1#wm!K$t_^EO6Z21y{cgE8g6qg_C}R*YQ+ z?Zm)3gXCT+LsG!kZj22Jt|n(1%pjJ9F@P!Zln~5#pBwR0Px(#wBm|5LphbUQhphc2 zN=jOI(hyR{gvW?ex;N0|ffset2G0#V^w}~iQ#c0Y1x>jN%8Qq_0rAwbZ8Cmco;n3| zR0lBmd-m{EnfqBm72iG-)YmJSc!Lgr0uR(30rFT91mQQ-^9Y50ss5U`>Y9Zy;l}uS mOV4Uc&lciekGqi^UR-z}9oUe=*Ux@*_Tz~^B_y}`JNyeYX6!ov diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_kibana_assets.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_kibana_assets.cpython-314.pyc deleted file mode 100644 index 218b4b3f8de9411ed6bc28c5f1d8241e4d3862c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13456 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 H5(obatt}ue diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_manifest_assets.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_manifest_assets.cpython-314.pyc deleted file mode 100644 index 59dc1b01b529e2437e891b57239d775cef6c6dee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3061 zcmb_eO>7fK6rT02?M-46{sJK+br4OdLrEY%IQ*!F8VV7_F&pC)YPwq1n`FV>-Oh}G zR6VpvmEcfSJ@i17K+u$)=%Kw)s6^FM-)y{gNK$cV$M(#d zH*em&nfJZ-ymdvm8bKS{wf9WckI*AN@fytC_Vi;IE~0mkBJ`re0u>^h_VxOx&mBc7 zx}!v;Hlzgl1?sOun~)-|M~ZYxN`*>#77ShD{DcNi$%?<{ErfDw5o$yry?TLIiQI&` zN>l{S-R%CN!QVMADzFs}HZ7_S6)l~bww2UNvhE<1CQn}jLW5hJLR3%?SiYKy>yQn1 zT92rt_@MVIA`N5^4Jy)R6!o*!eVSzs8HDa9#GoV%l2Dd&o~;1@1+Z&O9Q{HPUT}x7r>in%P|8J6g~KTYb(P)#w3n?? z1bA29Sg25X*S66@J{gsn&n8TAG&;h9ITKr2!C*n{G;ukyst%cXLseOgqv>b0VM7HO zCY`ZOi-kQ+DwhQ;NW{nw5q{BE*cXZ2+2h2(B%2 zs*l)KKCfpF*m|*GSd?T_*gj+EK%`G34)-V3V@1uP#e$l!3vgOa?X{>ej5Q9m?EHT9 z-I9ntFS4zpZF^g1mI7Xg+pA?WH5W;3&M5N(q>ekRzHbS}+T4{ja0ilv?jrhiW7A}8 zA~qSHh+prx5xW+<5x*AyuH$y>R_u2CR{W=)nLX*5t;c6JX2zvix&C2OWO8s~a56iQ zoqBn$b@z1Z?r)PbO-IJ1`*Oom(1@NxF~^6C;?KcjFGBGq1pbz|j^~>KaisWSrKsK` zs6x?K6xDLvIzmQBm2ptn>&3O>Q$+sp@JDuKb*Z`soVlB%VfsX#-%$le$Ot& zpAlaRR3yB!BHS-c6~0F)f#>Dl^1X0JFe5EIA+un|kslDMLND>NBHjs=QIQvEUrwfK zp*}_2jGEC_w56nE7<}A_OkV^wp@{oAC>-_g5u1=HM5~#A$NWV)w5@V z)2PM z9ZUX5X49Fu^vUV;$(h*OGxgc=-Up$TAN61E|Kg3wLlcK4lM~6QT{Df{cVh#0GbirF zPRxc*a*4jneOIDa^)K6}VzZ%6kJEaU-fP%8HF!VN{YMp8@i>I4!gF%{v|N9s@#^_m zx&470D$QS-T7O^O@vM%U40pL3j{i++;Ih|O9oXgnepk)G>Z+*E1(6F8Ugw~e@!|%x ztXfqIcCP5wwUEjSNWQdE%j+E`G;dmlWveP)1v+snbgWKQ2?d<$szw2Ar;Feq(6vfc z^*mrHXX;cp@_AK-_y{jx!ZuzJ_qkZXyw~ifxEAvoh#Ppv69totmPvUe zVV<6uoCY$XL0WMA!2gvpiNEeOH2>mmJj;9M(eXNtg8+9Pc>}t~q96#rpq59d>Sz9~ zeG&-P`YzV|xpuYCaixB4L+kX0);|$U9=9SXG(I*fZg?PtF7>_N_d)+3B9a>1GyVZN CDz^6k diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_readme.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_readme.cpython-314.pyc deleted file mode 100644 index 248f019163df7585c4ea2006b247eda800a03e10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2816 zcmd5;O>7fK6rT02opoZ91T{a9A3Gq@m?#z`0Y@YujS_yMmL#=;Lo3tKvb&C#tar`K zxQHMm)I&*ofr>-R364ZUf@6^?0rwt=LP@l3PxR7Tnjob@J@n0borE-{RO+E)`_0Uo zH*emX_q{i6-w`fH(3%hRoj>SD=mnpY8qD3cIt$%Z^a)A|Bj}{Sga{w|MtscY_97GA zUSd)WYC%b{4ke|t(zvVH)8Td9VsXF%XUmfQo-+t(?;zBOK)UL6Nj_^q-5xUn=k0ZW zvB0mK7ZaQvd16=$X9||e4BHx2Jz2LCyvb@O3>2{bEMh_ufyFWtYmp7U)FCD%eL(%( zVirhBtSp6?ob>NSv4B&a)DPxozB68g2CBr90eU z{r5Y#MO#{0E-|`2+qd>9WUbrw4?cuTx;FY0+Ag|DxYbgGLI1j4Ja#eBku+PSGr{Ds z!QoTK;yGZyT0V zLEP|QE(u_esBUH`_qElzIdmj_n(Bn6C$e@2YG8*Hsuyd^B`&Y!rW3P%Ku+;UPPhQ!EXSSWKTH3ddTyxF28eMAV{4 zM`!#%yerKBGSsEGXkouAoFJG?$AMf$zce)6PTWe|9=J7duk(Il zE^&WgZs5DlM~R1tM*|NBzVBJ+omgl;z0i=Fm7dAwR_w&KQUa<)oLd@?7Wao8@RKk@w z5{IBup-@N&HfpmGE9NJ>);fVKpxT6dQ*F>=F=wY{P{lOui@Jt$3Ymrsasu9f*NWCC zG*Zp?wsDMm=*C%vV#~%%&*e>p=@_W0XKhpC3c5A{{%tqyfFtO~Kp-c=mDeY~oV+oy zShH`wX5St9U~)0s|3kR{aqUuV&vnj-xAqU~~CXdG~59s*BAYUkX(% zh8pKXjo+m1Og;~Ftct*1YXU(~@QPM|`g_%bt^Oyi6@!O^+b7B&t_}Z}MA<$qlCPx& z$Z*fLw4^_^DRtf=We$5O6Ckyqia@R*QV(QwrrNZpXopw-@)y*O{WEo2S(=_v3MPvM z$Zo!|ffEi!(g?(ni&z}7NE1wBqKih-%-178C@(DlwIa|CY{m@0ACLyg3GaidW2$6y z%!p#qj7@U5n3+!R-vI7yHn;He;ZMoG1Kx4~1;f|FUxc65#_lGb$z4lwXi=`8m+PPI z>U?nGx!kuF+yc9H|C9EL!QNoZNBHaN-p*(&=)jZ5{evg39OIm=72M}9g!xNjdMlOu zStOJ}b`umKC4q9}`x}tNrn{)_}i%837^iAFe3O9mpw$1X2b`W(4n8H|V4ktcu-DNvo<6WjQz#8u3pqFT4!$bH4jI7$wI05_BN z0a+FWLHHT%dx3&K@^9tKKt$-jQNLKdXTEyRO9YeUVF5{@*_mhJt|cjS?bK(dJ|Fu{ JMAB|o`=3#ifdl{m diff --git a/packages/tychon_quantum_command/tests/__pycache__/test_stream_configuration.cpython-314.pyc b/packages/tychon_quantum_command/tests/__pycache__/test_stream_configuration.cpython-314.pyc deleted file mode 100644 index affca5fb5c40081c102160a7af168023e4b11889..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5802 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 diff --git a/packages/tychon_quantum_command/tests/test_changelog.py b/packages/tychon_quantum_command/tests/test_changelog.py deleted file mode 100644 index 073382c558f..00000000000 --- a/packages/tychon_quantum_command/tests/test_changelog.py +++ /dev/null @@ -1,28 +0,0 @@ -from __future__ import print_function - -import io -import os -import re -import unittest - - -class ChangelogTest(unittest.TestCase): - def setUp(self): - # type: () -> None - self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - self.changelog_path = os.path.join(self.package_dir, 'changelog.yml') - - def test_every_change_entry_has_link(self): - # type: () -> None - with io.open(self.changelog_path, 'r', encoding='utf-8') as handle: - content = handle.read() - - change_entries = re.findall(r'(?ms)^ - description: .*?(?=^ - description: |\Z)', content) - self.assertGreaterEqual(len(change_entries), 1) - - for entry in change_entries: - self.assertRegex(entry, r'(?m)^ link: https?://\S+$') - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/packages/tychon_quantum_command/tests/test_kibana_assets.py b/packages/tychon_quantum_command/tests/test_kibana_assets.py deleted file mode 100644 index a2945ed3b19..00000000000 --- a/packages/tychon_quantum_command/tests/test_kibana_assets.py +++ /dev/null @@ -1,534 +0,0 @@ -from __future__ import print_function - -import json -import os -import re -import unittest -import zipfile - - -EXPECTED_COUNTS = { - "dashboard": 6, - "index-pattern": 3, - "search": 2, - "tag": 3, - "visualization": 14, -} - -TOPOLOGY_VISUALIZATION_ID = 'tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c' -TOPOLOGY_DASHBOARD_ID = 'tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology' -APPLICATION_REPORT_DASHBOARD_ID = 'tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report' -CERTIFICATE_OPERATIONS_DASHBOARD_ID = 'tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard' -APPLICATION_LIST_VISUALIZATION_ID = 'tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e' - - -class KibanaAssetsTest(unittest.TestCase): - def setUp(self): - # type: () -> None - self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - self.kibana_dir = os.path.join(self.package_dir, "kibana") - self.kibana_zip = os.path.join(self.package_dir, "kibana.zip") - - def _get_source(self): - # type: () -> str - for root, _, files in os.walk(self.kibana_dir): - for file_name in files: - if file_name.endswith('.json'): - return 'dir' - if os.path.isfile(self.kibana_zip): - return 'zip' - self.fail('No Kibana saved objects found in kibana/ or kibana.zip') - - def _load_objects(self): - # type: () -> tuple - counts = {} - objects_by_type = {} - - if self._get_source() == 'dir': - for root, _, files in os.walk(self.kibana_dir): - folder_name = os.path.basename(root) - if folder_name == 'kibana': - continue - - normalized_type = folder_name.replace('_', '-') - for file_name in files: - if not file_name.endswith('.json'): - continue - - path = os.path.join(root, file_name) - with open(path, 'r', encoding='utf-8') as handle: - obj = json.load(handle) - - counts[normalized_type] = counts.get(normalized_type, 0) + 1 - type_objects = objects_by_type.setdefault(normalized_type, {}) - type_objects[obj['id']] = obj - - self.assertEqual(normalized_type, obj['type'], 'Object type mismatch for %s' % path) - self.assertEqual(obj['id'], os.path.splitext(file_name)[0], 'Object filename must exactly match the saved object id for %s' % path) - else: - with zipfile.ZipFile(self.kibana_zip, 'r') as archive: - for name in archive.namelist(): - if not name.endswith('.json'): - continue - - normalized_name = name.replace('\\', '/') - parts = normalized_name.split('/') - self.assertGreaterEqual(len(parts), 2, 'Unexpected archive entry %s' % normalized_name) - folder_name = parts[0] - file_name = parts[-1] - normalized_type = folder_name.replace('_', '-') - obj = json.loads(archive.read(name).decode('utf-8')) - - counts[normalized_type] = counts.get(normalized_type, 0) + 1 - type_objects = objects_by_type.setdefault(normalized_type, {}) - type_objects[obj['id']] = obj - - self.assertEqual(normalized_type, obj['type'], 'Object type mismatch for %s' % normalized_name) - self.assertEqual(obj['id'], os.path.splitext(file_name)[0], 'Object filename must exactly match the saved object id for %s' % normalized_name) - - return counts, objects_by_type - - def _load_reference_objects(self): - # type: () -> dict - reference_path = os.path.join( - os.path.dirname(self.package_dir), - "Dashboards", - "TYCHON QC Enterprise Dashboards 2.0.1.2.ndjson", - ) - objects_by_type = {} - with open(reference_path, 'r', encoding='utf-8') as handle: - for line in handle: - if not line.strip(): - continue - obj = json.loads(line) - if 'type' not in obj: - continue - type_objects = objects_by_type.setdefault(obj['type'], {}) - type_objects[obj['id']] = obj - - return objects_by_type - - def _reference_dashboard_id(self, dashboard_id): - # type: (str) -> str - normalized = dashboard_id - prefix = 'tychon_quantum_command-' - if normalized.startswith(prefix): - normalized = normalized[len(prefix):] - - for suffix in [ - '-inventory', - '-application-report', - '-application-detail', - '-application-connections-topology', - '-cost-analysis', - '-certificate-operations-dashboard', - ]: - if normalized.endswith(suffix): - return normalized[:-len(suffix)] - - return normalized - - def _panel_title(self, panel): - # type: (dict) -> str - return ( - panel.get('title') or - panel.get('embeddableConfig', {}).get('savedVis', {}).get('title') or - panel.get('embeddableConfig', {}).get('attributes', {}).get('title') or - '' - ) - - def _panel_type(self, panel): - # type: (dict) -> str - if panel.get('type') == 'search': - return 'search' - return panel.get('embeddableConfig', {}).get('savedVis', {}).get('type') or panel.get('type') - - def _resolve_reference_panel(self, dashboard, panel, reference_objects): - # type: (dict, dict, dict) -> dict - panel_ref_name = panel.get('panelRefName') - if not panel_ref_name: - return panel - - reference = None - for candidate in dashboard.get('references', []): - ref_name = candidate.get('name', '') - if ref_name == panel_ref_name or ref_name.endswith(':' + panel_ref_name): - reference = candidate - break - - if reference is None: - return panel - - saved_object = reference_objects.get(reference['type'], {}).get(reference['id']) - if saved_object is None: - return panel - - resolved = json.loads(json.dumps(panel)) - resolved.pop('panelRefName', None) - if reference['type'] == 'visualization': - vis_state = json.loads(saved_object['attributes']['visState']) - resolved.setdefault('embeddableConfig', {})['savedVis'] = { - 'title': vis_state.get('title'), - 'type': vis_state.get('type'), - 'aggs': vis_state.get('aggs', []), - 'params': vis_state.get('params', {}), - } - elif reference['type'] == 'search': - resolved['type'] = 'search' - resolved.setdefault('embeddableConfig', {})['attributes'] = saved_object['attributes'] - - return resolved - - def _collect_query_fields(self, value, fields): - # type: (object, set) -> None - if isinstance(value, dict): - for key, item in value.items(): - if key in ('field', '%timefield%', 'sourceField') and isinstance(item, str): - fields.add(item) - elif key in ('term', 'terms', 'match_phrase', 'exists', 'range') and isinstance(item, dict): - for field_name, field_value in item.items(): - if field_name == 'field' and isinstance(field_value, str): - fields.add(field_value) - elif isinstance(field_name, str): - fields.add(field_name) - self._collect_query_fields(field_value, fields) - elif key == 'query' and isinstance(item, str): - for match in re.findall(r'"?([A-Za-z_@][A-Za-z0-9_@.-]+)"?\s*:', item): - fields.add(match) - else: - self._collect_query_fields(item, fields) - elif isinstance(value, list): - for item in value: - self._collect_query_fields(item, fields) - - def _panel_query_signature(self, panel): - # type: (dict) -> tuple - indexes = set() - fields = set() - - def collect_vega_data(data): - # type: (object) -> None - if isinstance(data, dict): - url = data.get('url') - if isinstance(url, dict): - if isinstance(url.get('index'), str): - indexes.add(url['index']) - self._collect_query_fields(url, fields) - for item in data.values(): - collect_vega_data(item) - elif isinstance(data, list): - for item in data: - collect_vega_data(item) - - spec = panel.get('embeddableConfig', {}).get('savedVis', {}).get('params', {}).get('spec') - if spec: - spec_obj = json.loads(spec) - collect_vega_data(spec_obj.get('data', [])) - spec_text = json.dumps(spec_obj) - for match in re.findall(r"'([A-Za-z0-9_@.-]+)'\s*:", spec_text): - if '.' in match or match.startswith('@'): - fields.add(match) - - if panel.get('type') == 'search': - attributes = panel.get('embeddableConfig', {}).get('attributes', {}) - for column in attributes.get('columns', []): - fields.add(column) - for sort_item in attributes.get('sort', []): - if sort_item: - fields.add(sort_item[0]) - search_source = attributes.get('kibanaSavedObjectMeta', {}).get('searchSourceJSON') - if search_source: - self._collect_query_fields(json.loads(search_source), fields) - - self._collect_query_fields(panel.get('embeddableConfig', {}).get('attributes', {}).get('state', {}), fields) - - ignored_fields = set(['order', 'size']) - return sorted(indexes), sorted(fields - ignored_fields) - - def _assert_search_panel_uses_saved_object_reference(self, dashboard, panel, objects_by_type): - # type: (dict, dict, dict) -> dict - self.assertEqual('search', panel.get('type')) - self.assertIn('panelRefName', panel, 'Search panel %s must be embedded by reference' % panel.get('title')) - self.assertNotIn('attributes', panel.get('embeddableConfig', {}), 'Search panel %s should not carry by-value saved search state' % panel.get('title')) - - panel_ref_name = panel.get('panelRefName') - search_ref = None - for ref in dashboard.get('references', []): - ref_name = ref.get('name', '') - if ref.get('type') == 'search' and (ref_name == panel_ref_name or ref_name.endswith(':' + panel_ref_name)): - search_ref = ref - break - self.assertIsNotNone(search_ref, 'Search panel %s must reference a package search saved object' % panel.get('title')) - self.assertIn(search_ref['id'], objects_by_type.get('search', {})) - return objects_by_type['search'][search_ref['id']]['attributes'] - - def test_expected_object_counts(self): - counts, _ = self._load_objects() - self.assertEqual(EXPECTED_COUNTS, counts) - - def test_all_saved_object_references_resolve(self): - _, objects_by_type = self._load_objects() - - for object_type in sorted(objects_by_type): - objects = objects_by_type[object_type] - for object_id in sorted(objects): - obj = objects[object_id] - for reference in obj.get('references', []): - ref_type = reference['type'] - ref_id = reference['id'] - self.assertIn(ref_type, objects_by_type, 'Missing reference type %s from %s/%s' % (ref_type, object_type, object_id)) - self.assertIn(ref_id, objects_by_type[ref_type], 'Missing reference id %s (%s) from %s/%s' % (ref_id, ref_type, object_type, object_id)) - - def test_dashboards_do_not_use_legacy_saved_object_dependencies(self): - _, objects_by_type = self._load_objects() - - for dashboard in objects_by_type.get('dashboard', {}).values(): - disallowed_refs = {'links', 'visualization'} - for reference in dashboard.get('references', []): - self.assertNotIn(reference['type'], disallowed_refs, 'Dashboard %s still references %s' % (dashboard['id'], reference['type'])) - - panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) - for panel in panels: - if panel.get('type') == 'visualization': - self.assertNotIn('panelRefName', panel, 'Dashboard %s still uses by-reference visualization panel %s' % (dashboard['id'], panel.get('panelIndex'))) - - def test_dashboards_have_package_safe_navigation(self): - _, objects_by_type = self._load_objects() - - total_drilldown_refs = 0 - for dashboard in objects_by_type.get('dashboard', {}).values(): - search_source = json.loads(dashboard['attributes']['kibanaSavedObjectMeta']['searchSourceJSON']) - for filt in search_source.get('filter', []): - self.assertNotEqual(filt.get('query', {}).get('exists', {}).get('field'), '@timestamp', 'Dashboard %s still has a dashboard-level @timestamp exists filter' % dashboard['id']) - - drilldown_refs = [ - ref for ref in dashboard.get('references', []) - if ref['type'] == 'dashboard' and 'DASHBOARD_TO_DASHBOARD_DRILLDOWN' in ref['name'] - ] - self.assertGreaterEqual(len(drilldown_refs), 1, 'Dashboard %s is missing package-safe navigation drilldowns' % dashboard['id']) - total_drilldown_refs += len(drilldown_refs) - - panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) - panel_event_count = 0 - for panel in panels: - events = panel.get('embeddableConfig', {}).get('enhancements', {}).get('dynamicActions', {}).get('events', []) - for event in events: - if event.get('action', {}).get('factoryId') == 'DASHBOARD_TO_DASHBOARD_DRILLDOWN': - panel_event_count += 1 - self.assertGreaterEqual(panel_event_count, 1, 'Dashboard %s has no embedded drilldown events' % dashboard['id']) - - self.assertGreaterEqual(total_drilldown_refs, 20) - - def test_dashboards_have_visible_navigation_panel_in_screenshot_order(self): - _, objects_by_type = self._load_objects() - expected_labels = [ - 'Inventory', - 'Application Report', - 'Application Detail', - 'Certificate Report', - 'Application Connections Topology', - 'Cost Analysis', - ] - - for dashboard in objects_by_type.get('dashboard', {}).values(): - panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) - nav_panels = [panel for panel in panels if panel.get('panelIndex') == 'tychon-quantum-command-nav'] - self.assertEqual(1, len(nav_panels), 'Dashboard %s must include one visible nav panel' % dashboard['id']) - nav_panel = nav_panels[0] - self.assertEqual(0, nav_panel.get('gridData', {}).get('y'), 'Dashboard %s nav panel must be at the top row' % dashboard['id']) - self.assertEqual(3, nav_panel.get('gridData', {}).get('h'), 'Dashboard %s nav panel should match reference panel height' % dashboard['id']) - params = nav_panel.get('embeddableConfig', {}).get('savedVis', {}).get('params', {}) - self.assertEqual(12, params.get('fontSize'), 'Dashboard %s nav panel should match reference markdown font size' % dashboard['id']) - markdown = params.get('markdown', '') - self.assertNotIn('TYCHON Quantum Command Navigation', markdown, 'Dashboard %s nav panel should not include an extra heading' % dashboard['id']) - positions = [] - for label in expected_labels: - pos = markdown.find(label) - self.assertNotEqual(-1, pos, 'Dashboard %s nav panel is missing label %s' % (dashboard['id'], label)) - positions.append(pos) - self.assertEqual(sorted(positions), positions, 'Dashboard %s nav labels are out of order' % dashboard['id']) - - def test_package_dashboards_match_reference_saved_object_queries(self): - # type: () -> None - _, package_objects = self._load_objects() - reference_objects = self._load_reference_objects() - - reference_dashboards = reference_objects.get('dashboard', {}) - package_dashboards_by_reference_id = {} - for dashboard in package_objects.get('dashboard', {}).values(): - package_dashboards_by_reference_id[self._reference_dashboard_id(dashboard['id'])] = dashboard - - self.assertEqual(set(reference_dashboards), set(package_dashboards_by_reference_id)) - - for reference_id in sorted(reference_dashboards): - reference_dashboard = reference_dashboards[reference_id] - package_dashboard = package_dashboards_by_reference_id[reference_id] - reference_panels = {} - for panel in json.loads(reference_dashboard['attributes'].get('panelsJSON', '[]')): - reference_panels[panel.get('panelIndex')] = self._resolve_reference_panel(reference_dashboard, panel, reference_objects) - package_panels = {} - for panel in json.loads(package_dashboard['attributes'].get('panelsJSON', '[]')): - package_panels[panel.get('panelIndex')] = self._resolve_reference_panel(package_dashboard, panel, package_objects) - - missing_panel_ids = set(reference_panels) - set(package_panels) - extra_panel_ids = set(package_panels) - set(reference_panels) - self.assertEqual( - ['links'], - sorted(set(self._panel_type(reference_panels[panel_id]) for panel_id in missing_panel_ids)), - 'Dashboard %s has non-navigation panels missing from the package' % package_dashboard['id'], - ) - self.assertEqual( - set(['tychon-quantum-command-nav']), - extra_panel_ids, - 'Dashboard %s has unexpected package-only panels' % package_dashboard['id'], - ) - - for panel_id in sorted(set(reference_panels) & set(package_panels)): - reference_panel = reference_panels[panel_id] - package_panel = package_panels[panel_id] - self.assertEqual( - self._panel_title(reference_panel), - self._panel_title(package_panel), - 'Dashboard %s panel %s title drifted from the reference saved object' % (package_dashboard['id'], panel_id), - ) - self.assertEqual( - self._panel_query_signature(reference_panel), - self._panel_query_signature(package_panel), - 'Dashboard %s panel %s query fields drifted from the reference saved object' % (package_dashboard['id'], panel_id), - ) - - def test_package_dashboards_do_not_contain_mojibake(self): - # type: () -> None - _, objects_by_type = self._load_objects() - blocked_markers = ['\\u00e2', '\\u20ac', u'ā', u'â', u'Ã', u'�'] - - for dashboard in objects_by_type.get('dashboard', {}).values(): - dashboard_text = json.dumps(dashboard, ensure_ascii=False) - for marker in blocked_markers: - self.assertNotIn(marker, dashboard_text, 'Dashboard %s contains mojibake marker %s' % (dashboard['id'], marker)) - - def test_application_connections_topology_panel_matches_standalone_visualization(self): - # type: () -> None - _, objects_by_type = self._load_objects() - - dashboard = objects_by_type['dashboard'][TOPOLOGY_DASHBOARD_ID] - visualization = objects_by_type['visualization'][TOPOLOGY_VISUALIZATION_ID] - visualization_state = json.loads(visualization['attributes']['visState']) - - panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) - topology_panels = [panel for panel in panels if panel.get('title') == 'PQC Connections Topology'] - self.assertEqual(1, len(topology_panels), 'Topology dashboard must embed exactly one PQC Connections Topology panel') - - topology_panel = topology_panels[0] - saved_vis = topology_panel.get('embeddableConfig', {}).get('savedVis', {}) - inline_state = { - 'title': saved_vis.get('title'), - 'type': saved_vis.get('type'), - 'aggs': saved_vis.get('data', {}).get('aggs', []), - 'params': saved_vis.get('params', {}), - } - self.assertEqual(visualization_state, inline_state, 'Topology dashboard panel must stay in sync with the standalone Vega visualization') - - spec = json.loads(visualization_state['params']['spec']) - raw_sources = [source for source in spec.get('data', []) if source.get('name') == 'raw'] - self.assertEqual(1, len(raw_sources), 'Topology Vega spec must define exactly one raw source') - self.assertEqual('tychon-pqc-applications', raw_sources[0].get('url', {}).get('index')) - raw_must = raw_sources[0].get('url', {}).get('body', {}).get('aggs', {}).get('pairs', {}).get('filter', {}).get('bool', {}).get('must', []) - self.assertIn({'exists': {'field': 'host.hostname'}}, raw_must) - self.assertIn({'exists': {'field': 'tychon.application.name'}}, raw_must) - self.assertIn({'term': {'event.dataset': 'tychon.application'}}, raw_must) - - def test_application_visualizations_do_not_filter_on_unreachable_event_dataset(self): - # type: () -> None - _, objects_by_type = self._load_objects() - - application_list = objects_by_type['visualization'][APPLICATION_LIST_VISUALIZATION_ID] - topology = objects_by_type['visualization'][TOPOLOGY_VISUALIZATION_ID] - - app_list_spec = json.loads(json.loads(application_list['attributes']['visState'])['params']['spec']) - topology_spec = json.loads(json.loads(topology['attributes']['visState'])['params']['spec']) - - app_sources = [source for source in app_list_spec.get('data', []) if source.get('name') == 'apps'] - self.assertEqual(1, len(app_sources), 'Application list visualization must define one apps source') - self.assertEqual('tychon-pqc-applications', app_sources[0].get('url', {}).get('index')) - app_filter = app_sources[0].get('url', {}).get('body', {}).get('aggs', {}).get('app_only', {}).get('filter', {}) - self.assertEqual({'term': {'event.dataset': 'tychon.application'}}, app_filter) - - active_signals = [signal for signal in app_list_spec.get('signals', []) if signal.get('name') == 'activeFilter'] - self.assertEqual(1, len(active_signals), 'Application list visualization must define one activeFilter signal') - active_update = active_signals[0].get('update', '') - self.assertIn("'event.dataset': 'tychon.application'", active_update) - - self.assertIn("event.dataset", repr(topology_spec)) - - - def test_application_report_embeds_dod_omb_report_search_panel(self): - # type: () -> None - _, objects_by_type = self._load_objects() - - dashboard = objects_by_type['dashboard'][APPLICATION_REPORT_DASHBOARD_ID] - panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) - omb_panels = [panel for panel in panels if panel.get('title') == 'DoD OMB Report'] - self.assertEqual(1, len(omb_panels), 'Application Report dashboard must embed exactly one DoD OMB Report panel') - - omb_panel = omb_panels[0] - attributes = self._assert_search_panel_uses_saved_object_reference(dashboard, omb_panel, objects_by_type) - self.assertEqual('DoD OMB Report', attributes.get('title')) - self.assertEqual('OMB Report for the Department of Defense', attributes.get('description')) - self.assertIn('observer.hostname', attributes.get('columns', [])) - self.assertIn('omb.vulnerability_status', attributes.get('columns', [])) - - search_source = json.loads(attributes['kibanaSavedObjectMeta']['searchSourceJSON']) - self.assertEqual('kibanaSavedObjectMeta.searchSourceJSON.index', search_source.get('indexRefName')) - filters = search_source.get('filter', []) - self.assertEqual(1, len(filters)) - self.assertEqual('omb.vulnerability_status', filters[0].get('query', {}).get('exists', {}).get('field')) - self.assertEqual('kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index', filters[0].get('meta', {}).get('indexRefName')) - - - def test_certificate_operations_dashboard_embeds_inventory_detail_search_panel(self): - # type: () -> None - _, objects_by_type = self._load_objects() - - dashboard = objects_by_type['dashboard'][CERTIFICATE_OPERATIONS_DASHBOARD_ID] - panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) - inventory_panels = [panel for panel in panels if panel.get('title') == 'Certificate Inventory Detail'] - self.assertEqual(1, len(inventory_panels), 'Certificate Operations dashboard must embed exactly one Certificate Inventory Detail panel') - - inventory_panel = inventory_panels[0] - attributes = self._assert_search_panel_uses_saved_object_reference(dashboard, inventory_panel, objects_by_type) - self.assertEqual('Certificate Inventory Detail', attributes.get('title')) - self.assertIn('observer.hostname', attributes.get('columns', [])) - self.assertIn('x509.subject.common_name', attributes.get('columns', [])) - self.assertEqual([[u'cert_days_remaining', u'asc']], attributes.get('sort')) - - search_source = json.loads(attributes['kibanaSavedObjectMeta']['searchSourceJSON']) - self.assertEqual('kibanaSavedObjectMeta.searchSourceJSON.index', search_source.get('indexRefName')) - self.assertEqual([], search_source.get('filter', [])) - - - def test_application_list_panel_matches_standalone_visualization(self): - # type: () -> None - _, objects_by_type = self._load_objects() - - dashboard = objects_by_type['dashboard'][TOPOLOGY_DASHBOARD_ID] - visualization = objects_by_type['visualization'][APPLICATION_LIST_VISUALIZATION_ID] - visualization_state = json.loads(visualization['attributes']['visState']) - - panels = json.loads(dashboard['attributes'].get('panelsJSON', '[]')) - app_panels = [panel for panel in panels if panel.get('title') == 'QuantumApplicationList'] - self.assertEqual(1, len(app_panels), 'Topology dashboard must embed exactly one QuantumApplicationList panel') - - app_panel = app_panels[0] - saved_vis = app_panel.get('embeddableConfig', {}).get('savedVis', {}) - inline_state = { - 'title': saved_vis.get('title'), - 'type': saved_vis.get('type'), - 'aggs': saved_vis.get('data', {}).get('aggs', []), - 'params': saved_vis.get('params', {}), - } - self.assertEqual(visualization_state, inline_state, 'Topology dashboard app list panel must stay in sync with the standalone Vega visualization') - - -if __name__ == '__main__': - unittest.main() diff --git a/packages/tychon_quantum_command/tests/test_manifest_assets.py b/packages/tychon_quantum_command/tests/test_manifest_assets.py deleted file mode 100644 index 49abc0304b5..00000000000 --- a/packages/tychon_quantum_command/tests/test_manifest_assets.py +++ /dev/null @@ -1,40 +0,0 @@ -from __future__ import print_function - -import io -import os -import unittest - - -SCREENSHOTS = [ - ('/img/TQC_Inventory.png', '3434x1086'), - ('/img/TQC_Application_Report.png', '3437x1072'), - ('/img/TQC_Application_Detail.png', '3435x1086'), - ('/img/TQC_Certificate_Report.png', '3437x1083'), - ('/img/TQC_Application_Connections_Topology.png', '3435x1082'), - ('/img/TQC_Cost_Analysis.png', '3438x1082'), -] - - -class ManifestAssetsTest(unittest.TestCase): - def setUp(self): - # type: () -> None - self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - self.manifest_path = os.path.join(self.package_dir, 'manifest.yml') - - def test_manifest_screenshot_files_exist_with_expected_size_metadata(self): - # type: () -> None - with io.open(self.manifest_path, 'r', encoding='utf-8') as handle: - content = handle.read() - - for src, size in SCREENSHOTS: - disk_path = os.path.join(self.package_dir, src.lstrip('/').replace('/', os.sep)) - self.assertTrue(os.path.isfile(disk_path), 'Missing screenshot file %s' % src) - self.assertIn('src: %s' % src, content) - self.assertIn('size: %s' % size, content) - - self.assertNotIn('Topography', content) - self.assertNotIn('Appplication', content) - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/packages/tychon_quantum_command/tests/test_publish_readiness.py b/packages/tychon_quantum_command/tests/test_publish_readiness.py deleted file mode 100644 index 75d59285ecd..00000000000 --- a/packages/tychon_quantum_command/tests/test_publish_readiness.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import print_function - -import io -import json -import os -import unittest - - -class PublishReadinessTest(unittest.TestCase): - def setUp(self): - # type: () -> None - self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - self.docs_dir = os.path.join(self.package_dir, 'docs') - self.dev_dir = os.path.join(self.package_dir, '_dev') - self.sample_event_path = os.path.join(self.package_dir, 'sample_event.json') - self.validation_path = os.path.join(self.package_dir, 'validation.yml') - - def test_package_sample_event_is_real_data(self): - # type: () -> None - with io.open(self.sample_event_path, 'r', encoding='utf-8') as handle: - sample_event = json.load(handle) - - self.assertNotIn('description', sample_event) - self.assertEqual('logs', sample_event['data_stream']['type']) - self.assertEqual('tychon_quantum_command.tychon_pqc', sample_event['data_stream']['dataset']) - self.assertEqual('tychon_quantum_command.tychon_pqc', sample_event['event']['dataset']) - self.assertIn('@timestamp', sample_event) - self.assertIn('tychon', sample_event) - - def test_validation_enforces_docs_structure(self): - # type: () -> None - with io.open(self.validation_path, 'r', encoding='utf-8') as handle: - content = handle.read() - - self.assertIn('docs_structure_enforced:', content) - self.assertIn('enabled: true', content) - self.assertIn('version: 1', content) - self.assertIn('exclude_checks: [ "SVR00002" ]', content) - - def test_docs_directory_contains_only_generated_readme(self): - # type: () -> None - markdown_files = [] - for file_name in os.listdir(self.docs_dir): - if file_name.lower().endswith('.md'): - markdown_files.append(file_name) - - self.assertEqual(['README.md'], sorted(markdown_files)) - - def test_dev_directory_contains_only_build_readme_template(self): - # type: () -> None - allowed_files = set([ - '_dev/build/docs/README.md', - ]) - found_files = set() - - for root, _, files in os.walk(self.dev_dir): - for file_name in files: - relative_path = os.path.relpath(os.path.join(root, file_name), self.package_dir) - found_files.add(relative_path.replace('\\', '/')) - - self.assertEqual(allowed_files, found_files) - - -if __name__ == '__main__': - unittest.main() diff --git a/packages/tychon_quantum_command/tests/test_readme.py b/packages/tychon_quantum_command/tests/test_readme.py deleted file mode 100644 index b852e2ee04e..00000000000 --- a/packages/tychon_quantum_command/tests/test_readme.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import print_function - -import io -import os -import unittest - - -class ReadmeTest(unittest.TestCase): - def setUp(self): - # type: () -> None - self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - self.readme_path = os.path.join(self.package_dir, 'docs', 'README.md') - self.readme_template_path = os.path.join( - self.package_dir, - '_dev', - 'build', - 'docs', - 'README.md', - ) - - def test_readme_has_no_template_placeholders(self): - # type: () -> None - with io.open(self.readme_path, 'r', encoding='utf-8') as handle: - content = handle.read() - - disallowed_markers = [ - '{Data stream name}', - '{data stream name}', - '{source}', - '{list types}', - 'Vendor documentation link 1', - 'Vendor documentation link 2', - 'Vendor documentation link 3', - 'These APIs are used with this integration:\n* ...', - 'replace the placeholder package `sample_event.json`', - ] - - for marker in disallowed_markers: - self.assertNotIn(marker, content) - - def test_readme_uses_namespace_safe_transform_source(self): - # type: () -> None - with io.open(self.readme_path, 'r', encoding='utf-8') as handle: - content = handle.read() - - self.assertIn('logs-tychon_quantum_command.tychon_pqc-*', content) - self.assertIn('logs-tychon_quantum_command.tychon_pqc-', content) - self.assertIn('`logs-tychon_quantum_command.tychon_pqc`', content) - self.assertIn('.ds-logs-tychon_quantum_command.tychon_pqc--YYYY.MM.DD-000001', content) - self.assertNotIn('logs-tychon_pqc-*', content) - - def test_readme_template_exists_and_uses_generated_header(self): - # type: () -> None - self.assertTrue(os.path.isfile(self.readme_template_path)) - - with io.open(self.readme_template_path, 'r', encoding='utf-8') as handle: - content = handle.read() - - self.assertTrue(content.startswith('{{ generatedHeader }}\n\n')) - self.assertNotIn('\n', content) - self.assertNotIn('replace the placeholder package `sample_event.json`', content) - - -if __name__ == '__main__': - unittest.main() diff --git a/packages/tychon_quantum_command/tests/test_stream_configuration.py b/packages/tychon_quantum_command/tests/test_stream_configuration.py deleted file mode 100644 index 8d968981993..00000000000 --- a/packages/tychon_quantum_command/tests/test_stream_configuration.py +++ /dev/null @@ -1,230 +0,0 @@ -from __future__ import print_function - -import io -import os -import re -import unittest - - -class StreamConfigurationTest(unittest.TestCase): - def setUp(self): - # type: () -> None - self.package_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - self.manifest_path = os.path.join( - self.package_dir, - "data_stream", - "tychon_pqc", - "manifest.yml", - ) - self.stream_template_path = os.path.join( - self.package_dir, - "data_stream", - "tychon_pqc", - "agent", - "stream", - "stream.yml.hbs", - ) - self.pipeline_path = os.path.join( - self.package_dir, - "data_stream", - "tychon_pqc", - "elasticsearch", - "ingest_pipeline", - "default.yml", - ) - self.ecs_fields_path = os.path.join( - self.package_dir, - "data_stream", - "tychon_pqc", - "fields", - "ecs.yml", - ) - self.custom_fields_path = os.path.join( - self.package_dir, - "data_stream", - "tychon_pqc", - "fields", - "fields.yml", - ) - self.transform_dir = os.path.join( - self.package_dir, - "elasticsearch", - "transform", - ) - - def _read_text(self, path): - # type: (str) -> str - with io.open(path, "r", encoding="utf-8") as handle: - return handle.read() - - def test_manifest_exposes_windows_and_linux_path_vars(self): - # type: () -> None - content = self._read_text(self.manifest_path) - - self.assertIn("- name: windows_paths", content) - self.assertIn("title: Windows paths", content) - self.assertIn(r"C:\Program Files\Tychon\*.ndjson", content) - - self.assertIn("- name: linux_paths", content) - self.assertIn("title: Linux paths", content) - self.assertIn("/var/log/tychon/*.ndjson", content) - - additional_paths_match = re.search( - r"- name: paths\s+type: text\s+title: Additional paths\s+multi: true\s+required: false", - content, - re.MULTILINE, - ) - self.assertIsNotNone(additional_paths_match) - - def test_stream_template_renders_all_path_groups(self): - # type: () -> None - content = self._read_text(self.stream_template_path) - - self.assertNotIn("type: filestream", content) - self.assertNotIn("id:", content) - self.assertNotIn("data_stream:", content) - self.assertNotIn("{{uuid}}", content) - self.assertNotIn("{{data_stream.type}}-{{data_stream.dataset}}", content) - self.assertIn("parsers:", content) - self.assertIn("ndjson:", content) - self.assertIn("overwrite_keys: true", content) - self.assertIn("expand_keys: true", content) - - expected_order = [ - "{{#each windows_paths}}", - "{{#each linux_paths}}", - "{{#each paths}}", - ] - - start = 0 - for marker in expected_order: - index = content.find(marker, start) - self.assertNotEqual(-1, index, "Missing marker %s" % marker) - start = index + 1 - - def test_ingest_pipeline_preserves_or_derives_event_dataset(self): - # type: () -> None - content = self._read_text(self.pipeline_path) - - self.assertNotIn("field: event.dataset\n value: tychon_pqc", content) - self.assertIn("currentDataset == null", content) - self.assertIn("currentDataset == 'tychon_quantum_command.tychon_pqc'", content) - self.assertIn("currentDataset == 'tychon_pqc'", content) - self.assertIn("dataset = 'tychon.application';", content) - self.assertIn("dataset = 'tychon.installed_app';", content) - self.assertIn("dataset = 'tychon.browser_extension';", content) - self.assertIn("dataset = 'tychon.cipher';", content) - self.assertIn("tychonIndex == 'system-readiness'", content) - self.assertIn("def eventAction = ctx.event.action != null ? ctx.event.action.toString() : null;", content) - self.assertIn("if (eventAction == 'quantum_assessment_app_group') {", content) - self.assertIn("dataset = 'quantum_assessment.app_group';", content) - self.assertIn("dataset = 'quantum_assessment';", content) - self.assertIn("currentDataset == genericDataset", content) - self.assertIn("currentDataset instanceof List && currentDataset.contains(genericDataset)", content) - self.assertIn("genericDataset = tychonIndex != null ? 'tychon_quantum_command.' + tychonIndex : null;", content) - - def test_ingest_pipeline_includes_reference_rehydration_and_flat_field_logic(self): - # type: () -> None - content = self._read_text(self.pipeline_path) - - self.assertIn("field: event.ingested", content) - self.assertIn("Preserve flat event.* fields before event defaults are applied.", content) - self.assertIn("ctx.event.dataset = ctx['event.dataset'];", content) - self.assertIn("ctx.remove('event.dataset');", content) - self.assertLess(content.find("ctx.event.dataset = ctx['event.dataset'];"), content.find("def shouldDeriveDataset")) - self.assertIn("- dot_expander:", content) - self.assertIn("field: tychon.pipeline.processed", content) - self.assertIn("field: tychon.pipeline.failed", content) - self.assertIn("field: tychon.routing.original.host_ip", content) - self.assertIn("field: tychon.routing.target.ip", content) - self.assertIn("ctx.tychon.certificate_leaf_details = leafDetails;", content) - self.assertNotIn("certificate.leaf", content) - self.assertIn("ctx.tychon.cipher_negotiation = cipherNeg;", content) - self.assertIn("field: x509.issuer.organization", content) - self.assertIn("{{certificate.subject_public_key_info.curve}}", content) - self.assertIn("field: certificate.not_before", content) - self.assertIn("field: certificate.not_after", content) - self.assertIn("field: x509.subject.organization", content) - self.assertIn("field: x509.public_key_curve", content) - self.assertIn("field: destination.address", content) - self.assertIn("field: source.user.id", content) - self.assertIn("field: host.domain", content) - self.assertIn("field: network.protocol", content) - self.assertIn("{{port.protocol_detected}}", content) - self.assertIn("{{tychon.application.protocol_detected}}", content) - self.assertIn("field: error.processor_type", content) - self.assertIn("field: error.processor_tag", content) - self.assertIn("field: error.pipeline", content) - self.assertIn("ctx?.event?.dataset == 'quantum_assessment.app_group'", content) - self.assertIn("costAnalysis.instance_count = 1;", content) - self.assertNotIn("costAnalysis.app_family = costAnalysis.os_upgrade_target;", content) - self.assertNotIn("costAnalysis.tier = costAnalysis.os_tier;", content) - self.assertNotIn("costAnalysis.labor_cost_usd = costAnalysis.os_labor_cost_usd;", content) - self.assertNotIn("costAnalysis.license_cost_usd = costAnalysis.os_license_cost_usd;", content) - self.assertNotIn("costAnalysis.hardware_cost_usd = costAnalysis.os_hardware_cost_usd;", content) - - def test_field_definitions_cover_rehydrated_pipeline_outputs(self): - # type: () -> None - ecs_content = self._read_text(self.ecs_fields_path) - custom_content = self._read_text(self.custom_fields_path) - - self.assertIn("- name: ingested", ecs_content) - self.assertIn("- name: address", ecs_content) - self.assertIn("- name: pipeline", ecs_content) - self.assertIn("- name: processor_tag", ecs_content) - self.assertIn("- name: processor_type", ecs_content) - self.assertIn("- name: ipv4", ecs_content) - self.assertIn("- name: ipv6", ecs_content) - self.assertIn("- name: domain", ecs_content) - self.assertIn("- name: network", ecs_content) - self.assertIn("- name: protocol", ecs_content) - self.assertIn("- name: source", ecs_content) - self.assertIn("- name: id", ecs_content) - - self.assertIn("- name: pipeline", custom_content) - self.assertIn("- name: processed", custom_content) - self.assertIn("- name: failed", custom_content) - self.assertIn("- name: routing", custom_content) - self.assertIn("- name: cipher_negotiation", custom_content) - self.assertIn("- name: crypto_libraries", custom_content) - self.assertIn("- name: public_key_curve", custom_content) - self.assertIn("- name: organization", custom_content) - self.assertIn("- name: not_before", custom_content) - self.assertIn("- name: not_after", custom_content) - self.assertIn("- name: app_family", custom_content) - self.assertIn("- name: tier", custom_content) - self.assertIn("- name: instance_count", custom_content) - self.assertIn("- name: labor_cost_usd", custom_content) - self.assertIn("- name: license_cost_usd", custom_content) - self.assertIn("- name: hardware_cost_usd", custom_content) - - def test_transforms_use_namespace_safe_source_index(self): - # type: () -> None - expected_source_index = "index: logs-tychon_quantum_command.tychon_pqc-*" - - for transform_name in os.listdir(self.transform_dir): - transform_path = os.path.join( - self.transform_dir, - transform_name, - "transform.yml", - ) - - if not os.path.isfile(transform_path): - continue - - content = self._read_text(transform_path) - - self.assertIn( - expected_source_index, - content, - "Transform %s must read from every namespace." % transform_name, - ) - self.assertNotIn( - "index: logs-tychon_quantum_command.tychon_pqc-default", - content, - "Transform %s still hardcodes the default namespace." % transform_name, - ) - - -if __name__ == "__main__": - unittest.main() From 12b6fe730b3ec69f2330b849b3a128243ffcf165 Mon Sep 17 00:00:00 2001 From: Thomas Hatcher Date: Mon, 20 Jul 2026 17:24:27 +0000 Subject: [PATCH 4/6] - replaced hard-coded Data_streams/Transforms/Exported fields blocks in README Template with {{ fields tychon_pqc }} and {{ event tychon_pqc }} - replaced dashboard and supporting objects with those output from 'elastic-package export dashboards' command. --- .../_dev/build/docs/README.md | 913 +----- .../tychon_quantum_command/docs/README.md | 1383 ++++----- ...-4ea4-8458-7c8a8b58987e-cost-analysis.json | 474 ++- ...0d80-4a28-9de7-55b2046f7c45-inventory.json | 638 +++- ...-b0b9-c675dd057e2f-application-report.json | 2663 ++++++++++++++++- ...-9410-7d8c01ff0d9a-application-detail.json | 2344 ++++++++++++++- ...ea1b-application-connections-topology.json | 450 ++- ...3982-certificate-operations-dashboard.json | 741 ++++- ...4e80-9fe2-115c951fe43c-dod-omb-report.json | 247 +- ...d3e40001-certificate-inventory-detail.json | 129 +- ...-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json | 30 +- ...-dacb217e-57b4-4296-8545-cbf6b5739344.json | 30 +- ...-e9b715ba-5f19-4f99-b837-2c1a24143212.json | 30 +- 13 files changed, 7704 insertions(+), 2368 deletions(-) diff --git a/packages/tychon_quantum_command/_dev/build/docs/README.md b/packages/tychon_quantum_command/_dev/build/docs/README.md index b90f70665f4..ac2693d3e7e 100644 --- a/packages/tychon_quantum_command/_dev/build/docs/README.md +++ b/packages/tychon_quantum_command/_dev/build/docs/README.md @@ -188,917 +188,14 @@ The `tychon_pqc` data stream receives TYCHON Quantum Command output files collec This stream can contain multiple TYCHON record families in one place, including inventory, certificates, ciphers, applications, crypto libraries, readiness, keystores, VPN client findings, IPsec tunnel findings, MACsec findings, installed application data, browser extension data, archives, and other supporting scan artifacts. -### Data streams using ILM policies - -This package does not define a custom package-level ILM policy in `docs/README.md`. Apply retention and lifecycle controls according to your deployment standards for both the raw source stream and the transform destination indices. -### Transforms used - -#### applications -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-applications - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| host.hostname | | keyword | -| host.id | | keyword | -| id | Tychon unique document identifier for the application record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.domain | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.os.build | | keyword | -| observer.os.family | | keyword | -| observer.os.kernel | | keyword | -| observer.os.name | | keyword | -| observer.os.platform | | keyword | -| observer.os.version | | keyword | -| observer.software_version | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.application.app_root | | keyword | -| tychon.application.connected_to_count | | long | -| tychon.application.crypto_library_count | | long | -| tychon.application.in_memory_cert_count | | long | -| tychon.application.keychain_identity_count | | long | -| tychon.application.keystore_count | | long | -| tychon.application.name | | keyword | -| tychon.application.path | | keyword | -| tychon.application.pid | | long | -| tychon.application.port_count | | long | -| tychon.application.private_key_count | | long | -| tychon.application.service_display_name | | keyword | -| tychon.application.service_name | | keyword | -| tychon.application.source | | keyword | -| tychon.index | | keyword | -| tychon.library.crypt32_pqc_status | | keyword | -| tychon.library.crypt32_version | | keyword | -| tychon.library.openssl_pqc_status | | keyword | -| tychon.library.openssl_version | | keyword | -| tychon.library.uses_crypt32 | | boolean | -| tychon.library.uses_openssl | | boolean | -| tychon.library.uses_windows_cng | | boolean | -| tychon.library.windows_cng_pqc_status | | keyword | -| tychon.library.windows_cng_version | | keyword | -| tychon.type | | keyword | - -#### archives -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-archives - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| archive.encryption.strength | | keyword | -| archive.encryption.type | | keyword | -| archive.format.version | | keyword | -| archive.type | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the archive record. | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### assets -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-assets - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| config.config_file | | keyword | -| config.property_key | | keyword | -| config.ref_type | | keyword | -| config.resolved_path | | keyword | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| file.name | | keyword | -| file.path | | keyword | -| id | Tychon unique document identifier for the asset record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| process.name | | keyword | -| process.path | | keyword | -| process.pid | | long | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### browser_exts -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-installed-browser-extensions - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the browser extension record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| package.description | | keyword | -| package.name | | keyword | -| package.version | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.browser_extension.browser | | keyword | -| tychon.browser_extension.extension_id | | keyword | -| tychon.browser_extension.permissions | | keyword | -| tychon.browser_extension.profile_path | | keyword | -| tychon.browser_extension.quantum_ready | | boolean | -| tychon.index | | keyword | -| tychon.scan_mode | | keyword | -| tychon.type | | keyword | - -#### certificates -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-certificates - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| certificate.basic_constraints.is_ca | | boolean | -| certificate.basic_constraints.max_path_len | | long | -| certificate.basic_constraints.max_path_len_zero | | boolean | -| certificate.file_details.attributes | | keyword | -| certificate.file_details.extension | | keyword | -| certificate.file_details.group | | keyword | -| certificate.file_details.md5_hash | | keyword | -| certificate.file_details.name | | keyword | -| certificate.file_details.owner | | keyword | -| certificate.file_details.path | | keyword | -| certificate.file_details.sha1_hash | | keyword | -| certificate.file_details.sha256_hash | | keyword | -| certificate.file_details.size | | long | -| certificate.is_csr | | boolean | -| certificate.is_private_key | | boolean | -| certificate.is_self_signed | | boolean | -| certificate.issuer | | keyword | -| certificate.issuer_common_name | | keyword | -| certificate.key_usage | | keyword | -| certificate.not_after | | date | -| certificate.not_before | | date | -| certificate.pqc_vulnerable | | boolean | -| certificate.raw_pem_certificate | | match_only_text | -| certificate.serial_number | | keyword | -| certificate.sha1_fingerprint | | keyword | -| certificate.sha256_fingerprint | | keyword | -| certificate.signature_algorithm | | keyword | -| certificate.source_file_path | | keyword | -| certificate.source_id | | keyword | -| certificate.subject | | keyword | -| certificate.subject_common_name | | keyword | -| certificate.subject_public_key_info.algorithm | | keyword | -| certificate.subject_public_key_info.bit_size | | long | -| certificate.subject_public_key_info.rsa_exponent | | long | -| certificate.subject_public_key_info.rsa_modulus_hex | | wildcard | -| certificate.universal_id | | keyword | -| certificate.validity.duration_days | | keyword | -| certificate.version | | long | -| crypto.key_algorithm | | keyword | -| crypto.key_size | | long | -| crypto.signature_algorithm | | keyword | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| file.extension | | keyword | -| file.group.name | | keyword | -| file.mtime | | date | -| file.name | | keyword | -| file.owner.name | | keyword | -| file.path | | keyword | -| file.permissions | | keyword | -| file.size | | long | -| hash.sha256_certificate | | keyword | -| id | Tychon unique document identifier for the certificate record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| omb.sig_tier | | keyword | -| pqc.vulnerable | | boolean | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | -| x509.is_valid | | boolean | -| x509.issuer.common_name | | keyword | -| x509.issuer.distinguished_name | | keyword | -| x509.public_key_algorithm | | keyword | -| x509.public_key_size | | long | -| x509.serial_number | | keyword | -| x509.signature_algorithm | | keyword | -| x509.subject.common_name | | keyword | -| x509.subject.distinguished_name | | keyword | -| x509.validity.not_after | | date | -| x509.validity.not_before | | date | -| x509.version_number | | long | - -#### ciphers -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-ciphers - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| error.message | | match_only_text | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| hash.sha1_certificate | | keyword | -| hash.sha256_certificate | | keyword | -| id | Tychon unique document identifier for the cipher record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| omb.additional_notes | | wildcard | -| omb.block_cipher_key_lengths | | keyword | -| omb.block_cipher_modes | | keyword | -| omb.block_ciphers | | keyword | -| omb.certifications | | keyword | -| omb.crqc_vulnerable_algos | | keyword | -| omb.dsa_algorithms | | keyword | -| omb.hash_algorithms | | keyword | -| omb.kem_algorithms | | keyword | -| omb.kex_ciphersuites | | keyword | -| omb.kex_protocols | | keyword | -| omb.mac_algorithms | | keyword | -| omb.module_name | | keyword | -| omb.operating_system | | keyword | -| omb.other_crypto_details | | keyword | -| omb.other_protocols | | keyword | -| omb.pqc_algos | | keyword | -| omb.software_package_name | | keyword | -| omb.software_package_version | | keyword | -| omb.symmetric_algos | | keyword | -| omb.vulnerability_status | | keyword | -| port.number | | long | -| port.protocol_detected | | keyword | -| port.status_overall | | keyword | -| process.command_line | | wildcard | -| process.executable | | keyword | -| process.executable_directory | | keyword | -| process.name | | keyword | -| process.pid | | long | -| process.username | | keyword | -| quantum_ready | | boolean | -| quantum_ready_cert | | boolean | -| quantum_ready_cipher | | boolean | -| quantum_ready_kx | | boolean | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| server.address | | keyword | -| server.ip | | ip | -| server.port | | long | -| service.name | | keyword | -| service.state | | keyword | -| target_host.address | | keyword | -| target_host.domain | | keyword | -| target_host.ip | | ip | -| target_host.ipv4 | | ip | -| tychon.cipher.config_source | | keyword | -| tychon.cipher.insecure_ciphers | | keyword | -| tychon.cipher.is_encrypted | | boolean | -| tychon.cipher.migration_priority | | keyword | -| tychon.cipher.port | | long | -| tychon.cipher.pqc_readiness | | keyword | -| tychon.cipher.pqc_vulnerable | | boolean | -| tychon.cipher.protocol | | keyword | -| tychon.cipher.quantum_risk | | keyword | -| tychon.cipher.recommended_action | | keyword | -| tychon.cipher.supported_ciphers | | keyword | -| tychon.crypto.cipher | | keyword | -| tychon.crypto.pqc_readiness | | keyword | -| tychon.crypto.pqc_vulnerable | | boolean | -| tychon.crypto.protocol | | keyword | -| tychon.crypto.quantum_risk | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | -| x509.issuer.common_name | | keyword | -| x509.issuer.distinguished_name | | keyword | -| x509.public_key_algorithm | | keyword | -| x509.public_key_size | | long | -| x509.serial_number | | keyword | -| x509.signature_algorithm | | keyword | -| x509.subject.common_name | | keyword | -| x509.subject.distinguished_name | | keyword | - -#### crypto_libs -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-crypto-libraries - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| id | Tychon unique document identifier for the crypto library record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| process.executable | | keyword | -| process.executable_directory | | keyword | -| process.name | | keyword | -| process.pid | | long | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.library.crypto_type | | keyword | -| tychon.library.name | | keyword | -| tychon.library.openssl_version | | keyword | -| tychon.library.pqc_status | | keyword | -| tychon.library.uses_openssl | | boolean | -| tychon.library.uses_windows_cng | | boolean | -| tychon.library.windows_cng_version | | keyword | -| tychon.type | | keyword | -| vulnerability.assessed_at | | date | -| vulnerability.is_vulnerable | | boolean | -| vulnerability.risk_level | | keyword | -| vulnerability.risk_reason | | keyword | - -#### inst_apps -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-installed-apps - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the installed application record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| package.description | | keyword | -| package.install_directory | | keyword | -| package.name | | keyword | -| package.path | | keyword | -| package.version | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.installed_app.crypto_library_count | | long | -| tychon.scan_mode | | keyword | -| tychon.type | | keyword | - -#### inventory -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-inventory - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| destination.domain | | keyword | -| destination.ip | | ip | -| destination.port | | long | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| host.architecture | | keyword | -| host.hostname | | keyword | -| host.id | | keyword | -| host.ip | | keyword | -| host.os_category | | keyword | -| host.os_pqc_tier | | keyword | -| id | Tychon unique document identifier for the inventory record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.database_schema_version | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.output_schema_version | | keyword | -| observer.tychon_client_id | | keyword | -| observer.type | | keyword | -| observer.vendor | | keyword | -| observer.version | | keyword | -| observer.windows_server_role | | keyword | -| omb.kex_primary | | keyword | -| omb.kex_primary_quantum_safe | | boolean | -| omb.kex_secondary | | keyword | -| omb.kex_tier | | keyword | -| omb.protocol_tier | | keyword | -| omb.sig_tier | | keyword | -| process.command_line | | wildcard | -| process.executable | | keyword | -| process.executable_directory | | keyword | -| process.name | | keyword | -| process.pid | | long | -| process.start | | date | -| process.user_name | | keyword | -| quantum_ready | | boolean | -| quantum_ready_cert | | boolean | -| quantum_ready_cipher | | boolean | -| quantum_ready_kx | | boolean | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| scan_type | | keyword | -| server.port | | long | -| server.protocol | | keyword | -| tls.duration_ms | | long | -| tls.insecure_cipher_count | | long | -| tls.insecure_ciphers | | keyword | -| tls.preferred_cipher | | keyword | -| tls.preferred_key_exchange | | keyword | -| tls.preferred_protocol | | keyword | -| tls.supported_key_exchange_count | | long | -| tls.supported_key_exchanges | | keyword | -| tls.supported_protocol_count | | long | -| tls.supported_protocols | | keyword | -| tls.total_probes | | long | -| tychon.index | | keyword | -| tychon.type | | keyword | -| x509.issuer_cn | | keyword | -| x509.key_bits | | long | -| x509.key_type | | keyword | -| x509.key_usage | | keyword | -| x509.not_after | | date | -| x509.not_before | | date | -| x509.serial_number | | keyword | -| x509.sha256_fingerprint | | keyword | -| x509.sig_algorithm | | keyword | -| x509.subject_cn | | keyword | - -#### ipsec_tnls -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-ipsec-tunnels - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| id | Tychon unique document identifier for the IPSec tunnel record. | keyword | -| ipsec_tunnel.active | | boolean | -| ipsec_tunnel.config_path | | keyword | -| ipsec_tunnel.detection_confidence | | keyword | -| ipsec_tunnel.detection_method | | keyword | -| ipsec_tunnel.first_detected | | date | -| ipsec_tunnel.implementation | | keyword | -| ipsec_tunnel.last_seen | | date | -| ipsec_tunnel.name | | keyword | -| ipsec_tunnel.source_id | | keyword | -| ipsec_tunnel.status | | keyword | -| ipsec_tunnel.version | | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| pqc.is_pqc_ready | | boolean | -| pqc.pqc_migration_status | | keyword | -| pqc.quantum_resistance | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| security.known_vulnerabilities | | keyword | -| security.perfect_forward_secrecy | | boolean | -| security.pqc_support | | boolean | -| security.pqc_vulnerable | | boolean | -| security.risk_level | | keyword | -| security.score | | long | -| security.security_score | | long | -| security.vulnerable | | boolean | -| security.weak_crypto | | boolean | -| security.weak_dh_group | | boolean | -| tunnel_details.auth_method | | keyword | -| tunnel_details.dh_group | | keyword | -| tunnel_details.encryption_algorithm | | keyword | -| tunnel_details.integrity_algorithm | | keyword | -| tunnel_details.mode | | keyword | -| tunnel_details.nat_traversal | | boolean | -| tunnel_details.perfect_forward_secrecy | | boolean | -| tunnel_details.protocol | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### keystores -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-keystores - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| file.name | | keyword | -| file.path | | keyword | -| id | Tychon unique document identifier for the keystore record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| keystore.accessible | | boolean | -| keystore.cert_count | | long | -| keystore.path | | keyword | -| keystore.requires_auth | | boolean | -| keystore.stats.certificate_types.ca | | long | -| keystore.stats.expired_certificates | | long | -| keystore.stats.key_algorithms.ECDSA | | long | -| keystore.stats.key_algorithms.RSA | | long | -| keystore.stats.pqc_vulnerable_certificates | | long | -| keystore.stats.vulnerable_certificates | | long | -| keystore.type | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### macsec -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-macsec - **Exported fields** -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the MACsec record. | keyword | -| macsec.cipher_suite | | keyword | -| macsec.detection_confidence | | keyword | -| macsec.detection_method | | keyword | -| macsec.implementation | | keyword | -| macsec.interface_name | | keyword | -| macsec.key_agreement_method | | keyword | -| macsec.parent_interface | | keyword | -| macsec.risk_level | | keyword | -| macsec.sci | | keyword | -| macsec.status | | keyword | -| macsec.validation_mode | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### readiness -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-system-readiness +{{ fields "tychon_pqc" }} -**Exported fields** +**Example event** -| Field | Description | Type | -|---|---|---| -| @timestamp | Timestamp when the readiness event occurred. | date | -| data_stream.dataset | Data stream dataset of the source event. | constant_keyword | -| data_stream.namespace | Data stream namespace of the source event. | constant_keyword | -| data_stream.type | Data stream type of the source event. | constant_keyword | -| ecs.version | ECS version of the transformed event. | keyword | -| error.message | Error message captured during readiness collection or processing. | match_only_text | -| event.action | Action captured for the readiness event. | keyword | -| event.category | Event category for the readiness event. | keyword | -| event.dataset | Event dataset of the source readiness record. | keyword | -| event.ingested | Timestamp when the event was ingested into Elasticsearch. | date | -| event.kind | Event kind for the readiness record. | keyword | -| id | Tychon unique document identifier for the system readiness record. | keyword | -| kerberos.config_source | Source of Kerberos encryption configuration. | keyword | -| kerberos.has_aes128 | Indicates whether AES128 Kerberos support is enabled. | boolean | -| kerberos.has_aes256 | Indicates whether AES256 Kerberos support is enabled. | boolean | -| kerberos.has_des | Indicates whether DES Kerberos support is enabled. | boolean | -| kerberos.has_rc4 | Indicates whether RC4 Kerberos support is enabled. | boolean | -| kerberos.is_explicitly_configured | Indicates whether Kerberos encryption settings are explicitly configured. | boolean | -| kerberos.is_quantum_safe | Indicates whether the Kerberos configuration is considered post-quantum safe. | boolean | -| kerberos.raw_bitmask | Windows Kerberos encryption type bitmask, when available. | long | -| kerberos.supported_types | Supported Kerberos encryption types as reported by the host. | keyword | -| observer.bigfix_client_installed | Indicates whether a BigFix client is installed on the observer host. | boolean | -| observer.bios_serial_number | BIOS serial number reported by the observer host. | keyword | -| observer.cpu_cores | Number of physical CPU cores reported by the observer host. | long | -| observer.cpu_logical_cores | Number of logical CPU cores reported by the observer host. | long | -| observer.cpu_model_name | CPU model name reported by the observer host. | keyword | -| observer.cpu_vendor_id | CPU vendor identifier reported by the observer host. | keyword | -| observer.current_user | Current user context used by the observer when scanning. | keyword | -| observer.domain | Domain associated with the observer host. | keyword | -| observer.fips_mode_enabled | Indicates whether FIPS mode is enabled on the observer host. | boolean | -| observer.hostname | Hostname of the observer host. | keyword | -| observer.id | Unique observer identifier. | keyword | -| observer.ip_addresses | IP addresses reported by the observer host. | keyword | -| observer.is_vdi_environment | Indicates whether the observer is running in a VDI environment. | boolean | -| observer.kernel_arch | Kernel architecture reported by the observer host. | keyword | -| observer.kernel_version | Kernel version reported by the observer host. | keyword | -| observer.machine_serial_number | Machine serial number reported by the observer host. | keyword | -| observer.organization | Organization associated with the observer host. | keyword | -| observer.os.build | Observer operating system build identifier. | keyword | -| observer.os.family | Observer operating system family. | keyword | -| observer.os.kernel | Observer operating system kernel string. | keyword | -| observer.os.name | Observer operating system name. | keyword | -| observer.os.platform | Observer operating system platform. | keyword | -| observer.os.version | Observer operating system version. | keyword | -| observer.platform_version | Platform-specific version string reported by the observer host. | keyword | -| observer.ram_used_percent | Percent of RAM in use on the observer host. | float | -| observer.software_version | Tychon software version on the observer host. | keyword | -| observer.system_uptime_seconds | System uptime in seconds on the observer host. | long | -| observer.total_ram_bytes | Total RAM bytes on the observer host. | long | -| observer.tychon_client_id | Tychon client identifier reported on Windows endpoints. | keyword | -| observer.user_gid | Current user group identifier on the observer host. | keyword | -| observer.user_home_dir | Home directory of the current user on the observer host. | keyword | -| observer.user_uid | Current user identifier on the observer host. | keyword | -| observer.vdi_identity_source | Source used to determine VDI identity. | keyword | -| observer.windows_server_role | Windows server role or workstation role of the observer host. | keyword | -| quantum_readiness.assessment_duration_ms | Duration of the readiness assessment in milliseconds. | long | -| quantum_readiness.assessment_id | Unique assessment identifier emitted by TQC. | keyword | -| quantum_readiness.assessment_type | Type of readiness assessment performed. | keyword | -| quantum_readiness.compliance.common_criteria | Indicates whether Common Criteria readiness is met. | boolean | -| quantum_readiness.compliance.compliance_notes | Compliance notes reported by the readiness assessment. | wildcard | -| quantum_readiness.compliance.fips_ready | Indicates whether FIPS readiness requirements are met. | boolean | -| quantum_readiness.compliance.nist_ready | Indicates whether NIST readiness requirements are met. | boolean | -| quantum_readiness.cost_analysis.labor_rate_used | Labor rate used for cost analysis. | float | -| quantum_readiness.cost_analysis.os_category | Operating system category used in cost analysis. | keyword | -| quantum_readiness.cost_analysis.os_hardware_cost_usd | Hardware cost for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_labor_cost_usd | Labor cost for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_labor_hours | Labor hours for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_license_cost_usd | License cost for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_tier | Operating system tier classification for cost analysis. | keyword | -| quantum_readiness.cost_analysis.os_total_cost_usd | Total operating system remediation cost. | float | -| quantum_readiness.cost_analysis.os_upgrade_target | Target operating system identified for remediation. | keyword | -| quantum_readiness.cost_analysis.total_cost_usd | Total estimated remediation cost. | float | -| quantum_readiness.cost_analysis.total_hardware_cost_usd | Total estimated hardware cost. | float | -| quantum_readiness.cost_analysis.total_labor_cost_usd | Total estimated labor cost. | float | -| quantum_readiness.cost_analysis.total_labor_hours | Total estimated labor hours. | float | -| quantum_readiness.cost_analysis.total_license_cost_usd | Total estimated license cost. | float | -| quantum_readiness.crypto_libraries.fips_mode | Indicates whether FIPS mode is enabled for system crypto libraries. | boolean | -| quantum_readiness.crypto_libraries.legacy_libraries_present | Indicates whether legacy crypto libraries were detected. | boolean | -| quantum_readiness.crypto_libraries.max_score | Maximum score available for crypto libraries. | long | -| quantum_readiness.crypto_libraries.openssl_max_score | Maximum score assigned to OpenSSL readiness. | long | -| quantum_readiness.crypto_libraries.openssl_score | OpenSSL readiness score. | long | -| quantum_readiness.crypto_libraries.openssl_version | OpenSSL version detected on the system. | keyword | -| quantum_readiness.crypto_libraries.oqs_provider | Indicates whether an OQS provider was detected. | boolean | -| quantum_readiness.crypto_libraries.pqc_support | Indicates whether post-quantum crypto support was detected. | boolean | -| quantum_readiness.crypto_libraries.system_crypto_max_score | Maximum score available for the system crypto stack. | long | -| quantum_readiness.crypto_libraries.system_crypto_score | Score assigned to the system crypto stack. | long | -| quantum_readiness.crypto_libraries.system_libraries | System crypto libraries detected during the assessment. | keyword | -| quantum_readiness.crypto_libraries.total_score | Total crypto library readiness score. | long | -| quantum_readiness.crypto_libraries.uses_openssl | Indicates whether OpenSSL was detected in the system crypto stack. | boolean | -| quantum_readiness.detailed_report | Markdown-formatted detailed readiness report. | match_only_text | -| quantum_readiness.hardware.architecture | Hardware architecture evaluated by the readiness assessment. | keyword | -| quantum_readiness.hardware.available_ram_gb | Available RAM in gigabytes. | float | -| quantum_readiness.hardware.base_frequency_ghz | Base CPU frequency in gigahertz. | float | -| quantum_readiness.hardware.cores | Number of CPU cores evaluated. | long | -| quantum_readiness.hardware.cpu_max_score | Maximum possible CPU score. | long | -| quantum_readiness.hardware.cpu_score | CPU score assigned by the assessment. | long | -| quantum_readiness.hardware.has_aes_ni | Indicates whether AES-NI instructions are available. | boolean | -| quantum_readiness.hardware.has_avx2 | Indicates whether AVX2 instructions are available. | boolean | -| quantum_readiness.hardware.has_hsm | Indicates whether a hardware security module is available. | boolean | -| quantum_readiness.hardware.has_neon | Indicates whether NEON instructions are available. | boolean | -| quantum_readiness.hardware.has_secure_boot | Indicates whether secure boot support is available. | boolean | -| quantum_readiness.hardware.has_tpm | Indicates whether TPM support is available. | boolean | -| quantum_readiness.hardware.instruction_sets | Instruction sets detected on the host. | keyword | -| quantum_readiness.hardware.logical_cores | Number of logical CPU cores evaluated. | long | -| quantum_readiness.hardware.max_score | Maximum hardware score. | long | -| quantum_readiness.hardware.memory_max_score | Maximum memory score. | long | -| quantum_readiness.hardware.memory_score | Memory score assigned by the assessment. | long | -| quantum_readiness.hardware.security_hw_max_score | Maximum security hardware score. | long | -| quantum_readiness.hardware.security_hw_score | Security hardware score assigned by the assessment. | long | -| quantum_readiness.hardware.total_ram_gb | Total RAM in gigabytes. | float | -| quantum_readiness.hardware.total_score | Total hardware readiness score. | long | -| quantum_readiness.hardware.tpm_version | TPM version detected on the host. | keyword | -| quantum_readiness.max_possible_score | Maximum possible score for the readiness assessment. | long | -| quantum_readiness.network.bandwidth_max_score | Maximum bandwidth score. | long | -| quantum_readiness.network.bandwidth_score | Bandwidth score assigned by the assessment. | long | -| quantum_readiness.network.estimated_bandwidth_mbps | Estimated network bandwidth in megabits per second. | long | -| quantum_readiness.network.ipv6_support | Indicates whether IPv6 support is available. | boolean | -| quantum_readiness.network.latency_ms | Estimated network latency in milliseconds. | long | -| quantum_readiness.network.max_score | Maximum network score. | long | -| quantum_readiness.network.modern_cipher_support | Indicates whether modern network ciphers are supported. | boolean | -| quantum_readiness.network.mtu | Network MTU detected during assessment. | long | -| quantum_readiness.network.protocol_max_score | Maximum network protocol score. | long | -| quantum_readiness.network.protocol_score | Network protocol score assigned by the assessment. | long | -| quantum_readiness.network.tls13_capable | Indicates whether TLS 1.3 capability is present. | boolean | -| quantum_readiness.network.total_score | Total network readiness score. | long | -| quantum_readiness.operating_system.build | Operating system build reported by the assessment. | keyword | -| quantum_readiness.operating_system.crypto_api_max_score | Maximum operating system crypto API score. | long | -| quantum_readiness.operating_system.crypto_api_score | Operating system crypto API score assigned by the assessment. | long | -| quantum_readiness.operating_system.crypto_framework | Native crypto framework detected on the operating system. | keyword | -| quantum_readiness.operating_system.family | Operating system family evaluated by the assessment. | keyword | -| quantum_readiness.operating_system.fips_mode_enabled | Indicates whether operating system FIPS mode is enabled. | boolean | -| quantum_readiness.operating_system.kernel_version | Kernel version evaluated by the assessment. | keyword | -| quantum_readiness.operating_system.max_score | Maximum operating system score. | long | -| quantum_readiness.operating_system.modern_crypto_api | Indicates whether a modern crypto API is available. | boolean | -| quantum_readiness.operating_system.native_pqc_support | Indicates whether native post-quantum support is available. | boolean | -| quantum_readiness.operating_system.os_version_max_score | Maximum operating system version score. | long | -| quantum_readiness.operating_system.os_version_score | Operating system version score assigned by the assessment. | long | -| quantum_readiness.operating_system.pqc_framework | Post-quantum framework detected on the operating system. | keyword | -| quantum_readiness.operating_system.symcrypt_present | Indicates whether SymCrypt is present. | boolean | -| quantum_readiness.operating_system.total_score | Total operating system readiness score. | long | -| quantum_readiness.operating_system.version | Operating system version evaluated by the assessment. | keyword | -| quantum_readiness.overall_score | Overall readiness score. | long | -| quantum_readiness.readiness_status | High-level readiness status returned by the assessment. | keyword | -| quantum_readiness.ready_timeline | Estimated timeline to reach readiness. | keyword | -| quantum_readiness.recommendations | Readiness recommendations summarized by TQC. | keyword | -| quantum_readiness.status_color | UI-oriented status color assigned by TQC. | keyword | -| quantum_readiness.system_classification.criticality_level | System criticality level assigned by TQC. | keyword | -| quantum_readiness.system_classification.detection_reason | Reason used to classify the system role and type. | keyword | -| quantum_readiness.system_classification.role | System role assigned by the readiness assessment. | keyword | -| quantum_readiness.system_classification.type | System type assigned by the readiness assessment. | keyword | -| quantum_readiness.timestamp | Native readiness timestamp emitted by TQC. | date | -| quantum_readiness.upgrade_pathway.action | Recommended remediation action. | keyword | -| quantum_readiness.upgrade_pathway.component | Component targeted by the remediation action. | keyword | -| quantum_readiness.upgrade_pathway.description | Description of the recommended remediation step. | keyword | -| quantum_readiness.upgrade_pathway.estimated_time_weeks | Estimated time in weeks for the remediation step. | long | -| quantum_readiness.upgrade_pathway.order | Ordered step number in the upgrade pathway. | long | -| quantum_readiness.upgrade_pathway.priority | Priority assigned to the remediation step. | keyword | -| scan.target_input | Original scan target input supplied to TQC. | keyword | -| scan.timestamp | Timestamp emitted by the scanner for this record. | date | -| scan.type | Scan mode used to collect the readiness record. | keyword | -| tags | Tags preserved on the transformed readiness document. | keyword | -| tychon.index | Tychon dataset discriminator used by the source event. | keyword | -| tychon.type | Tychon record type. | keyword | - -#### vpn_clients -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-vpn-clients +{{ event "tychon_pqc" }} -**Exported fields** +### Data streams using ILM policies -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| file.path | | keyword | -| id | Tychon unique document identifier for the VPN client record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| security.pqc_support | | boolean | -| security.pqc_vulnerable | | boolean | -| security.risk_level | | keyword | -| security.score | | long | -| security.security_score | | long | -| security.vulnerable | | boolean | -| security.weak_crypto | | boolean | -| service.name | | keyword | -| service.state | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | -| vpn_client.active | | boolean | -| vpn_client.config_path | | keyword | -| vpn_client.detection_confidence | | keyword | -| vpn_client.detection_method | | keyword | -| vpn_client.executable_path | | keyword | -| vpn_client.first_detected | | date | -| vpn_client.install_path | | keyword | -| vpn_client.last_seen | | date | -| vpn_client.name | | keyword | -| vpn_client.service_name | | keyword | -| vpn_client.status | | keyword | -| vpn_client.vendor | | keyword | -| vpn_client.version | | keyword | -| vpn_config.auto_reconnect | | boolean | -| vpn_config.config_encrypted | | boolean | -| vpn_config.dns_leak_protection | | boolean | -| vpn_config.ipv6_leak_protection | | boolean | -| vpn_config.kill_switch | | boolean | -| vpn_config.logging_enabled | | boolean | -| vpn_config.split_tunneling | | boolean | +This package does not define a custom package-level ILM policy. Apply retention and lifecycle controls according to your deployment standards for both the raw source stream and the transform destination indices. diff --git a/packages/tychon_quantum_command/docs/README.md b/packages/tychon_quantum_command/docs/README.md index 81f57c3c2ff..3f0bc897bac 100644 --- a/packages/tychon_quantum_command/docs/README.md +++ b/packages/tychon_quantum_command/docs/README.md @@ -189,188 +189,23 @@ The `tychon_pqc` data stream receives TYCHON Quantum Command output files collec This stream can contain multiple TYCHON record families in one place, including inventory, certificates, ciphers, applications, crypto libraries, readiness, keystores, VPN client findings, IPsec tunnel findings, MACsec findings, installed application data, browser extension data, archives, and other supporting scan artifacts. -### Data streams using ILM policies - -This package does not define a custom package-level ILM policy in `docs/README.md`. Apply retention and lifecycle controls according to your deployment standards for both the raw source stream and the transform destination indices. -### Transforms used - -#### applications -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-applications - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| host.hostname | | keyword | -| host.id | | keyword | -| id | Tychon unique document identifier for the application record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.domain | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.os.build | | keyword | -| observer.os.family | | keyword | -| observer.os.kernel | | keyword | -| observer.os.name | | keyword | -| observer.os.platform | | keyword | -| observer.os.version | | keyword | -| observer.software_version | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.application.app_root | | keyword | -| tychon.application.connected_to_count | | long | -| tychon.application.crypto_library_count | | long | -| tychon.application.in_memory_cert_count | | long | -| tychon.application.keychain_identity_count | | long | -| tychon.application.keystore_count | | long | -| tychon.application.name | | keyword | -| tychon.application.path | | keyword | -| tychon.application.pid | | long | -| tychon.application.port_count | | long | -| tychon.application.private_key_count | | long | -| tychon.application.service_display_name | | keyword | -| tychon.application.service_name | | keyword | -| tychon.application.source | | keyword | -| tychon.index | | keyword | -| tychon.library.crypt32_pqc_status | | keyword | -| tychon.library.crypt32_version | | keyword | -| tychon.library.openssl_pqc_status | | keyword | -| tychon.library.openssl_version | | keyword | -| tychon.library.uses_crypt32 | | boolean | -| tychon.library.uses_openssl | | boolean | -| tychon.library.uses_windows_cng | | boolean | -| tychon.library.windows_cng_pqc_status | | keyword | -| tychon.library.windows_cng_version | | keyword | -| tychon.type | | keyword | - -#### archives -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-archives - **Exported fields** -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| archive.encryption.strength | | keyword | -| archive.encryption.type | | keyword | -| archive.format.version | | keyword | -| archive.type | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the archive record. | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### assets -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-assets - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| config.config_file | | keyword | -| config.property_key | | keyword | -| config.ref_type | | keyword | -| config.resolved_path | | keyword | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| file.name | | keyword | -| file.path | | keyword | -| id | Tychon unique document identifier for the asset record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| process.name | | keyword | -| process.path | | keyword | -| process.pid | | long | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### browser_exts -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-installed-browser-extensions - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the browser extension record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| package.description | | keyword | -| package.name | | keyword | -| package.version | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.browser_extension.browser | | keyword | -| tychon.browser_extension.extension_id | | keyword | -| tychon.browser_extension.permissions | | keyword | -| tychon.browser_extension.profile_path | | keyword | -| tychon.browser_extension.quantum_ready | | boolean | -| tychon.index | | keyword | -| tychon.scan_mode | | keyword | -| tychon.type | | keyword | - -#### certificates -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-certificates - **Exported fields** | Field | Description | Type | |---|---|---| | @timestamp | | date | +| certificate.alias | | keyword | +| certificate.authority_key_id | | keyword | | certificate.basic_constraints.is_ca | | boolean | | certificate.basic_constraints.max_path_len | | long | | certificate.basic_constraints.max_path_len_zero | | boolean | +| certificate.chain_complete | | boolean | +| certificate.crl_distribution_points | | keyword | +| certificate.cve_list | | keyword | +| certificate.ext_key_usage | | keyword | +| certificate.extended_key_usage | | keyword | | certificate.file_details.attributes | | keyword | | certificate.file_details.extension | | keyword | | certificate.file_details.group | | keyword | @@ -381,39 +216,92 @@ This package does not define a custom package-level ILM policy in `docs/README.m | certificate.file_details.sha1_hash | | keyword | | certificate.file_details.sha256_hash | | keyword | | certificate.file_details.size | | long | +| certificate.has_private_key | | boolean | +| certificate.is_ca | | boolean | | certificate.is_csr | | boolean | | certificate.is_private_key | | boolean | | certificate.is_self_signed | | boolean | | certificate.issuer | | keyword | | certificate.issuer_common_name | | keyword | +| certificate.issuer_country | | keyword | +| certificate.issuer_locality | | keyword | +| certificate.issuer_organization | | keyword | +| certificate.issuer_organizational_unit | | keyword | +| certificate.issuer_province | | keyword | +| certificate.issuing_certificate_urls | | keyword | +| certificate.key_algorithm | | keyword | +| certificate.key_size | | long | +| certificate.key_strength_assessment | | keyword | | certificate.key_usage | | keyword | +| certificate.migration_priority | | keyword | | certificate.not_after | | date | | certificate.not_before | | date | +| certificate.ocsp_servers | | keyword | +| certificate.policy_identifiers | | keyword | +| certificate.pqc_readiness | | keyword | +| certificate.pqc_reason | | wildcard | | certificate.pqc_vulnerable | | boolean | +| certificate.quantum_risk | | keyword | | certificate.raw_pem_certificate | | match_only_text | +| certificate.recommended_action | | keyword | +| certificate.risk_level | | keyword | +| certificate.risk_reason | | wildcard | | certificate.serial_number | | keyword | | certificate.sha1_fingerprint | | keyword | | certificate.sha256_fingerprint | | keyword | | certificate.signature_algorithm | | keyword | +| certificate.signature_hex | | wildcard | | certificate.source_file_path | | keyword | | certificate.source_id | | keyword | | certificate.subject | | keyword | +| certificate.subject_alternative_names.dns_names | | keyword | +| certificate.subject_alternative_names.email_addresses | | keyword | +| certificate.subject_alternative_names.ip_addresses | | keyword | | certificate.subject_common_name | | keyword | +| certificate.subject_country | | keyword | +| certificate.subject_key_id | | keyword | +| certificate.subject_locality | | keyword | +| certificate.subject_organization | | keyword | +| certificate.subject_organizational_unit | | keyword | +| certificate.subject_province | | keyword | | certificate.subject_public_key_info.algorithm | | keyword | | certificate.subject_public_key_info.bit_size | | long | +| certificate.subject_public_key_info.curve | | keyword | +| certificate.subject_public_key_info.ecdsa_x_hex | | wildcard | +| certificate.subject_public_key_info.ecdsa_y_hex | | wildcard | | certificate.subject_public_key_info.rsa_exponent | | long | | certificate.subject_public_key_info.rsa_modulus_hex | | wildcard | +| certificate.thumbprint | | keyword | | certificate.universal_id | | keyword | | certificate.validity.duration_days | | keyword | | certificate.version | | long | +| certificate.vulnerable | | boolean | +| config.config_file | | keyword | +| config.property_key | | keyword | +| config.ref_type | | keyword | +| config.resolved_path | | keyword | | crypto.key_algorithm | | keyword | | crypto.key_size | | long | | crypto.signature_algorithm | | keyword | +| data_stream.dataset | | constant_keyword | +| data_stream.namespace | | constant_keyword | +| data_stream.type | | constant_keyword | +| destination.address | | keyword | +| destination.domain | | keyword | +| destination.ip | | ip | +| destination.port | | long | +| ecs.version | | keyword | +| error.message | | match_only_text | +| error.pipeline | | keyword | +| error.processor_tag | | keyword | +| error.processor_type | | keyword | | event.action | | keyword | | event.category | | keyword | | event.dataset | | keyword | | event.ingested | | date | | event.kind | | keyword | +| event.original | | match_only_text | +| event.type | | keyword | | file.extension | | keyword | | file.group.name | | keyword | | file.mtime | | date | @@ -422,68 +310,104 @@ This package does not define a custom package-level ILM policy in `docs/README.m | file.path | | keyword | | file.permissions | | keyword | | file.size | | long | -| hash.sha256_certificate | | keyword | -| id | Tychon unique document identifier for the certificate record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| omb.sig_tier | | keyword | -| pqc.vulnerable | | boolean | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | -| x509.is_valid | | boolean | -| x509.issuer.common_name | | keyword | -| x509.issuer.distinguished_name | | keyword | -| x509.public_key_algorithm | | keyword | -| x509.public_key_size | | long | -| x509.serial_number | | keyword | -| x509.signature_algorithm | | keyword | -| x509.subject.common_name | | keyword | -| x509.subject.distinguished_name | | keyword | -| x509.validity.not_after | | date | -| x509.validity.not_before | | date | -| x509.version_number | | long | - -#### ciphers -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-ciphers - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| error.message | | match_only_text | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | | hash.sha1_certificate | | keyword | | hash.sha256_certificate | | keyword | -| id | Tychon unique document identifier for the cipher record. | keyword | +| host.architecture | | keyword | +| host.cpu.cores | | long | +| host.domain | | keyword | +| host.hostname | | keyword | +| host.id | | keyword | +| host.ip | | ip | +| host.ipv4 | | ip | +| host.ipv6 | | ip | +| host.memory.total | | long | +| host.os.family | | keyword | +| host.os.kernel | | keyword | +| host.os.name | | keyword | +| host.os.platform | | keyword | +| host.os.version | | keyword | +| host.os_category | | keyword | +| host.os_pqc_tier | | keyword | +| id | | keyword | +| ipsec_tunnel.active | | boolean | +| ipsec_tunnel.config_path | | keyword | +| ipsec_tunnel.detection_confidence | | keyword | +| ipsec_tunnel.detection_method | | keyword | +| ipsec_tunnel.first_detected | | date | +| ipsec_tunnel.implementation | | keyword | +| ipsec_tunnel.last_seen | | date | +| ipsec_tunnel.name | | keyword | +| ipsec_tunnel.source_id | | keyword | +| ipsec_tunnel.status | | keyword | +| ipsec_tunnel.version | | keyword | | kerberos.config_source | | keyword | | kerberos.has_aes128 | | boolean | | kerberos.has_aes256 | | boolean | | kerberos.has_des | | boolean | | kerberos.has_rc4 | | boolean | +| kerberos.is_explicitly_configured | | boolean | | kerberos.is_quantum_safe | | boolean | | kerberos.raw_bitmask | | long | | kerberos.supported_types | | keyword | +| keystore.accessible | | boolean | +| keystore.cert_count | | long | +| keystore.encryption.iterations | | long | +| keystore.encryption.mac | | keyword | +| keystore.encryption.salt_length | | long | +| keystore.encryption.vulnerable | | boolean | +| keystore.error_message | | keyword | +| keystore.path | | keyword | +| keystore.permissions | | keyword | +| keystore.requires_auth | | boolean | +| keystore.size | | long | +| keystore.stats.certificate_types.ca | | long | +| keystore.stats.certificate_types.end_entity | | long | +| keystore.stats.expired_certificates | | long | +| keystore.stats.key_algorithms.ECDSA | | long | +| keystore.stats.key_algorithms.RSA | | long | +| keystore.stats.pqc_vulnerable_certificates | | long | +| keystore.stats.vulnerable_certificates | | long | +| keystore.type | | keyword | +| network.protocol | | keyword | +| observer.bigfix_client_installed | | boolean | +| observer.bios_serial_number | | keyword | +| observer.cpu_cores | | long | +| observer.cpu_logical_cores | | long | +| observer.cpu_model_name | | keyword | +| observer.cpu_vendor_id | | keyword | +| observer.current_user | | keyword | +| observer.database_schema_version | | keyword | +| observer.domain | | keyword | +| observer.error | | keyword | +| observer.fips_mode_enabled | | boolean | | observer.hostname | | keyword | | observer.id | | keyword | +| observer.ip_addresses | | keyword | +| observer.is_vdi_environment | | boolean | +| observer.kernel_arch | | keyword | +| observer.kernel_version | | keyword | +| observer.machine_serial_number | | keyword | +| observer.organization | | keyword | +| observer.os.build | | keyword | +| observer.os.family | | keyword | +| observer.os.kernel | | keyword | +| observer.os.name | | keyword | +| observer.os.platform | | keyword | +| observer.os.version | | keyword | +| observer.output_schema_version | | keyword | +| observer.platform_version | | keyword | +| observer.ram_used_percent | | float | +| observer.software_version | | keyword | +| observer.system_uptime_seconds | | long | +| observer.total_ram_bytes | | long | | observer.tychon_client_id | | keyword | +| observer.type | | keyword | +| observer.user_gid | | keyword | +| observer.user_home_dir | | keyword | +| observer.user_uid | | keyword | +| observer.vdi_identity_source | | keyword | +| observer.vendor | | keyword | +| observer.version | | keyword | | observer.windows_server_role | | keyword | | omb.additional_notes | | wildcard | | omb.block_cipher_key_lengths | | keyword | @@ -492,29 +416,187 @@ This package does not define a custom package-level ILM policy in `docs/README.m | omb.certifications | | keyword | | omb.crqc_vulnerable_algos | | keyword | | omb.dsa_algorithms | | keyword | +| omb.dsa_hash_algorithms | | keyword | +| omb.dsa_parameters | | keyword | +| omb.hash_algorithm_parameters | | keyword | | omb.hash_algorithms | | keyword | | omb.kem_algorithms | | keyword | +| omb.kem_parameters | | keyword | | omb.kex_ciphersuites | | keyword | +| omb.kex_primary | | keyword | +| omb.kex_primary_quantum_safe | | boolean | | omb.kex_protocols | | keyword | +| omb.kex_secondary | | keyword | +| omb.kex_tier | | keyword | +| omb.mac_algorithm_parameters | | keyword | | omb.mac_algorithms | | keyword | | omb.module_name | | keyword | | omb.operating_system | | keyword | | omb.other_crypto_details | | keyword | | omb.other_protocols | | keyword | +| omb.other_protocols_params | | keyword | | omb.pqc_algos | | keyword | +| omb.protocol_tier | | keyword | +| omb.sig_tier | | keyword | | omb.software_package_name | | keyword | | omb.software_package_version | | keyword | | omb.symmetric_algos | | keyword | +| omb.vendor | | keyword | | omb.vulnerability_status | | keyword | +| package.description | | keyword | +| package.install_directory | | keyword | +| package.name | | keyword | +| package.path | | keyword | +| package.version | | keyword | | port.number | | long | | port.protocol_detected | | keyword | | port.status_overall | | keyword | +| pqc.is_pqc_ready | | boolean | +| pqc.key_strength | | keyword | +| pqc.migration_priority | | keyword | +| pqc.pqc_migration_status | | keyword | +| pqc.quantum_resistance | | keyword | +| pqc.quantum_risk | | keyword | +| pqc.readiness | | keyword | +| pqc.reason | | wildcard | +| pqc.recommended_action | | keyword | +| pqc.vulnerable | | boolean | | process.command_line | | wildcard | | process.executable | | keyword | | process.executable_directory | | keyword | +| process.executable_file.attributes | | keyword | +| process.executable_file.company_name | | keyword | +| process.executable_file.extension | | keyword | +| process.executable_file.file_version | | keyword | +| process.executable_file.group | | keyword | +| process.executable_file.md5_hash | | keyword | +| process.executable_file.name | | keyword | +| process.executable_file.owner | | keyword | +| process.executable_file.path | | keyword | +| process.executable_file.product_name | | keyword | +| process.executable_file.product_version | | keyword | +| process.executable_file.sha1_hash | | keyword | +| process.executable_file.sha256_hash | | keyword | +| process.executable_file.size | | long | +| process.hash.sha256 | | keyword | | process.name | | keyword | +| process.path | | keyword | | process.pid | | long | -| process.username | | keyword | +| process.service_info.description | | keyword | +| process.service_info.display_name | | keyword | +| process.service_info.name | | keyword | +| process.service_info.state | | keyword | +| process.start | | date | +| process.user_name | | keyword | +| process.username | | keyword | +| quantum_readiness.assessment_duration_ms | | long | +| quantum_readiness.assessment_id | | keyword | +| quantum_readiness.assessment_type | | keyword | +| quantum_readiness.compliance.common_criteria | | boolean | +| quantum_readiness.compliance.compliance_notes | | wildcard | +| quantum_readiness.compliance.fips_ready | | boolean | +| quantum_readiness.compliance.nist_ready | | boolean | +| quantum_readiness.cost_analysis.app_family | | keyword | +| quantum_readiness.cost_analysis.hardware_cost_usd | | float | +| quantum_readiness.cost_analysis.instance_count | | long | +| quantum_readiness.cost_analysis.labor_cost_usd | | float | +| quantum_readiness.cost_analysis.labor_rate_used | | float | +| quantum_readiness.cost_analysis.license_cost_usd | | float | +| quantum_readiness.cost_analysis.os_category | | keyword | +| quantum_readiness.cost_analysis.os_hardware_cost_usd | | float | +| quantum_readiness.cost_analysis.os_labor_cost_usd | | float | +| quantum_readiness.cost_analysis.os_labor_hours | | float | +| quantum_readiness.cost_analysis.os_license_cost_usd | | float | +| quantum_readiness.cost_analysis.os_tier | | keyword | +| quantum_readiness.cost_analysis.os_total_cost_usd | | float | +| quantum_readiness.cost_analysis.os_upgrade_target | | keyword | +| quantum_readiness.cost_analysis.tier | | keyword | +| quantum_readiness.cost_analysis.total_cost_usd | | float | +| quantum_readiness.cost_analysis.total_hardware_cost_usd | | float | +| quantum_readiness.cost_analysis.total_labor_cost_usd | | float | +| quantum_readiness.cost_analysis.total_labor_hours | | float | +| quantum_readiness.cost_analysis.total_license_cost_usd | | float | +| quantum_readiness.crypto_libraries.fips_mode | | boolean | +| quantum_readiness.crypto_libraries.legacy_libraries_present | | boolean | +| quantum_readiness.crypto_libraries.max_score | | long | +| quantum_readiness.crypto_libraries.openssl_max_score | | long | +| quantum_readiness.crypto_libraries.openssl_score | | long | +| quantum_readiness.crypto_libraries.openssl_version | | keyword | +| quantum_readiness.crypto_libraries.oqs_provider | | boolean | +| quantum_readiness.crypto_libraries.pqc_support | | boolean | +| quantum_readiness.crypto_libraries.system_crypto_max_score | | long | +| quantum_readiness.crypto_libraries.system_crypto_score | | long | +| quantum_readiness.crypto_libraries.system_libraries | | keyword | +| quantum_readiness.crypto_libraries.total_score | | long | +| quantum_readiness.crypto_libraries.uses_openssl | | boolean | +| quantum_readiness.detailed_report | | match_only_text | +| quantum_readiness.hardware.architecture | | keyword | +| quantum_readiness.hardware.available_ram_gb | | float | +| quantum_readiness.hardware.base_frequency_ghz | | float | +| quantum_readiness.hardware.cores | | long | +| quantum_readiness.hardware.cpu_max_score | | long | +| quantum_readiness.hardware.cpu_score | | long | +| quantum_readiness.hardware.has_aes_ni | | boolean | +| quantum_readiness.hardware.has_avx2 | | boolean | +| quantum_readiness.hardware.has_hsm | | boolean | +| quantum_readiness.hardware.has_neon | | boolean | +| quantum_readiness.hardware.has_secure_boot | | boolean | +| quantum_readiness.hardware.has_tpm | | boolean | +| quantum_readiness.hardware.instruction_sets | | keyword | +| quantum_readiness.hardware.logical_cores | | long | +| quantum_readiness.hardware.max_score | | long | +| quantum_readiness.hardware.memory_max_score | | long | +| quantum_readiness.hardware.memory_score | | long | +| quantum_readiness.hardware.security_hw_max_score | | long | +| quantum_readiness.hardware.security_hw_score | | long | +| quantum_readiness.hardware.total_ram_gb | | float | +| quantum_readiness.hardware.total_score | | long | +| quantum_readiness.hardware.tpm_version | | keyword | +| quantum_readiness.max_possible_score | | long | +| quantum_readiness.network.bandwidth_max_score | | long | +| quantum_readiness.network.bandwidth_score | | long | +| quantum_readiness.network.estimated_bandwidth_mbps | | long | +| quantum_readiness.network.ipv6_support | | boolean | +| quantum_readiness.network.latency_ms | | long | +| quantum_readiness.network.max_score | | long | +| quantum_readiness.network.modern_cipher_support | | boolean | +| quantum_readiness.network.mtu | | long | +| quantum_readiness.network.protocol_max_score | | long | +| quantum_readiness.network.protocol_score | | long | +| quantum_readiness.network.tls13_capable | | boolean | +| quantum_readiness.network.total_score | | long | +| quantum_readiness.operating_system.build | | keyword | +| quantum_readiness.operating_system.crypto_api_max_score | | long | +| quantum_readiness.operating_system.crypto_api_score | | long | +| quantum_readiness.operating_system.crypto_framework | | keyword | +| quantum_readiness.operating_system.family | | keyword | +| quantum_readiness.operating_system.fips_mode_enabled | | boolean | +| quantum_readiness.operating_system.kernel_version | | keyword | +| quantum_readiness.operating_system.max_score | | long | +| quantum_readiness.operating_system.modern_crypto_api | | boolean | +| quantum_readiness.operating_system.native_pqc_support | | boolean | +| quantum_readiness.operating_system.os_version_max_score | | long | +| quantum_readiness.operating_system.os_version_score | | long | +| quantum_readiness.operating_system.pqc_framework | | keyword | +| quantum_readiness.operating_system.symcrypt_present | | boolean | +| quantum_readiness.operating_system.total_score | | long | +| quantum_readiness.operating_system.version | | keyword | +| quantum_readiness.overall_score | | long | +| quantum_readiness.readiness_status | | keyword | +| quantum_readiness.ready_timeline | | keyword | +| quantum_readiness.recommendations | | keyword | +| quantum_readiness.status_color | | keyword | +| quantum_readiness.system_classification.criticality_level | | keyword | +| quantum_readiness.system_classification.detection_reason | | keyword | +| quantum_readiness.system_classification.role | | keyword | +| quantum_readiness.system_classification.type | | keyword | +| quantum_readiness.timestamp | | date | +| quantum_readiness.upgrade_pathway.action | | keyword | +| quantum_readiness.upgrade_pathway.component | | keyword | +| quantum_readiness.upgrade_pathway.description | | keyword | +| quantum_readiness.upgrade_pathway.estimated_time_weeks | | long | +| quantum_readiness.upgrade_pathway.order | | long | +| quantum_readiness.upgrade_pathway.priority | | keyword | | quantum_ready | | boolean | | quantum_ready_cert | | boolean | | quantum_ready_cipher | | boolean | @@ -522,15 +604,188 @@ This package does not define a custom package-level ILM policy in `docs/README.m | scan.target_input | | keyword | | scan.timestamp | | date | | scan.type | | keyword | +| scan_type | | keyword | +| security.known_vulnerabilities | | keyword | +| security.perfect_forward_secrecy | | boolean | +| security.pqc_support | | boolean | +| security.pqc_vulnerable | | boolean | +| security.risk_level | | keyword | +| security.score | | long | +| security.security_score | | long | +| security.vulnerable | | boolean | +| security.weak_crypto | | boolean | +| security.weak_dh_group | | boolean | | server.address | | keyword | | server.ip | | ip | | server.port | | long | +| server.protocol | | keyword | | service.name | | keyword | | service.state | | keyword | +| source.domain | | keyword | +| source.user.id | | keyword | +| ssh.algorithms.client_offered_ciphers | | keyword | +| ssh.algorithms.client_offered_host_key_algos | | keyword | +| ssh.algorithms.client_offered_kex | | keyword | +| ssh.algorithms.client_offered_macs | | keyword | +| ssh.algorithms.negotiated_cipher_c2s | | keyword | +| ssh.algorithms.negotiated_cipher_s2c | | keyword | +| ssh.algorithms.negotiated_host_key_algo | | keyword | +| ssh.algorithms.negotiated_kex | | keyword | +| ssh.algorithms.negotiated_mac_c2s | | keyword | +| ssh.algorithms.negotiated_mac_s2c | | keyword | +| ssh.algorithms.server_offered_ciphers_c2s | | keyword | +| ssh.algorithms.server_offered_ciphers_s2c | | keyword | +| ssh.algorithms.server_offered_host_key_algos | | keyword | +| ssh.algorithms.server_offered_kex | | keyword | +| ssh.algorithms.server_offered_macs_c2s | | keyword | +| ssh.algorithms.server_offered_macs_s2c | | keyword | +| ssh.banner | | keyword | +| ssh.host_key.bits | | long | +| ssh.host_key.fingerprint_sha256 | | keyword | +| ssh.host_key.public_key | | match_only_text | +| ssh.host_key.type | | keyword | +| ssh.host_key.x509_certificate.is_csr | | boolean | +| ssh.host_key.x509_certificate.is_private_key | | boolean | +| ssh.host_key.x509_certificate.is_self_signed | | boolean | +| ssh.host_key.x509_certificate.issuer.common_name | | keyword | +| ssh.host_key.x509_certificate.pqc_vulnerable | | boolean | +| ssh.host_key.x509_certificate.serial_number | | keyword | +| ssh.host_key.x509_certificate.source_file_path | | keyword | +| ssh.host_key.x509_certificate.subject.common_name | | keyword | +| ssh.host_key.x509_certificate.subject_public_key_info.algorithm | | keyword | +| ssh.host_key.x509_certificate.subject_public_key_info.bit_size | | long | +| ssh.server.encryption_ciphers | | keyword | +| ssh.server.host_key_algorithms | | keyword | +| ssh.server.kex_algorithms | | keyword | +| ssh.server.mac_algorithms | | keyword | +| ssh.status | | keyword | | target_host.address | | keyword | | target_host.domain | | keyword | | target_host.ip | | ip | | target_host.ipv4 | | ip | +| tls.certificate.extended_key_usage | | keyword | +| tls.certificate.issuer | | keyword | +| tls.certificate.not_after | | date | +| tls.certificate.not_before | | date | +| tls.certificate.serial_number | | keyword | +| tls.certificate.subject | | keyword | +| tls.duration_ms | | long | +| tls.insecure_cipher_count | | long | +| tls.insecure_ciphers | | keyword | +| tls.preferred_cipher | | keyword | +| tls.preferred_key_exchange | | keyword | +| tls.preferred_protocol | | keyword | +| tls.server.cipher_count | | long | +| tls.server.hash.sha1 | | keyword | +| tls.server.issuer | | keyword | +| tls.server.not_after | | date | +| tls.server.not_before | | date | +| tls.server.serial_number | | keyword | +| tls.server.subject | | keyword | +| tls.server.supported_ciphers | | keyword | +| tls.server.supported_protocols | | keyword | +| tls.supported_cipher_count | | long | +| tls.supported_ciphers | | keyword | +| tls.supported_key_exchange_count | | long | +| tls.supported_key_exchanges | | keyword | +| tls.supported_protocol_count | | long | +| tls.supported_protocols | | keyword | +| tls.total_probes | | long | +| tls.weak_cipher_count | | long | +| tls.weak_ciphers | | keyword | +| tunnel_details.auth_method | | keyword | +| tunnel_details.dh_group | | keyword | +| tunnel_details.encryption_algorithm | | keyword | +| tunnel_details.integrity_algorithm | | keyword | +| tunnel_details.mode | | keyword | +| tunnel_details.nat_traversal | | boolean | +| tunnel_details.perfect_forward_secrecy | | boolean | +| tunnel_details.protocol | | keyword | +| tychon.application.app_root | | keyword | +| tychon.application.company_name | | keyword | +| tychon.application.connected_to_count | | long | +| tychon.application.crypto_library_count | | long | +| tychon.application.file_version | | keyword | +| tychon.application.in_memory_cert_count | | long | +| tychon.application.insecure_ciphers | | keyword | +| tychon.application.keychain_identity_count | | long | +| tychon.application.keystore_count | | long | +| tychon.application.name | | keyword | +| tychon.application.path | | keyword | +| tychon.application.pid | | long | +| tychon.application.port | | long | +| tychon.application.port_count | | long | +| tychon.application.port_quantum_grade.grade | | keyword | +| tychon.application.port_quantum_grade.score | | float | +| tychon.application.preferred_cipher | | keyword | +| tychon.application.preferred_key_exchange | | keyword | +| tychon.application.preferred_protocol | | keyword | +| tychon.application.private_key_count | | long | +| tychon.application.product_name | | keyword | +| tychon.application.product_version | | keyword | +| tychon.application.protocol_detected | | keyword | +| tychon.application.quantum_grade.best_port_score | | float | +| tychon.application.quantum_grade.grade | | keyword | +| tychon.application.quantum_grade.os_deductions | | float | +| tychon.application.quantum_grade.score | | float | +| tychon.application.quantum_grade.worst_port_score | | float | +| tychon.application.quantum_ready | | boolean | +| tychon.application.service_display_name | | keyword | +| tychon.application.service_name | | keyword | +| tychon.application.software_package_names | | keyword | +| tychon.application.software_package_versions | | keyword | +| tychon.application.source | | keyword | +| tychon.application.supported_cipher_suites | | keyword | +| tychon.application.supported_key_exchanges | | keyword | +| tychon.application.supported_protocols | | keyword | +| tychon.application.weak_ciphers | | keyword | +| tychon.asset_type | | keyword | +| tychon.browser_extension.browser | | keyword | +| tychon.browser_extension.extension_id | | keyword | +| tychon.browser_extension.permissions | | keyword | +| tychon.browser_extension.profile_path | | keyword | +| tychon.browser_extension.quantum_ready | | boolean | +| tychon.certificate_leaf_details.basic_constraints.is_ca | | boolean | +| tychon.certificate_leaf_details.basic_constraints.max_path_len_zero | | boolean | +| tychon.certificate_leaf_details.extended_key_usage | | keyword | +| tychon.certificate_leaf_details.is_csr | | boolean | +| tychon.certificate_leaf_details.is_private_key | | boolean | +| tychon.certificate_leaf_details.is_self_signed | | boolean | +| tychon.certificate_leaf_details.issuer.common_name | | keyword | +| tychon.certificate_leaf_details.issuer.country | | keyword | +| tychon.certificate_leaf_details.issuer.locality | | keyword | +| tychon.certificate_leaf_details.issuer.organization | | keyword | +| tychon.certificate_leaf_details.issuer.organizational_unit | | keyword | +| tychon.certificate_leaf_details.issuer.province | | keyword | +| tychon.certificate_leaf_details.issuer.raw_string | | keyword | +| tychon.certificate_leaf_details.key_usage | | keyword | +| tychon.certificate_leaf_details.pqc_vulnerable | | boolean | +| tychon.certificate_leaf_details.raw_pem_certificate | | match_only_text | +| tychon.certificate_leaf_details.serial_number | | keyword | +| tychon.certificate_leaf_details.sha1_fingerprint | | keyword | +| tychon.certificate_leaf_details.sha256_fingerprint | | keyword | +| tychon.certificate_leaf_details.signature_algorithm | | keyword | +| tychon.certificate_leaf_details.signature_hex | | wildcard | +| tychon.certificate_leaf_details.source_id | | keyword | +| tychon.certificate_leaf_details.subject.common_name | | keyword | +| tychon.certificate_leaf_details.subject.country | | keyword | +| tychon.certificate_leaf_details.subject.locality | | keyword | +| tychon.certificate_leaf_details.subject.organization | | keyword | +| tychon.certificate_leaf_details.subject.organizational_unit | | keyword | +| tychon.certificate_leaf_details.subject.province | | keyword | +| tychon.certificate_leaf_details.subject.raw_string | | keyword | +| tychon.certificate_leaf_details.subject_key_id | | keyword | +| tychon.certificate_leaf_details.subject_public_key_info.algorithm | | keyword | +| tychon.certificate_leaf_details.subject_public_key_info.bit_size | | long | +| tychon.certificate_leaf_details.subject_public_key_info.curve | | keyword | +| tychon.certificate_leaf_details.subject_public_key_info.ecdsa_x_hex | | wildcard | +| tychon.certificate_leaf_details.subject_public_key_info.ecdsa_y_hex | | wildcard | +| tychon.certificate_leaf_details.subject_public_key_info.rsa_exponent | | long | +| tychon.certificate_leaf_details.subject_public_key_info.rsa_modulus_hex | | wildcard | +| tychon.certificate_leaf_details.validity.duration_days | | keyword | +| tychon.certificate_leaf_details.validity.not_after | | date | +| tychon.certificate_leaf_details.validity.not_before | | date | +| tychon.certificate_leaf_details.version | | long | | tychon.cipher.config_source | | keyword | | tychon.cipher.insecure_ciphers | | keyword | | tychon.cipher.is_encrypted | | boolean | @@ -542,546 +797,92 @@ This package does not define a custom package-level ILM policy in `docs/README.m | tychon.cipher.quantum_risk | | keyword | | tychon.cipher.recommended_action | | keyword | | tychon.cipher.supported_ciphers | | keyword | +| tychon.cipher_negotiation.active | | boolean | +| tychon.cipher_negotiation.alpn_protocol | | keyword | +| tychon.cipher_negotiation.cipher_suite | | keyword | +| tychon.cipher_negotiation.compression_method | | keyword | +| tychon.cipher_negotiation.intel.vulnerabilities | | keyword | +| tychon.cipher_negotiation.is_preferred | | boolean | +| tychon.cipher_negotiation.key_length_bits | | long | +| tychon.cipher_negotiation.last_seen | | date | +| tychon.cipher_negotiation.protocol | | keyword | +| tychon.cipher_negotiation.session_id | | keyword | +| tychon.cipher_negotiation.session_ticket_lifetime_hint_seconds | | long | +| tychon.cipher_negotiation.source | | keyword | +| tychon.cipher_negotiation.source_id | | keyword | +| tychon.cipher_negotiation.universal_id | | keyword | +| tychon.cipher_quick.duration_ms | | long | +| tychon.cipher_quick.insecure_cipher_count | | long | +| tychon.cipher_quick.insecure_ciphers | | keyword | +| tychon.cipher_quick.preferred_cipher | | keyword | +| tychon.cipher_quick.preferred_key_exchange | | keyword | +| tychon.cipher_quick.preferred_protocol | | keyword | +| tychon.cipher_quick.supported_cipher_count | | long | +| tychon.cipher_quick.supported_cipher_suites | | keyword | +| tychon.cipher_quick.supported_key_exchange_count | | long | +| tychon.cipher_quick.supported_key_exchanges | | keyword | +| tychon.cipher_quick.supported_protocol_count | | long | +| tychon.cipher_quick.supported_protocols | | keyword | +| tychon.cipher_quick.total_probes | | long | +| tychon.cipher_quick.weak_cipher_count | | long | +| tychon.cipher_quick.weak_ciphers | | keyword | +| tychon.crypto.auth | | keyword | +| tychon.crypto.certificate | | keyword | | tychon.crypto.cipher | | keyword | +| tychon.crypto.grade | | keyword | +| tychon.crypto.grade_score | | float | +| tychon.crypto.key_exchange | | keyword | +| tychon.crypto.mac | | keyword | | tychon.crypto.pqc_readiness | | keyword | | tychon.crypto.pqc_vulnerable | | boolean | | tychon.crypto.protocol | | keyword | +| tychon.crypto.protocol_version | | keyword | | tychon.crypto.quantum_risk | | keyword | | tychon.index | | keyword | -| tychon.type | | keyword | -| x509.issuer.common_name | | keyword | -| x509.issuer.distinguished_name | | keyword | -| x509.public_key_algorithm | | keyword | -| x509.public_key_size | | long | -| x509.serial_number | | keyword | -| x509.signature_algorithm | | keyword | -| x509.subject.common_name | | keyword | -| x509.subject.distinguished_name | | keyword | - -#### crypto_libs -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-crypto-libraries - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| id | Tychon unique document identifier for the crypto library record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| process.executable | | keyword | -| process.executable_directory | | keyword | -| process.name | | keyword | -| process.pid | | long | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | +| tychon.installed_app.crypto_libraries | | keyword | +| tychon.installed_app.crypto_library_count | | long | +| tychon.library.crypt32_pqc_status | | keyword | +| tychon.library.crypt32_version | | keyword | | tychon.library.crypto_type | | keyword | +| tychon.library.gnutls_pqc_status | | keyword | +| tychon.library.gnutls_version | | keyword | | tychon.library.name | | keyword | +| tychon.library.nss_pqc_status | | keyword | +| tychon.library.openssl_pqc_status | | keyword | | tychon.library.openssl_version | | keyword | +| tychon.library.pqc_algorithms | | keyword | | tychon.library.pqc_status | | keyword | +| tychon.library.schannel_pqc_status | | keyword | +| tychon.library.schannel_version | | keyword | +| tychon.library.uses_crypt32 | | boolean | +| tychon.library.uses_gnutls | | boolean | +| tychon.library.uses_nss | | boolean | | tychon.library.uses_openssl | | boolean | +| tychon.library.uses_schannel | | boolean | | tychon.library.uses_windows_cng | | boolean | +| tychon.library.windows_cng_pqc_status | | keyword | | tychon.library.windows_cng_version | | keyword | -| tychon.type | | keyword | -| vulnerability.assessed_at | | date | -| vulnerability.is_vulnerable | | boolean | -| vulnerability.risk_level | | keyword | -| vulnerability.risk_reason | | keyword | - -#### inst_apps -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-installed-apps - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the installed application record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| package.description | | keyword | -| package.install_directory | | keyword | -| package.name | | keyword | -| package.path | | keyword | -| package.version | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.installed_app.crypto_library_count | | long | +| tychon.migration_priority | | keyword | +| tychon.pipeline.failed | | boolean | +| tychon.pipeline.processed | | boolean | +| tychon.pqc_readiness | | keyword | +| tychon.quantum_risk | | keyword | +| tychon.routing.original.host_architecture | | keyword | +| tychon.routing.original.host_hostname | | keyword | +| tychon.routing.original.host_id | | keyword | +| tychon.routing.original.host_ip | | ip | +| tychon.routing.original.host_ipv4 | | ip | +| tychon.routing.original.host_ipv6 | | ip | +| tychon.routing.original.host_os_family | | keyword | +| tychon.routing.original.host_os_name | | keyword | +| tychon.routing.original.host_os_platform | | keyword | +| tychon.routing.original.host_os_version | | keyword | +| tychon.routing.source.hostname | | keyword | +| tychon.routing.source.observer_id | | keyword | +| tychon.routing.target.address | | keyword | +| tychon.routing.target.ip | | ip | | tychon.scan_mode | | keyword | -| tychon.type | | keyword | - -#### inventory -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-inventory - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| destination.domain | | keyword | -| destination.ip | | ip | -| destination.port | | long | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| host.architecture | | keyword | -| host.hostname | | keyword | -| host.id | | keyword | -| host.ip | | keyword | -| host.os_category | | keyword | -| host.os_pqc_tier | | keyword | -| id | Tychon unique document identifier for the inventory record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.database_schema_version | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.output_schema_version | | keyword | -| observer.tychon_client_id | | keyword | -| observer.type | | keyword | -| observer.vendor | | keyword | -| observer.version | | keyword | -| observer.windows_server_role | | keyword | -| omb.kex_primary | | keyword | -| omb.kex_primary_quantum_safe | | boolean | -| omb.kex_secondary | | keyword | -| omb.kex_tier | | keyword | -| omb.protocol_tier | | keyword | -| omb.sig_tier | | keyword | -| process.command_line | | wildcard | -| process.executable | | keyword | -| process.executable_directory | | keyword | -| process.name | | keyword | -| process.pid | | long | -| process.start | | date | -| process.user_name | | keyword | -| quantum_ready | | boolean | -| quantum_ready_cert | | boolean | -| quantum_ready_cipher | | boolean | -| quantum_ready_kx | | boolean | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| scan_type | | keyword | -| server.port | | long | -| server.protocol | | keyword | -| tls.duration_ms | | long | -| tls.insecure_cipher_count | | long | -| tls.insecure_ciphers | | keyword | -| tls.preferred_cipher | | keyword | -| tls.preferred_key_exchange | | keyword | -| tls.preferred_protocol | | keyword | -| tls.supported_key_exchange_count | | long | -| tls.supported_key_exchanges | | keyword | -| tls.supported_protocol_count | | long | -| tls.supported_protocols | | keyword | -| tls.total_probes | | long | -| tychon.index | | keyword | -| tychon.type | | keyword | -| x509.issuer_cn | | keyword | -| x509.key_bits | | long | -| x509.key_type | | keyword | -| x509.key_usage | | keyword | -| x509.not_after | | date | -| x509.not_before | | date | -| x509.serial_number | | keyword | -| x509.sha256_fingerprint | | keyword | -| x509.sig_algorithm | | keyword | -| x509.subject_cn | | keyword | - -#### ipsec_tnls -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-ipsec-tunnels - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| id | Tychon unique document identifier for the IPSec tunnel record. | keyword | -| ipsec_tunnel.active | | boolean | -| ipsec_tunnel.config_path | | keyword | -| ipsec_tunnel.detection_confidence | | keyword | -| ipsec_tunnel.detection_method | | keyword | -| ipsec_tunnel.first_detected | | date | -| ipsec_tunnel.implementation | | keyword | -| ipsec_tunnel.last_seen | | date | -| ipsec_tunnel.name | | keyword | -| ipsec_tunnel.source_id | | keyword | -| ipsec_tunnel.status | | keyword | -| ipsec_tunnel.version | | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| pqc.is_pqc_ready | | boolean | -| pqc.pqc_migration_status | | keyword | -| pqc.quantum_resistance | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| security.known_vulnerabilities | | keyword | -| security.perfect_forward_secrecy | | boolean | -| security.pqc_support | | boolean | -| security.pqc_vulnerable | | boolean | -| security.risk_level | | keyword | -| security.score | | long | -| security.security_score | | long | -| security.vulnerable | | boolean | -| security.weak_crypto | | boolean | -| security.weak_dh_group | | boolean | -| tunnel_details.auth_method | | keyword | -| tunnel_details.dh_group | | keyword | -| tunnel_details.encryption_algorithm | | keyword | -| tunnel_details.integrity_algorithm | | keyword | -| tunnel_details.mode | | keyword | -| tunnel_details.nat_traversal | | boolean | -| tunnel_details.perfect_forward_secrecy | | boolean | -| tunnel_details.protocol | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### keystores -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-keystores - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| file.name | | keyword | -| file.path | | keyword | -| id | Tychon unique document identifier for the keystore record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| keystore.accessible | | boolean | -| keystore.cert_count | | long | -| keystore.path | | keyword | -| keystore.requires_auth | | boolean | -| keystore.stats.certificate_types.ca | | long | -| keystore.stats.expired_certificates | | long | -| keystore.stats.key_algorithms.ECDSA | | long | -| keystore.stats.key_algorithms.RSA | | long | -| keystore.stats.pqc_vulnerable_certificates | | long | -| keystore.stats.vulnerable_certificates | | long | -| keystore.type | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### macsec -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-macsec - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.dataset | | keyword | -| event.ingested | | date | -| id | Tychon unique document identifier for the MACsec record. | keyword | -| macsec.cipher_suite | | keyword | -| macsec.detection_confidence | | keyword | -| macsec.detection_method | | keyword | -| macsec.implementation | | keyword | -| macsec.interface_name | | keyword | -| macsec.key_agreement_method | | keyword | -| macsec.parent_interface | | keyword | -| macsec.risk_level | | keyword | -| macsec.sci | | keyword | -| macsec.status | | keyword | -| macsec.validation_mode | | keyword | -| tychon.index | | keyword | -| tychon.type | | keyword | - -#### readiness -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-system-readiness - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | Timestamp when the readiness event occurred. | date | -| data_stream.dataset | Data stream dataset of the source event. | constant_keyword | -| data_stream.namespace | Data stream namespace of the source event. | constant_keyword | -| data_stream.type | Data stream type of the source event. | constant_keyword | -| ecs.version | ECS version of the transformed event. | keyword | -| error.message | Error message captured during readiness collection or processing. | match_only_text | -| event.action | Action captured for the readiness event. | keyword | -| event.category | Event category for the readiness event. | keyword | -| event.dataset | Event dataset of the source readiness record. | keyword | -| event.ingested | Timestamp when the event was ingested into Elasticsearch. | date | -| event.kind | Event kind for the readiness record. | keyword | -| id | Tychon unique document identifier for the system readiness record. | keyword | -| kerberos.config_source | Source of Kerberos encryption configuration. | keyword | -| kerberos.has_aes128 | Indicates whether AES128 Kerberos support is enabled. | boolean | -| kerberos.has_aes256 | Indicates whether AES256 Kerberos support is enabled. | boolean | -| kerberos.has_des | Indicates whether DES Kerberos support is enabled. | boolean | -| kerberos.has_rc4 | Indicates whether RC4 Kerberos support is enabled. | boolean | -| kerberos.is_explicitly_configured | Indicates whether Kerberos encryption settings are explicitly configured. | boolean | -| kerberos.is_quantum_safe | Indicates whether the Kerberos configuration is considered post-quantum safe. | boolean | -| kerberos.raw_bitmask | Windows Kerberos encryption type bitmask, when available. | long | -| kerberos.supported_types | Supported Kerberos encryption types as reported by the host. | keyword | -| observer.bigfix_client_installed | Indicates whether a BigFix client is installed on the observer host. | boolean | -| observer.bios_serial_number | BIOS serial number reported by the observer host. | keyword | -| observer.cpu_cores | Number of physical CPU cores reported by the observer host. | long | -| observer.cpu_logical_cores | Number of logical CPU cores reported by the observer host. | long | -| observer.cpu_model_name | CPU model name reported by the observer host. | keyword | -| observer.cpu_vendor_id | CPU vendor identifier reported by the observer host. | keyword | -| observer.current_user | Current user context used by the observer when scanning. | keyword | -| observer.domain | Domain associated with the observer host. | keyword | -| observer.fips_mode_enabled | Indicates whether FIPS mode is enabled on the observer host. | boolean | -| observer.hostname | Hostname of the observer host. | keyword | -| observer.id | Unique observer identifier. | keyword | -| observer.ip_addresses | IP addresses reported by the observer host. | keyword | -| observer.is_vdi_environment | Indicates whether the observer is running in a VDI environment. | boolean | -| observer.kernel_arch | Kernel architecture reported by the observer host. | keyword | -| observer.kernel_version | Kernel version reported by the observer host. | keyword | -| observer.machine_serial_number | Machine serial number reported by the observer host. | keyword | -| observer.organization | Organization associated with the observer host. | keyword | -| observer.os.build | Observer operating system build identifier. | keyword | -| observer.os.family | Observer operating system family. | keyword | -| observer.os.kernel | Observer operating system kernel string. | keyword | -| observer.os.name | Observer operating system name. | keyword | -| observer.os.platform | Observer operating system platform. | keyword | -| observer.os.version | Observer operating system version. | keyword | -| observer.platform_version | Platform-specific version string reported by the observer host. | keyword | -| observer.ram_used_percent | Percent of RAM in use on the observer host. | float | -| observer.software_version | Tychon software version on the observer host. | keyword | -| observer.system_uptime_seconds | System uptime in seconds on the observer host. | long | -| observer.total_ram_bytes | Total RAM bytes on the observer host. | long | -| observer.tychon_client_id | Tychon client identifier reported on Windows endpoints. | keyword | -| observer.user_gid | Current user group identifier on the observer host. | keyword | -| observer.user_home_dir | Home directory of the current user on the observer host. | keyword | -| observer.user_uid | Current user identifier on the observer host. | keyword | -| observer.vdi_identity_source | Source used to determine VDI identity. | keyword | -| observer.windows_server_role | Windows server role or workstation role of the observer host. | keyword | -| quantum_readiness.assessment_duration_ms | Duration of the readiness assessment in milliseconds. | long | -| quantum_readiness.assessment_id | Unique assessment identifier emitted by TQC. | keyword | -| quantum_readiness.assessment_type | Type of readiness assessment performed. | keyword | -| quantum_readiness.compliance.common_criteria | Indicates whether Common Criteria readiness is met. | boolean | -| quantum_readiness.compliance.compliance_notes | Compliance notes reported by the readiness assessment. | wildcard | -| quantum_readiness.compliance.fips_ready | Indicates whether FIPS readiness requirements are met. | boolean | -| quantum_readiness.compliance.nist_ready | Indicates whether NIST readiness requirements are met. | boolean | -| quantum_readiness.cost_analysis.labor_rate_used | Labor rate used for cost analysis. | float | -| quantum_readiness.cost_analysis.os_category | Operating system category used in cost analysis. | keyword | -| quantum_readiness.cost_analysis.os_hardware_cost_usd | Hardware cost for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_labor_cost_usd | Labor cost for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_labor_hours | Labor hours for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_license_cost_usd | License cost for the operating system upgrade path. | float | -| quantum_readiness.cost_analysis.os_tier | Operating system tier classification for cost analysis. | keyword | -| quantum_readiness.cost_analysis.os_total_cost_usd | Total operating system remediation cost. | float | -| quantum_readiness.cost_analysis.os_upgrade_target | Target operating system identified for remediation. | keyword | -| quantum_readiness.cost_analysis.total_cost_usd | Total estimated remediation cost. | float | -| quantum_readiness.cost_analysis.total_hardware_cost_usd | Total estimated hardware cost. | float | -| quantum_readiness.cost_analysis.total_labor_cost_usd | Total estimated labor cost. | float | -| quantum_readiness.cost_analysis.total_labor_hours | Total estimated labor hours. | float | -| quantum_readiness.cost_analysis.total_license_cost_usd | Total estimated license cost. | float | -| quantum_readiness.crypto_libraries.fips_mode | Indicates whether FIPS mode is enabled for system crypto libraries. | boolean | -| quantum_readiness.crypto_libraries.legacy_libraries_present | Indicates whether legacy crypto libraries were detected. | boolean | -| quantum_readiness.crypto_libraries.max_score | Maximum score available for crypto libraries. | long | -| quantum_readiness.crypto_libraries.openssl_max_score | Maximum score assigned to OpenSSL readiness. | long | -| quantum_readiness.crypto_libraries.openssl_score | OpenSSL readiness score. | long | -| quantum_readiness.crypto_libraries.openssl_version | OpenSSL version detected on the system. | keyword | -| quantum_readiness.crypto_libraries.oqs_provider | Indicates whether an OQS provider was detected. | boolean | -| quantum_readiness.crypto_libraries.pqc_support | Indicates whether post-quantum crypto support was detected. | boolean | -| quantum_readiness.crypto_libraries.system_crypto_max_score | Maximum score available for the system crypto stack. | long | -| quantum_readiness.crypto_libraries.system_crypto_score | Score assigned to the system crypto stack. | long | -| quantum_readiness.crypto_libraries.system_libraries | System crypto libraries detected during the assessment. | keyword | -| quantum_readiness.crypto_libraries.total_score | Total crypto library readiness score. | long | -| quantum_readiness.crypto_libraries.uses_openssl | Indicates whether OpenSSL was detected in the system crypto stack. | boolean | -| quantum_readiness.detailed_report | Markdown-formatted detailed readiness report. | match_only_text | -| quantum_readiness.hardware.architecture | Hardware architecture evaluated by the readiness assessment. | keyword | -| quantum_readiness.hardware.available_ram_gb | Available RAM in gigabytes. | float | -| quantum_readiness.hardware.base_frequency_ghz | Base CPU frequency in gigahertz. | float | -| quantum_readiness.hardware.cores | Number of CPU cores evaluated. | long | -| quantum_readiness.hardware.cpu_max_score | Maximum possible CPU score. | long | -| quantum_readiness.hardware.cpu_score | CPU score assigned by the assessment. | long | -| quantum_readiness.hardware.has_aes_ni | Indicates whether AES-NI instructions are available. | boolean | -| quantum_readiness.hardware.has_avx2 | Indicates whether AVX2 instructions are available. | boolean | -| quantum_readiness.hardware.has_hsm | Indicates whether a hardware security module is available. | boolean | -| quantum_readiness.hardware.has_neon | Indicates whether NEON instructions are available. | boolean | -| quantum_readiness.hardware.has_secure_boot | Indicates whether secure boot support is available. | boolean | -| quantum_readiness.hardware.has_tpm | Indicates whether TPM support is available. | boolean | -| quantum_readiness.hardware.instruction_sets | Instruction sets detected on the host. | keyword | -| quantum_readiness.hardware.logical_cores | Number of logical CPU cores evaluated. | long | -| quantum_readiness.hardware.max_score | Maximum hardware score. | long | -| quantum_readiness.hardware.memory_max_score | Maximum memory score. | long | -| quantum_readiness.hardware.memory_score | Memory score assigned by the assessment. | long | -| quantum_readiness.hardware.security_hw_max_score | Maximum security hardware score. | long | -| quantum_readiness.hardware.security_hw_score | Security hardware score assigned by the assessment. | long | -| quantum_readiness.hardware.total_ram_gb | Total RAM in gigabytes. | float | -| quantum_readiness.hardware.total_score | Total hardware readiness score. | long | -| quantum_readiness.hardware.tpm_version | TPM version detected on the host. | keyword | -| quantum_readiness.max_possible_score | Maximum possible score for the readiness assessment. | long | -| quantum_readiness.network.bandwidth_max_score | Maximum bandwidth score. | long | -| quantum_readiness.network.bandwidth_score | Bandwidth score assigned by the assessment. | long | -| quantum_readiness.network.estimated_bandwidth_mbps | Estimated network bandwidth in megabits per second. | long | -| quantum_readiness.network.ipv6_support | Indicates whether IPv6 support is available. | boolean | -| quantum_readiness.network.latency_ms | Estimated network latency in milliseconds. | long | -| quantum_readiness.network.max_score | Maximum network score. | long | -| quantum_readiness.network.modern_cipher_support | Indicates whether modern network ciphers are supported. | boolean | -| quantum_readiness.network.mtu | Network MTU detected during assessment. | long | -| quantum_readiness.network.protocol_max_score | Maximum network protocol score. | long | -| quantum_readiness.network.protocol_score | Network protocol score assigned by the assessment. | long | -| quantum_readiness.network.tls13_capable | Indicates whether TLS 1.3 capability is present. | boolean | -| quantum_readiness.network.total_score | Total network readiness score. | long | -| quantum_readiness.operating_system.build | Operating system build reported by the assessment. | keyword | -| quantum_readiness.operating_system.crypto_api_max_score | Maximum operating system crypto API score. | long | -| quantum_readiness.operating_system.crypto_api_score | Operating system crypto API score assigned by the assessment. | long | -| quantum_readiness.operating_system.crypto_framework | Native crypto framework detected on the operating system. | keyword | -| quantum_readiness.operating_system.family | Operating system family evaluated by the assessment. | keyword | -| quantum_readiness.operating_system.fips_mode_enabled | Indicates whether operating system FIPS mode is enabled. | boolean | -| quantum_readiness.operating_system.kernel_version | Kernel version evaluated by the assessment. | keyword | -| quantum_readiness.operating_system.max_score | Maximum operating system score. | long | -| quantum_readiness.operating_system.modern_crypto_api | Indicates whether a modern crypto API is available. | boolean | -| quantum_readiness.operating_system.native_pqc_support | Indicates whether native post-quantum support is available. | boolean | -| quantum_readiness.operating_system.os_version_max_score | Maximum operating system version score. | long | -| quantum_readiness.operating_system.os_version_score | Operating system version score assigned by the assessment. | long | -| quantum_readiness.operating_system.pqc_framework | Post-quantum framework detected on the operating system. | keyword | -| quantum_readiness.operating_system.symcrypt_present | Indicates whether SymCrypt is present. | boolean | -| quantum_readiness.operating_system.total_score | Total operating system readiness score. | long | -| quantum_readiness.operating_system.version | Operating system version evaluated by the assessment. | keyword | -| quantum_readiness.overall_score | Overall readiness score. | long | -| quantum_readiness.readiness_status | High-level readiness status returned by the assessment. | keyword | -| quantum_readiness.ready_timeline | Estimated timeline to reach readiness. | keyword | -| quantum_readiness.recommendations | Readiness recommendations summarized by TQC. | keyword | -| quantum_readiness.status_color | UI-oriented status color assigned by TQC. | keyword | -| quantum_readiness.system_classification.criticality_level | System criticality level assigned by TQC. | keyword | -| quantum_readiness.system_classification.detection_reason | Reason used to classify the system role and type. | keyword | -| quantum_readiness.system_classification.role | System role assigned by the readiness assessment. | keyword | -| quantum_readiness.system_classification.type | System type assigned by the readiness assessment. | keyword | -| quantum_readiness.timestamp | Native readiness timestamp emitted by TQC. | date | -| quantum_readiness.upgrade_pathway.action | Recommended remediation action. | keyword | -| quantum_readiness.upgrade_pathway.component | Component targeted by the remediation action. | keyword | -| quantum_readiness.upgrade_pathway.description | Description of the recommended remediation step. | keyword | -| quantum_readiness.upgrade_pathway.estimated_time_weeks | Estimated time in weeks for the remediation step. | long | -| quantum_readiness.upgrade_pathway.order | Ordered step number in the upgrade pathway. | long | -| quantum_readiness.upgrade_pathway.priority | Priority assigned to the remediation step. | keyword | -| scan.target_input | Original scan target input supplied to TQC. | keyword | -| scan.timestamp | Timestamp emitted by the scanner for this record. | date | -| scan.type | Scan mode used to collect the readiness record. | keyword | -| tags | Tags preserved on the transformed readiness document. | keyword | -| tychon.index | Tychon dataset discriminator used by the source event. | keyword | -| tychon.type | Tychon record type. | keyword | - -#### vpn_clients -* Source Index: logs-tychon_quantum_command.tychon_pqc-* -* Destination Index: tychon-pqc-vpn-clients - -**Exported fields** - -| Field | Description | Type | -|---|---|---| -| @timestamp | | date | -| event.action | | keyword | -| event.category | | keyword | -| event.dataset | | keyword | -| event.ingested | | date | -| event.kind | | keyword | -| file.path | | keyword | -| id | Tychon unique document identifier for the VPN client record. | keyword | -| kerberos.config_source | | keyword | -| kerberos.has_aes128 | | boolean | -| kerberos.has_aes256 | | boolean | -| kerberos.has_des | | boolean | -| kerberos.has_rc4 | | boolean | -| kerberos.is_quantum_safe | | boolean | -| kerberos.raw_bitmask | | long | -| kerberos.supported_types | | keyword | -| observer.hostname | | keyword | -| observer.id | | keyword | -| observer.tychon_client_id | | keyword | -| observer.windows_server_role | | keyword | -| scan.target_input | | keyword | -| scan.timestamp | | date | -| scan.type | | keyword | -| security.pqc_support | | boolean | -| security.pqc_vulnerable | | boolean | -| security.risk_level | | keyword | -| security.score | | long | -| security.security_score | | long | -| security.vulnerable | | boolean | -| security.weak_crypto | | boolean | -| service.name | | keyword | -| service.state | | keyword | -| tychon.index | | keyword | +| tychon.scanner_version | | keyword | | tychon.type | | keyword | | vpn_client.active | | boolean | | vpn_client.config_path | | keyword | @@ -1103,3 +904,89 @@ This package does not define a custom package-level ILM policy in `docs/README.m | vpn_config.kill_switch | | boolean | | vpn_config.logging_enabled | | boolean | | vpn_config.split_tunneling | | boolean | +| vulnerability.assessed_at | | date | +| vulnerability.cve_list | | keyword | +| vulnerability.is_vulnerable | | boolean | +| vulnerability.risk_level | | keyword | +| vulnerability.risk_reason | | wildcard | +| x509.fingerprint_sha256 | | keyword | +| x509.is_ca | | boolean | +| x509.is_self_signed | | boolean | +| x509.is_valid | | boolean | +| x509.is_weak_signature | | boolean | +| x509.issuer.common_name | | keyword | +| x509.issuer.distinguished_name | | keyword | +| x509.issuer.organization | | keyword | +| x509.issuer_cn | | keyword | +| x509.issuer_org | | keyword | +| x509.key_bits | | long | +| x509.key_type | | keyword | +| x509.key_usage | | keyword | +| x509.not_after | | date | +| x509.not_before | | date | +| x509.public_key_algorithm | | keyword | +| x509.public_key_curve | | keyword | +| x509.public_key_size | | long | +| x509.serial_number | | keyword | +| x509.sha256_fingerprint | | keyword | +| x509.sig_algorithm | | keyword | +| x509.signature_algorithm | | keyword | +| x509.subject.common_name | | keyword | +| x509.subject.distinguished_name | | keyword | +| x509.subject.organization | | keyword | +| x509.subject_cn | | keyword | +| x509.subject_org | | keyword | +| x509.validity.not_after | | date | +| x509.validity.not_before | | date | +| x509.version_number | | long | + + +**Example event** + +An example event for `tychon_pqc` looks as following: + +```json +{ + "@timestamp": "2026-06-11T12:00:00Z", + "event": { + "kind": "event", + "category": [ + "configuration" + ], + "dataset": "tychon_quantum_command.tychon_pqc" + }, + "data_stream": { + "type": "logs", + "dataset": "tychon_quantum_command.tychon_pqc", + "namespace": "default" + }, + "ecs": { + "version": "8.17.0" + }, + "host": { + "hostname": "server01" + }, + "tychon": { + "index": "applications", + "asset_type": "application", + "scan_mode": "quantum_command", + "pqc_readiness": "partial", + "quantum_risk": "medium", + "application": { + "name": "Example Service", + "port": 443, + "preferred_protocol": "TLSv1.3", + "preferred_cipher": "TLS_AES_256_GCM_SHA384", + "preferred_key_exchange": "ECDHE", + "port_quantum_grade": { + "grade": "B", + "score": 82.5 + } + } + } +} +``` + +### Data streams using ILM policies + +This package does not define a custom package-level ILM policy. Apply retention and lifecycle controls according to your deployment standards for both the raw source stream and the transform destination indices. diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json index 89ae630053e..b4d8f4696e2 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json @@ -1,79 +1,399 @@ { - "attributes": { - "controlGroupInput": { - "chainingSystem": "HIERARCHICAL", - "controlStyle": "oneLine", - "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", - "panelsJSON": "{}", - "showApplySelections": false + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": {}, + "showApplySelections": false + }, + "description": "Aligns to schema 2.0.3", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": false, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": false + }, + "panelsJSON": [ + { + "embeddableConfig": { + "enhancements": {}, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | Cost Analysis", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 3, + "i": "tychon-quantum-command-nav", + "w": 48, + "x": 0, + "y": 0 + }, + "panelIndex": "tychon-quantum-command-nav", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Inventory" + }, + "eventId": "39e70128-521d-50c8-913c-d745903e2b64", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Upgrade Cost Analysis — Responsive KPI header: unified top card with accent stripe, three cost-breakdown tiles, and proportional composition bar. Reads pre-computed fields from tychon-pqc-system-readiness*. No cost arithmetic in Vega.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 16, \"right\": 16, \"top\": 16, \"bottom\": 16 },\n \"data\": [\n {\n \"name\": \"cost_totals\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"agg_labor_hours\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_labor_hours\" } },\n \"agg_total_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } },\n \"agg_labor_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_labor_cost_usd\" } },\n \"agg_hw_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_hardware_cost_usd\" } },\n \"agg_lic_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_license_cost_usd\" } },\n \"agg_asset_count\": { \"value_count\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"labor_hours\", \"expr\": \"isValid(datum.agg_labor_hours) ? datum.agg_labor_hours.value : 0\" },\n { \"type\": \"formula\", \"as\": \"total_cost\", \"expr\": \"isValid(datum.agg_total_cost) ? datum.agg_total_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"labor_cost\", \"expr\": \"isValid(datum.agg_labor_cost) ? datum.agg_labor_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"hw_cost\", \"expr\": \"isValid(datum.agg_hw_cost) ? datum.agg_hw_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"lic_cost\", \"expr\": \"isValid(datum.agg_lic_cost) ? datum.agg_lic_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"asset_count\", \"expr\": \"isValid(datum.agg_asset_count) ? datum.agg_asset_count.value : 0\" }\n ]\n }\n ],\n \"signals\": [\n { \"name\": \"gap\", \"value\": 12 },\n { \"name\": \"topH\", \"value\": 124 },\n { \"name\": \"midH\", \"value\": 88 },\n { \"name\": \"midY\", \"update\": \"topH + gap\" },\n { \"name\": \"cw\", \"update\": \"(width - gap * 2) / 3\" },\n { \"name\": \"c2x\", \"update\": \"cw + gap\" },\n { \"name\": \"c3x\", \"update\": \"(cw + gap) * 2\" },\n { \"name\": \"div1x\", \"update\": \"width / 3\" },\n { \"name\": \"div2x\", \"update\": \"width * 2 / 3\" },\n {\n \"name\": \"r\",\n \"update\": \"length(data('cost_totals')) \u003e 0 ? data('cost_totals')[0] : {total_cost:0,labor_hours:0,labor_cost:0,hw_cost:0,lic_cost:0,asset_count:0}\"\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"value\": 0 },\n \"width\": { \"signal\": \"width\" }, \"height\": { \"signal\": \"topH\" },\n \"fill\": { \"value\": \"#f8faff\" },\n \"stroke\": { \"value\": \"#dbeafe\" }, \"strokeWidth\": { \"value\": 1.5 },\n \"cornerRadius\": { \"value\": 10 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"value\": 0 },\n \"width\": { \"signal\": \"width\" }, \"height\": { \"value\": 4 },\n \"fill\": { \"value\": \"#3b82f6\" },\n \"cornerRadiusTopLeft\": { \"value\": 10 }, \"cornerRadiusTopRight\": { \"value\": 10 }\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x\" }, \"y\": { \"value\": 18 },\n \"x2\": { \"signal\": \"div1x\" }, \"y2\": { \"signal\": \"topH - 18\" },\n \"stroke\": { \"value\": \"#e2e8f0\" }, \"strokeWidth\": { \"value\": 1 }\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div2x\" }, \"y\": { \"value\": 18 },\n \"x2\": { \"signal\": \"div2x\" }, \"y2\": { \"signal\": \"topH - 18\" },\n \"stroke\": { \"value\": \"#e2e8f0\" }, \"strokeWidth\": { \"value\": 1 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x / 2\" }, \"y\": { \"signal\": \"topH * 0.40\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 38 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#1d4ed8\" },\n \"text\": { \"signal\": \"'$' + format(r.total_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x / 2\" }, \"y\": { \"signal\": \"topH * 0.65\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 12 }, \"fill\": { \"value\": \"#64748b\" },\n \"text\": { \"value\": \"Total Upgrade Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x / 2\" }, \"y\": { \"signal\": \"topH * 0.85\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#94a3b8\" },\n \"text\": { \"signal\": \"r.asset_count \u003e 0 ? '$' + format(r.total_cost / r.asset_count, ',.0f') + ' per asset' : ''\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x + (div2x - div1x) / 2\" }, \"y\": { \"signal\": \"topH * 0.40\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 34 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#047857\" },\n \"text\": { \"signal\": \"format(r.labor_hours, ',.1f') + ' h'\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x + (div2x - div1x) / 2\" }, \"y\": { \"signal\": \"topH * 0.65\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 12 }, \"fill\": { \"value\": \"#64748b\" },\n \"text\": { \"value\": \"Total Labor Hours\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x + (div2x - div1x) / 2\" }, \"y\": { \"signal\": \"topH * 0.85\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#94a3b8\" },\n \"text\": { \"signal\": \"r.asset_count \u003e 0 ? format(r.labor_hours / r.asset_count, '.1f') + ' h per asset' : ''\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div2x + (width - div2x) / 2\" }, \"y\": { \"signal\": \"topH * 0.40\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 34 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#7e22ce\" },\n \"text\": { \"signal\": \"format(r.asset_count, ',')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div2x + (width - div2x) / 2\" }, \"y\": { \"signal\": \"topH * 0.65\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 12 }, \"fill\": { \"value\": \"#64748b\" },\n \"text\": { \"value\": \"Assets Requiring Upgrade\" }\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"signal\": \"cw\" }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#eff6ff\" }, \"stroke\": { \"value\": \"#bfdbfe\" },\n \"strokeWidth\": { \"value\": 1 }, \"cornerRadius\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"value\": 5 }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#3b82f6\" },\n \"cornerRadiusTopLeft\": { \"value\": 8 }, \"cornerRadiusBottomLeft\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.34\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 26 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#1d4ed8\" },\n \"text\": { \"signal\": \"'$' + format(r.labor_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.58\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 11 }, \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"value\": \"Labor Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.78\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#9ca3af\" },\n \"text\": { \"signal\": \"r.total_cost \u003e 0 ? format(r.labor_cost / r.total_cost * 100, '.0f') + '% of total' : ''\" }\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"signal\": \"cw\" }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#fff1f2\" }, \"stroke\": { \"value\": \"#fca5a5\" },\n \"strokeWidth\": { \"value\": 1 }, \"cornerRadius\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"value\": 5 }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#ef4444\" },\n \"cornerRadiusTopLeft\": { \"value\": 8 }, \"cornerRadiusBottomLeft\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.34\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 26 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#b91c1c\" },\n \"text\": { \"signal\": \"'$' + format(r.hw_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.58\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 11 }, \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"value\": \"Hardware Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.78\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#9ca3af\" },\n \"text\": { \"signal\": \"r.total_cost \u003e 0 ? format(r.hw_cost / r.total_cost * 100, '.0f') + '% of total' : ''\" }\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"signal\": \"cw\" }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#fffbeb\" }, \"stroke\": { \"value\": \"#fcd34d\" },\n \"strokeWidth\": { \"value\": 1 }, \"cornerRadius\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"value\": 5 }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#f59e0b\" },\n \"cornerRadiusTopLeft\": { \"value\": 8 }, \"cornerRadiusBottomLeft\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.34\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 26 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#b45309\" },\n \"text\": { \"signal\": \"'$' + format(r.lic_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.58\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 11 }, \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"value\": \"License / Software Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.78\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#9ca3af\" },\n \"text\": { \"signal\": \"r.total_cost \u003e 0 ? format(r.lic_cost / r.total_cost * 100, '.0f') + '% of total' : ''\" }\n }}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 13, + "i": "e96a3b6f-c862-4732-94f6-635d6e64c5d7", + "w": 48, + "x": 0, + "y": 2 + }, + "panelIndex": "e96a3b6f-c862-4732-94f6-635d6e64c5d7", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Certificate Operations" + }, + "eventId": "939918a5-e238-5f2d-88ff-e2f67ab75598", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Upgrade Cost — OS Category cost estimates ranked list. Reads pre-computed total_cost_usd per OS category from tychon-pqc-system-readiness*. Styled to match the main OS breakdown panel. No cost arithmetic in Vega.\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.os_category === sel ? null : datum.os_category\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.os_category === sel ? kibanaRemoveFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}}) : kibanaAddFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"os_costs\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"qa_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment\" } },\n \"aggs\": {\n \"categories\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.os_category\",\n \"size\": 30,\n \"order\": { \"cost_sum\": \"desc\" }\n },\n \"aggs\": {\n \"cost_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_total_cost_usd\" } },\n \"hours_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_labor_hours\" } },\n \"license_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_license_cost_usd\" } },\n \"hw_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_hardware_cost_usd\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.os_tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\", \"as\": \"buckets\",\n \"expr\": \"isValid(datum.qa_only) \u0026\u0026 isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\"\n },\n { \"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"] },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.item) \u0026\u0026 isValid(datum.item.key)\" },\n { \"type\": \"formula\", \"as\": \"os_category\", \"expr\": \"datum.item.key\" },\n { \"type\": \"formula\", \"as\": \"total_cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"labor_hours\", \"expr\": \"isValid(datum.item.hours_sum) ? datum.item.hours_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"license_cost\", \"expr\": \"isValid(datum.item.license_sum) ? datum.item.license_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"hw_cost\", \"expr\": \"isValid(datum.item.hw_sum) ? datum.item.hw_sum.value : 0\" },\n {\n \"type\": \"formula\", \"as\": \"tier\",\n \"expr\": \"isValid(datum.item.tier_terms) \u0026\u0026 datum.item.tier_terms.buckets.length \u003e 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n {\n \"type\": \"formula\", \"as\": \"clr\",\n \"expr\": \"datum.total_cost === 0 ? '#66bb6a' : datum.tier === 'LEGACY' ? '#ef5350' : datum.tier === 'CLASSICAL' ? '#ffa726' : '#448aff'\"\n },\n {\n \"type\": \"formula\", \"as\": \"bgclr\",\n \"expr\": \"datum.total_cost === 0 ? '#66bb6a18' : datum.tier === 'LEGACY' ? '#ef535018' : datum.tier === 'CLASSICAL' ? '#ffa72618' : '#448aff18'\"\n }\n ]\n },\n {\n \"name\": \"mx\",\n \"source\": \"os_costs\",\n \"transform\": [\n { \"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"total_cost\"], \"as\": [\"v\"] }\n ]\n }\n ],\n \"scales\": [\n {\n \"name\": \"yscale\",\n \"type\": \"band\",\n \"domain\": { \"data\": \"os_costs\", \"field\": \"os_category\", \"sort\": false },\n \"range\": { \"step\": 72 },\n \"paddingInner\": 0,\n \"paddingOuter\": 0\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"OS UPGRADE COST ESTIMATE\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 38},\n \"text\": {\"value\": \"TOTAL COST BY OS CATEGORY — sorted by cost desc\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 48},\n \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.os_category === sel ? '#1c1c2e' : datum.total_cost === 0 ? '#121a12' : '#161622'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 48},\n \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 4}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 110},\n \"width\": {\"signal\": \"length(data('mx')) \u003e 0 \u0026\u0026 data('mx')[0].v \u003e 0 ? max((datum.total_cost / data('mx')[0].v) * (width - 4), 0) : 0\"},\n \"height\": {\"value\": 4},\n \"fill\": {\"field\": \"clr\"},\n \"opacity\": {\"value\": 0.35}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"},\n \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 113},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 72},\n \"text\": {\"field\": \"os_category\"},\n \"limit\": {\"signal\": \"width * 0.58 - 18\"},\n \"fill\": {\"value\": \"#e8e8e8\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 92},\n \"text\": {\"signal\": \"format(datum.labor_hours, ',.1f') + ' labor hrs | $' + format(datum.license_cost, ',.0f') + ' license | $' + format(datum.hw_cost, ',.0f') + ' hardware'\"},\n \"limit\": {\"signal\": \"width * 0.58 - 18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 56},\n \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"field\": \"bgclr\"},\n \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62 + 41\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 68},\n \"text\": {\"field\": \"tier\"},\n \"fill\": {\"field\": \"clr\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 79},\n \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#333333\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62 + 41\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 91},\n \"text\": {\"signal\": \"datum.os_category === sel ? 'SELECTED' : ''\"},\n \"fill\": {\"signal\": \"datum.os_category === sel ? datum.clr : '#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 84},\n \"text\": {\"signal\": \"datum.total_cost \u003e= 1e6 ? '$' + format(datum.total_cost / 1e6, ',.2~f') + 'M' : datum.total_cost \u003e= 1e3 ? '$' + format(datum.total_cost / 1e3, ',.1~f') + 'k' : '$' + format(datum.total_cost, ',')\"},\n \"fill\": {\"signal\": \"datum.os_category === sel ? datum.clr : datum.total_cost \u003e 0 ? '#dddddd' : '#66bb6a'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height - 8\"},\n \"text\": {\"value\": \"↑ highest cost at top\"},\n \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 100},\n \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'NO OS UPGRADE COSTS IN SELECTED TIME RANGE' : ''\"},\n \"fill\": {\"value\": \"#333333\"}, \"fontSize\": {\"value\": 11},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"},\n \"fontWeight\": {\"value\": \"bold\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'OS costs appear when scanned hosts run RHEL 7/8/9, CentOS, Windows 10/Server, Ubuntu, Debian,' : ''\"},\n \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 136},\n \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'or any macOS below version 26 (Tahoe). Windows 11 and macOS 26 Tahoe are PQC targets.' : ''\"},\n \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}\n }}\n }\n ]\n}" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 43, + "i": "499d6919-5d84-47bf-8bff-653bbd5d0ecd", + "w": 17, + "x": 0, + "y": 15 + }, + "panelIndex": "499d6919-5d84-47bf-8bff-653bbd5d0ecd", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "3a5225f5-247d-560e-b33f-876471396e3f", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Upgrade Cost — Effort vs. Risk Bubble Chart. X=total_cost_usd, Y=tier, bubble size=count. Reads pre-computed values from tychon-pqc-system-readiness* using new row schema.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 90, \"right\": 40, \"top\": 40, \"bottom\": 60 },\n \"data\": [\n {\n \"name\": \"os_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"qa_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment\" } },\n \"aggs\": {\n \"categories\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.os_category\",\n \"size\": 30\n },\n \"aggs\": {\n \"cost_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_total_cost_usd\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.os_tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"buckets\",\n \"expr\": \"isValid(datum.qa_only) \u0026\u0026 isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\"\n },\n { \"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"] },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.item) \u0026\u0026 isValid(datum.item.key)\" },\n { \"type\": \"formula\", \"as\": \"label\", \"expr\": \"datum.item.key\" },\n { \"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"datum.item.doc_count \u003e 0 ? datum.item.doc_count : 1\" },\n {\n \"type\": \"formula\",\n \"as\": \"tier\",\n \"expr\": \"isValid(datum.item.tier_terms) \u0026\u0026 datum.item.tier_terms.buckets.length \u003e 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"'OS Upgrade'\" }\n ]\n },\n {\n \"name\": \"app_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment.app_group\" } },\n \"aggs\": {\n \"families\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.app_family\",\n \"size\": 20\n },\n \"aggs\": {\n \"cost_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } },\n \"instances_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.instance_count\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"buckets\",\n \"expr\": \"isValid(datum.app_only) \u0026\u0026 isValid(datum.app_only.families) ? datum.app_only.families.buckets : []\"\n },\n { \"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"] },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.item) \u0026\u0026 isValid(datum.item.key)\" },\n { \"type\": \"formula\", \"as\": \"label\", \"expr\": \"datum.item.key\" },\n { \"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"isValid(datum.item.instances_sum) \u0026\u0026 datum.item.instances_sum.value \u003e 0 ? datum.item.instances_sum.value : 1\" },\n {\n \"type\": \"formula\",\n \"as\": \"tier\",\n \"expr\": \"isValid(datum.item.tier_terms) \u0026\u0026 datum.item.tier_terms.buckets.length \u003e 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"'App Upgrade'\" }\n ]\n },\n {\n \"name\": \"all_items\",\n \"source\": [\"os_raw\", \"app_raw\"],\n \"transform\": [\n { \"type\": \"filter\", \"expr\": \"isFinite(datum.cost) \u0026\u0026 datum.cost \u003e 0\" }\n ]\n }\n ],\n \"scales\": [\n {\n \"name\": \"xscale\",\n \"type\": \"linear\",\n \"domain\": { \"data\": \"all_items\", \"field\": \"cost\" },\n \"range\": \"width\",\n \"nice\": true,\n \"zero\": true\n },\n {\n \"name\": \"yscale\",\n \"type\": \"point\",\n \"domain\": [\"LEGACY\", \"CLASSICAL\"],\n \"range\": [80, 260],\n \"padding\": 0.5\n },\n {\n \"name\": \"sizescale\",\n \"type\": \"sqrt\",\n \"domain\": { \"data\": \"all_items\", \"field\": \"count\" },\n \"range\": [200, 3000],\n \"zero\": true\n },\n {\n \"name\": \"colorscale\",\n \"type\": \"ordinal\",\n \"domain\": [\"OS Upgrade\", \"App Upgrade\"],\n \"range\": [\"#ef5350\", \"#3b82f6\"]\n }\n ],\n \"axes\": [\n {\n \"orient\": \"bottom\",\n \"scale\": \"xscale\",\n \"format\": \"$,.0f\",\n \"title\": \"Total Upgrade Cost (USD)\",\n \"titleFontSize\": 12,\n \"labelAngle\": -30\n },\n {\n \"orient\": \"left\",\n \"scale\": \"yscale\",\n \"title\": \"Risk Tier\",\n \"titleFontSize\": 12\n }\n ],\n \"legends\": [\n {\n \"fill\": \"colorscale\",\n \"title\": \"Category\",\n \"symbolType\": \"circle\",\n \"orient\": \"top-right\"\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 60 },\n \"y\": { \"scale\": \"yscale\", \"value\": \"CLASSICAL\", \"offset\": 40 },\n \"text\": { \"value\": \"Quick Wins\" },\n \"fontSize\": { \"value\": 11 },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"fontStyle\": { \"value\": \"italic\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"signal\": \"width - 100\" },\n \"y\": { \"scale\": \"yscale\", \"value\": \"LEGACY\", \"offset\": -20 },\n \"text\": { \"value\": \"Plan Carefully\" },\n \"fontSize\": { \"value\": 11 },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"fontStyle\": { \"value\": \"italic\" }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": { \"data\": \"all_items\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"cost\" },\n \"y\": { \"scale\": \"yscale\", \"field\": \"tier\" },\n \"size\": { \"scale\": \"sizescale\", \"field\": \"count\" },\n \"fill\": { \"scale\": \"colorscale\", \"field\": \"source\" },\n \"fillOpacity\": { \"value\": 0.65 },\n \"stroke\": { \"scale\": \"colorscale\", \"field\": \"source\" },\n \"strokeWidth\": { \"value\": 1.5 },\n \"tooltip\": {\n \"signal\": \"{'Label': datum.label, 'Tier': datum.tier, 'Category': datum.source, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Count': datum.count}\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"all_items\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"cost\" },\n \"y\": { \"scale\": \"yscale\", \"field\": \"tier\", \"offset\": -16 },\n \"align\": { \"value\": \"center\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"field\": \"label\" }\n }\n }\n }\n ]\n}" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 23, + "i": "53bd2970-764a-498b-9632-f3e37a82d528", + "w": 31, + "x": 17, + "y": 15 + }, + "panelIndex": "53bd2970-764a-498b-9632-f3e37a82d528", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Connections Topology" + }, + "eventId": "702a251d-4e87-5dbc-8cf6-25f5098c4de7", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Cost Composition by App Family (compact). Stacked bars: labor + license + hardware.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 110, \"right\": 18, \"top\": 34, \"bottom\": 38 },\n \"background\": \"#111111\",\n\n \"signals\": [\n { \"name\": \"chartTitle\", \"value\": \"PQC COST COMPOSITION BY APP FAMILY\" },\n { \"name\": \"topN\", \"value\": 10 }\n ],\n\n \"data\": [\n {\n \"name\": \"raw_all\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment.app_group\" } },\n \"aggs\": {\n \"families\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.app_family\",\n \"size\": 30,\n \"order\": { \"total_cost\": \"desc\" }\n },\n \"aggs\": {\n \"labor_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.labor_cost_usd\" } },\n \"license_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.license_cost_usd\" } },\n \"hardware_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.hardware_cost_usd\" } },\n \"total_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } },\n \"instances\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.instance_count\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.app_only.families.buckets\" },\n \"transform\": [\n { \"type\": \"filter\", \"expr\": \"datum \u0026\u0026 datum.key\" },\n { \"type\": \"formula\", \"as\": \"app_family\", \"expr\": \"datum.key\" },\n {\n \"type\": \"formula\",\n \"as\": \"app_family_short\",\n \"expr\": \"length(datum.key) \u003e 14 ? substring(datum.key,0,11) + '...' : datum.key\"\n },\n { \"type\": \"formula\", \"as\": \"labor\", \"expr\": \"isValid(datum.labor_cost) ? datum.labor_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"license\", \"expr\": \"isValid(datum.license_cost) ? datum.license_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"hardware\", \"expr\": \"isValid(datum.hardware_cost) ? datum.hardware_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"total\", \"expr\": \"isValid(datum.total_cost) ? datum.total_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"instances\", \"expr\": \"isValid(datum.instances) ? datum.instances.value : 0\" },\n {\n \"type\": \"formula\",\n \"as\": \"tier\",\n \"expr\": \"isValid(datum.tier_terms) \u0026\u0026 datum.tier_terms.buckets.length \u003e 0 ? datum.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n { \"type\": \"filter\", \"expr\": \"isFinite(datum.total) \u0026\u0026 datum.total \u003e 0\" },\n { \"type\": \"collect\", \"sort\": { \"field\": \"total\", \"order\": \"descending\" } },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rank\"] },\n { \"type\": \"filter\", \"expr\": \"datum.rank \u003c= topN\" }\n ]\n },\n\n {\n \"name\": \"components\",\n \"source\": \"raw_all\",\n \"transform\": [\n { \"type\": \"fold\", \"fields\": [\"labor\", \"license\", \"hardware\"], \"as\": [\"component\", \"value\"] },\n { \"type\": \"stack\", \"groupby\": [\"app_family_short\"], \"sort\": { \"field\": \"component\" }, \"field\": \"value\", \"as\": [\"x0\", \"x1\"] }\n ]\n }\n ],\n\n \"scales\": [\n {\n \"name\": \"yscale\",\n \"type\": \"band\",\n \"domain\": { \"data\": \"raw_all\", \"field\": \"app_family_short\" },\n \"range\": \"height\",\n \"paddingInner\": 0.18,\n \"paddingOuter\": 0.06\n },\n {\n \"name\": \"xscale\",\n \"type\": \"linear\",\n \"domain\": { \"data\": \"raw_all\", \"field\": \"total\" },\n \"nice\": true,\n \"zero\": true,\n \"range\": \"width\"\n },\n {\n \"name\": \"cscale\",\n \"type\": \"ordinal\",\n \"domain\": [\"labor\", \"license\", \"hardware\"],\n \"range\": [\"#f59e0b\", \"#3b82f6\", \"#ef4444\"]\n }\n ],\n\n \"axes\": [\n {\n \"orient\": \"left\",\n \"scale\": \"yscale\",\n \"labelLimit\": 96,\n \"labelColor\": \"#d1d5db\",\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\",\n \"title\": \"\",\n \"zindex\": 1\n },\n {\n \"orient\": \"bottom\",\n \"scale\": \"xscale\",\n \"format\": \"$,.2s\",\n \"title\": \"Total Cost (USD)\",\n \"titleColor\": \"#9ca3af\",\n \"labelColor\": \"#9ca3af\",\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\"\n }\n ],\n\n \"legends\": [\n {\n \"fill\": \"cscale\",\n \"title\": \"Cost Component\",\n \"orient\": \"top-right\",\n \"titleColor\": \"#d1d5db\",\n \"labelColor\": \"#9ca3af\"\n }\n ],\n\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 0 },\n \"y\": { \"value\": -10 },\n \"text\": { \"signal\": \"chartTitle + ' (TOP ' + topN + ')'\" },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"letterSpacing\": { \"value\": 0.8 }\n }\n }\n },\n\n {\n \"type\": \"rect\",\n \"from\": { \"data\": \"components\" },\n \"encode\": {\n \"enter\": {\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\" },\n \"height\": { \"scale\": \"yscale\", \"band\": 1 },\n \"x\": { \"scale\": \"xscale\", \"field\": \"x0\" },\n \"x2\": { \"scale\": \"xscale\", \"field\": \"x1\" },\n \"fill\": { \"scale\": \"cscale\", \"field\": \"component\" },\n \"stroke\": { \"value\": \"#0f0f0f\" },\n \"strokeWidth\": { \"value\": 0.6 },\n \"tooltip\": {\n \"signal\": \"{'App Family': datum.app_family, 'Tier': datum.tier, 'Component': datum.component, 'Component Cost': '$' + format(datum.value, ',.0f'), 'Total Cost': '$' + format(datum.total, ',.0f'), 'Instances': datum.instances}\"\n }\n }\n }\n },\n\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"raw_all\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"total\", \"offset\": 4 },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5 },\n \"text\": { \"signal\": \"'$' + format(datum.total, ',.2s')\" },\n \"fill\": { \"value\": \"#e5e7eb\" },\n \"fontSize\": { \"value\": 9 },\n \"align\": { \"value\": \"left\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"raw_all\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": -4 },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5 },\n \"text\": { \"signal\": \"datum.instances \u003e 0 ? '(' + format(datum.instances, ',.0f') + ')' : ''\" },\n \"fill\": { \"value\": \"#6b7280\" },\n \"fontSize\": { \"value\": 8 },\n \"align\": { \"value\": \"right\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n }\n ]\n}" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 20, + "i": "3b9211b0-164b-495c-b3b6-479193fe6c1e", + "w": 15, + "x": 17, + "y": 38 + }, + "panelIndex": "3b9211b0-164b-495c-b3b6-479193fe6c1e", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Inventory" + }, + "eventId": "26ab7837-9182-5ae8-9186-6a46abbd5428", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Priority Matrix — Tier x App Family heatmap. Responsive, compact layout.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 92, \"right\": 16, \"top\": 34, \"bottom\": 46 },\n \"background\": \"#111111\",\n\n \"signals\": [\n { \"name\": \"topN\", \"value\": 10 },\n { \"name\": \"showCellText\", \"update\": \"bandwidth('yscale') \u003e= 18 \u0026\u0026 bandwidth('xscale') \u003e= 64\" }\n ],\n\n \"data\": [\n {\n \"name\": \"matrix_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment.app_group\" } },\n \"aggs\": {\n \"families\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.app_family\",\n \"size\": 40\n },\n \"aggs\": {\n \"tiers\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.tier\",\n \"size\": 5\n },\n \"aggs\": {\n \"cost_sum\": {\n \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" }\n },\n \"instances_sum\": {\n \"sum\": { \"field\": \"quantum_readiness.cost_analysis.instance_count\" }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.app_only.families.buckets\" },\n \"transform\": [\n { \"type\": \"filter\", \"expr\": \"datum \u0026\u0026 datum.key \u0026\u0026 datum.tiers \u0026\u0026 datum.tiers.buckets\" },\n { \"type\": \"formula\", \"as\": \"app_family\", \"expr\": \"datum.key\" },\n { \"type\": \"flatten\", \"fields\": [\"tiers.buckets\"], \"as\": [\"tier_bucket\"] },\n { \"type\": \"filter\", \"expr\": \"datum.tier_bucket \u0026\u0026 datum.tier_bucket.key\" },\n { \"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.tier_bucket.key\" },\n { \"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.tier_bucket.cost_sum) ? datum.tier_bucket.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"instances\", \"expr\": \"isValid(datum.tier_bucket.instances_sum) ? datum.tier_bucket.instances_sum.value : 0\" },\n { \"type\": \"filter\", \"expr\": \"isFinite(datum.cost) \u0026\u0026 datum.cost \u003e= 0\" }\n ]\n },\n\n {\n \"name\": \"family_order\",\n \"source\": \"matrix_raw\",\n \"transform\": [\n { \"type\": \"aggregate\", \"groupby\": [\"app_family\"], \"ops\": [\"sum\"], \"fields\": [\"cost\"], \"as\": [\"family_total_cost\"] },\n { \"type\": \"collect\", \"sort\": { \"field\": \"family_total_cost\", \"order\": \"descending\" } },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rank\"] },\n { \"type\": \"filter\", \"expr\": \"datum.rank \u003c= topN\" },\n {\n \"type\": \"formula\",\n \"as\": \"app_family_short\",\n \"expr\": \"length(datum.app_family) \u003e 14 ? substring(datum.app_family,0,11) + '...' : datum.app_family\"\n }\n ]\n },\n\n {\n \"name\": \"matrix\",\n \"source\": \"matrix_raw\",\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"family_order\",\n \"key\": \"app_family\",\n \"fields\": [\"app_family\"],\n \"values\": [\"rank\", \"app_family_short\", \"family_total_cost\"],\n \"as\": [\"rank\", \"app_family_short\", \"family_total_cost\"]\n },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.rank)\" }\n ]\n }\n ],\n\n \"scales\": [\n {\n \"name\": \"xscale\",\n \"type\": \"band\",\n \"domain\": [\"LEGACY\", \"CLASSICAL\"],\n \"range\": \"width\",\n \"paddingInner\": 0.08,\n \"paddingOuter\": 0.03\n },\n {\n \"name\": \"yscale\",\n \"type\": \"band\",\n \"domain\": { \"data\": \"family_order\", \"field\": \"app_family_short\" },\n \"range\": \"height\",\n \"paddingInner\": 0.08,\n \"paddingOuter\": 0.03\n },\n {\n \"name\": \"cscale\",\n \"type\": \"linear\",\n \"domain\": { \"data\": \"matrix\", \"field\": \"cost\" },\n \"range\": [\"#1f2937\", \"#2563eb\", \"#7c3aed\", \"#dc2626\"],\n \"nice\": true,\n \"zero\": true\n }\n ],\n\n \"axes\": [\n {\n \"orient\": \"bottom\",\n \"scale\": \"xscale\",\n \"title\": \"Tier\",\n \"titleColor\": \"#d1d5db\",\n \"labelColor\": \"#d1d5db\",\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\"\n },\n {\n \"orient\": \"left\",\n \"scale\": \"yscale\",\n \"title\": \"\",\n \"labelColor\": \"#d1d5db\",\n \"labelLimit\": 86,\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\"\n }\n ],\n\n \"legends\": [\n {\n \"fill\": \"cscale\",\n \"title\": \"Cost\",\n \"orient\": \"right\",\n \"titleColor\": \"#d1d5db\",\n \"labelColor\": \"#9ca3af\",\n \"format\": \"$,.2s\"\n }\n ],\n\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 0 },\n \"y\": { \"value\": -12 },\n \"text\": { \"value\": \"PRIORITY MATRIX (TOP APP FAMILIES)\" },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"letterSpacing\": { \"value\": 0.8 }\n }\n }\n },\n\n {\n \"type\": \"rect\",\n \"from\": { \"data\": \"matrix\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"tier\" },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\" },\n \"width\": { \"scale\": \"xscale\", \"band\": 1 },\n \"height\": { \"scale\": \"yscale\", \"band\": 1 },\n \"fill\": { \"scale\": \"cscale\", \"field\": \"cost\" },\n \"stroke\": { \"value\": \"#1a1a1a\" },\n \"strokeWidth\": { \"value\": 1 },\n \"tooltip\": {\n \"signal\": \"{'App Family': datum.app_family, 'Tier': datum.tier, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Instances': format(datum.instances, ',.0f')}\"\n }\n }\n }\n },\n\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"matrix\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"tier\", \"band\": 0.5 },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5 },\n \"align\": { \"value\": \"center\" },\n \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 9 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#f9fafb\" },\n \"text\": { \"signal\": \"showCellText \u0026\u0026 datum.instances \u003e 0 ? format(datum.instances, ',.0f') : ''\" }\n }\n }\n }\n ]\n}" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 20, + "i": "279b7812-2cf0-43a2-8c2f-410ab21ba53d", + "w": 16, + "x": 32, + "y": 38 + }, + "panelIndex": "279b7812-2cf0-43a2-8c2f-410ab21ba53d", + "type": "visualization" + } + ], + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "timeFrom": "now-24h/h", + "timeRestore": true, + "timeTo": "now", + "title": "[TYCHON Quantum Command] Cost Analysis", + "version": 3 }, - "description": "Aligns to schema 2.0.3", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "optionsJSON": "{\"useMargins\":false,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", - "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | Cost Analysis\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"39e70128-521d-50c8-913c-d745903e2b64\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Upgrade Cost Analysis \\u2014 Responsive KPI header: unified top card with accent stripe, three cost-breakdown tiles, and proportional composition bar. Reads pre-computed fields from tychon-pqc-system-readiness*. No cost arithmetic in Vega.\\\",\\n \\\"autosize\\\": { \\\"type\\\": \\\"fit\\\", \\\"contains\\\": \\\"padding\\\" },\\n \\\"padding\\\": { \\\"left\\\": 16, \\\"right\\\": 16, \\\"top\\\": 16, \\\"bottom\\\": 16 },\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"cost_totals\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"agg_labor_hours\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_labor_hours\\\" } },\\n \\\"agg_total_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" } },\\n \\\"agg_labor_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_labor_cost_usd\\\" } },\\n \\\"agg_hw_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_hardware_cost_usd\\\" } },\\n \\\"agg_lic_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_license_cost_usd\\\" } },\\n \\\"agg_asset_count\\\": { \\\"value_count\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" } }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"labor_hours\\\", \\\"expr\\\": \\\"isValid(datum.agg_labor_hours) ? datum.agg_labor_hours.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total_cost\\\", \\\"expr\\\": \\\"isValid(datum.agg_total_cost) ? datum.agg_total_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"labor_cost\\\", \\\"expr\\\": \\\"isValid(datum.agg_labor_cost) ? datum.agg_labor_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hw_cost\\\", \\\"expr\\\": \\\"isValid(datum.agg_hw_cost) ? datum.agg_hw_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"lic_cost\\\", \\\"expr\\\": \\\"isValid(datum.agg_lic_cost) ? datum.agg_lic_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"asset_count\\\", \\\"expr\\\": \\\"isValid(datum.agg_asset_count) ? datum.agg_asset_count.value : 0\\\" }\\n ]\\n }\\n ],\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"gap\\\", \\\"value\\\": 12 },\\n { \\\"name\\\": \\\"topH\\\", \\\"value\\\": 124 },\\n { \\\"name\\\": \\\"midH\\\", \\\"value\\\": 88 },\\n { \\\"name\\\": \\\"midY\\\", \\\"update\\\": \\\"topH + gap\\\" },\\n { \\\"name\\\": \\\"cw\\\", \\\"update\\\": \\\"(width - gap * 2) / 3\\\" },\\n { \\\"name\\\": \\\"c2x\\\", \\\"update\\\": \\\"cw + gap\\\" },\\n { \\\"name\\\": \\\"c3x\\\", \\\"update\\\": \\\"(cw + gap) * 2\\\" },\\n { \\\"name\\\": \\\"div1x\\\", \\\"update\\\": \\\"width / 3\\\" },\\n { \\\"name\\\": \\\"div2x\\\", \\\"update\\\": \\\"width * 2 / 3\\\" },\\n {\\n \\\"name\\\": \\\"r\\\",\\n \\\"update\\\": \\\"length(data('cost_totals')) > 0 ? data('cost_totals')[0] : {total_cost:0,labor_hours:0,labor_cost:0,hw_cost:0,lic_cost:0,asset_count:0}\\\"\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"width\\\": { \\\"signal\\\": \\\"width\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"topH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#f8faff\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#dbeafe\\\" }, \\\"strokeWidth\\\": { \\\"value\\\": 1.5 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 10 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"width\\\": { \\\"signal\\\": \\\"width\\\" }, \\\"height\\\": { \\\"value\\\": 4 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#3b82f6\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 10 }, \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 10 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x\\\" }, \\\"y\\\": { \\\"value\\\": 18 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"div1x\\\" }, \\\"y2\\\": { \\\"signal\\\": \\\"topH - 18\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#e2e8f0\\\" }, \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div2x\\\" }, \\\"y\\\": { \\\"value\\\": 18 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"div2x\\\" }, \\\"y2\\\": { \\\"signal\\\": \\\"topH - 18\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#e2e8f0\\\" }, \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.40\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 38 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#1d4ed8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.total_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.65\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 }, \\\"fill\\\": { \\\"value\\\": \\\"#64748b\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Total Upgrade Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.85\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#94a3b8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.asset_count > 0 ? '$' + format(r.total_cost / r.asset_count, ',.0f') + ' per asset' : ''\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x + (div2x - div1x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.40\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 34 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#047857\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(r.labor_hours, ',.1f') + ' h'\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x + (div2x - div1x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.65\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 }, \\\"fill\\\": { \\\"value\\\": \\\"#64748b\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Total Labor Hours\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div1x + (div2x - div1x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.85\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#94a3b8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.asset_count > 0 ? format(r.labor_hours / r.asset_count, '.1f') + ' h per asset' : ''\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div2x + (width - div2x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.40\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 34 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#7e22ce\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(r.asset_count, ',')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"div2x + (width - div2x) / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"topH * 0.65\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 }, \\\"fill\\\": { \\\"value\\\": \\\"#64748b\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Assets Requiring Upgrade\\\" }\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"signal\\\": \\\"cw\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#eff6ff\\\" }, \\\"stroke\\\": { \\\"value\\\": \\\"#bfdbfe\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }, \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"value\\\": 5 }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#3b82f6\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 }, \\\"cornerRadiusBottomLeft\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.34\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 26 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#1d4ed8\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.labor_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.58\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 }, \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Labor Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.78\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#9ca3af\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.total_cost > 0 ? format(r.labor_cost / r.total_cost * 100, '.0f') + '% of total' : ''\\\" }\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"signal\\\": \\\"cw\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#fff1f2\\\" }, \\\"stroke\\\": { \\\"value\\\": \\\"#fca5a5\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }, \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"value\\\": 5 }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#ef4444\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 }, \\\"cornerRadiusBottomLeft\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.34\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 26 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#b91c1c\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.hw_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.58\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 }, \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"Hardware Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c2x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.78\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#9ca3af\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.total_cost > 0 ? format(r.hw_cost / r.total_cost * 100, '.0f') + '% of total' : ''\\\" }\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"signal\\\": \\\"cw\\\" }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#fffbeb\\\" }, \\\"stroke\\\": { \\\"value\\\": \\\"#fcd34d\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }, \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY\\\" },\\n \\\"width\\\": { \\\"value\\\": 5 }, \\\"height\\\": { \\\"signal\\\": \\\"midH\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#f59e0b\\\" },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 }, \\\"cornerRadiusBottomLeft\\\": { \\\"value\\\": 8 }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.34\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 26 }, \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#b45309\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(r.lic_cost, ',.0f')\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.58\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 }, \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"License / Software Cost\\\" }\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": { \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"c3x + cw / 2\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"midY + midH * 0.78\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" }, \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 }, \\\"fill\\\": { \\\"value\\\": \\\"#9ca3af\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"r.total_cost > 0 ? format(r.lic_cost / r.total_cost * 100, '.0f') + '% of total' : ''\\\" }\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"e96a3b6f-c862-4732-94f6-635d6e64c5d7\",\"gridData\":{\"i\":\"e96a3b6f-c862-4732-94f6-635d6e64c5d7\",\"y\":2,\"x\":0,\"w\":48,\"h\":13}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"939918a5-e238-5f2d-88ff-e2f67ab75598\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Certificate Operations\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Upgrade Cost \\u2014 OS Category cost estimates ranked list. Reads pre-computed total_cost_usd per OS category from tychon-pqc-system-readiness*. Styled to match the main OS breakdown panel. No cost arithmetic in Vega.\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.os_category === sel ? null : datum.os_category\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.os_category === sel ? kibanaRemoveFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}}) : kibanaAddFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"os_costs\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"qa_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment\\\" } },\\n \\\"aggs\\\": {\\n \\\"categories\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_category\\\",\\n \\\"size\\\": 30,\\n \\\"order\\\": { \\\"cost_sum\\\": \\\"desc\\\" }\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_total_cost_usd\\\" } },\\n \\\"hours_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_labor_hours\\\" } },\\n \\\"license_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_license_cost_usd\\\" } },\\n \\\"hw_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_hardware_cost_usd\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"buckets\\\",\\n \\\"expr\\\": \\\"isValid(datum.qa_only) && isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"buckets\\\"], \\\"as\\\": [\\\"item\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.item) && isValid(datum.item.key)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"os_category\\\", \\\"expr\\\": \\\"datum.item.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total_cost\\\", \\\"expr\\\": \\\"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"labor_hours\\\", \\\"expr\\\": \\\"isValid(datum.item.hours_sum) ? datum.item.hours_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"license_cost\\\", \\\"expr\\\": \\\"isValid(datum.item.license_sum) ? datum.item.license_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hw_cost\\\", \\\"expr\\\": \\\"isValid(datum.item.hw_sum) ? datum.item.hw_sum.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\",\\n \\\"expr\\\": \\\"datum.total_cost === 0 ? '#66bb6a' : datum.tier === 'LEGACY' ? '#ef5350' : datum.tier === 'CLASSICAL' ? '#ffa726' : '#448aff'\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bgclr\\\",\\n \\\"expr\\\": \\\"datum.total_cost === 0 ? '#66bb6a18' : datum.tier === 'LEGACY' ? '#ef535018' : datum.tier === 'CLASSICAL' ? '#ffa72618' : '#448aff18'\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"os_costs\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"total_cost\\\"], \\\"as\\\": [\\\"v\\\"] }\\n ]\\n }\\n ],\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"os_costs\\\", \\\"field\\\": \\\"os_category\\\", \\\"sort\\\": false },\\n \\\"range\\\": { \\\"step\\\": 72 },\\n \\\"paddingInner\\\": 0,\\n \\\"paddingOuter\\\": 0\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"OS UPGRADE COST ESTIMATE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38},\\n \\\"text\\\": {\\\"value\\\": \\\"TOTAL COST BY OS CATEGORY \\u2014 sorted by cost desc\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 48},\\n \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? '#1c1c2e' : datum.total_cost === 0 ? '#121a12' : '#161622'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 48},\\n \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 4}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 110},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx')) > 0 && data('mx')[0].v > 0 ? max((datum.total_cost / data('mx')[0].v) * (width - 4), 0) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"opacity\\\": {\\\"value\\\": 0.35}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"},\\n \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 113},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 72},\\n \\\"text\\\": {\\\"field\\\": \\\"os_category\\\"},\\n \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.58 - 18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 92},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.labor_hours, ',.1f') + ' labor hrs | $' + format(datum.license_cost, ',.0f') + ' license | $' + format(datum.hw_cost, ',.0f') + ' hardware'\\\"},\\n \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.58 - 18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 56},\\n \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bgclr\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 41\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 68},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 79},\\n \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#333333\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 41\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 91},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? 'SELECTED' : ''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? datum.clr : '#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"os_costs\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"os_category\\\", \\\"offset\\\": 84},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.total_cost >= 1e6 ? '$' + format(datum.total_cost / 1e6, ',.2~f') + 'M' : datum.total_cost >= 1e3 ? '$' + format(datum.total_cost / 1e3, ',.1~f') + 'k' : '$' + format(datum.total_cost, ',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.os_category === sel ? datum.clr : datum.total_cost > 0 ? '#dddddd' : '#66bb6a'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height - 8\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"\\u2191 highest cost at top\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"value\\\": 100},\\n \\\"text\\\": {\\\"signal\\\": \\\"length(data('os_costs')) === 0 ? 'NO OS UPGRADE COSTS IN SELECTED TIME RANGE' : ''\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#333333\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"length(data('os_costs')) === 0 ? 'OS costs appear when scanned hosts run RHEL 7/8/9, CentOS, Windows 10/Server, Ubuntu, Debian,' : ''\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width / 2\\\"}, \\\"y\\\": {\\\"value\\\": 136},\\n \\\"text\\\": {\\\"signal\\\": \\\"length(data('os_costs')) === 0 ? 'or any macOS below version 26 (Tahoe). Windows 11 and macOS 26 Tahoe are PQC targets.' : ''\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}\\n }}\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"499d6919-5d84-47bf-8bff-653bbd5d0ecd\",\"gridData\":{\"i\":\"499d6919-5d84-47bf-8bff-653bbd5d0ecd\",\"y\":15,\"x\":0,\"w\":17,\"h\":43}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"3a5225f5-247d-560e-b33f-876471396e3f\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Upgrade Cost \\u2014 Effort vs. Risk Bubble Chart. X=total_cost_usd, Y=tier, bubble size=count. Reads pre-computed values from tychon-pqc-system-readiness* using new row schema.\\\",\\n \\\"autosize\\\": { \\\"type\\\": \\\"fit\\\", \\\"contains\\\": \\\"padding\\\" },\\n \\\"padding\\\": { \\\"left\\\": 90, \\\"right\\\": 40, \\\"top\\\": 40, \\\"bottom\\\": 60 },\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"os_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"qa_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment\\\" } },\\n \\\"aggs\\\": {\\n \\\"categories\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_category\\\",\\n \\\"size\\\": 30\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_total_cost_usd\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.os_tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"buckets\\\",\\n \\\"expr\\\": \\\"isValid(datum.qa_only) && isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"buckets\\\"], \\\"as\\\": [\\\"item\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.item) && isValid(datum.item.key)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"label\\\", \\\"expr\\\": \\\"datum.item.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cost\\\", \\\"expr\\\": \\\"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"datum.item.doc_count > 0 ? datum.item.doc_count : 1\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"'OS Upgrade'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"app_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment.app_group\\\" } },\\n \\\"aggs\\\": {\\n \\\"families\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.app_family\\\",\\n \\\"size\\\": 20\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" } },\\n \\\"instances_sum\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.instance_count\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"buckets\\\",\\n \\\"expr\\\": \\\"isValid(datum.app_only) && isValid(datum.app_only.families) ? datum.app_only.families.buckets : []\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"buckets\\\"], \\\"as\\\": [\\\"item\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.item) && isValid(datum.item.key)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"label\\\", \\\"expr\\\": \\\"datum.item.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cost\\\", \\\"expr\\\": \\\"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"isValid(datum.item.instances_sum) && datum.item.instances_sum.value > 0 ? datum.item.instances_sum.value : 1\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"'App Upgrade'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"all_items\\\",\\n \\\"source\\\": [\\\"os_raw\\\", \\\"app_raw\\\"],\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isFinite(datum.cost) && datum.cost > 0\\\" }\\n ]\\n }\\n ],\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"xscale\\\",\\n \\\"type\\\": \\\"linear\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"all_items\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"range\\\": \\\"width\\\",\\n \\\"nice\\\": true,\\n \\\"zero\\\": true\\n },\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"point\\\",\\n \\\"domain\\\": [\\\"LEGACY\\\", \\\"CLASSICAL\\\"],\\n \\\"range\\\": [80, 260],\\n \\\"padding\\\": 0.5\\n },\\n {\\n \\\"name\\\": \\\"sizescale\\\",\\n \\\"type\\\": \\\"sqrt\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"all_items\\\", \\\"field\\\": \\\"count\\\" },\\n \\\"range\\\": [200, 3000],\\n \\\"zero\\\": true\\n },\\n {\\n \\\"name\\\": \\\"colorscale\\\",\\n \\\"type\\\": \\\"ordinal\\\",\\n \\\"domain\\\": [\\\"OS Upgrade\\\", \\\"App Upgrade\\\"],\\n \\\"range\\\": [\\\"#ef5350\\\", \\\"#3b82f6\\\"]\\n }\\n ],\\n \\\"axes\\\": [\\n {\\n \\\"orient\\\": \\\"bottom\\\",\\n \\\"scale\\\": \\\"xscale\\\",\\n \\\"format\\\": \\\"$,.0f\\\",\\n \\\"title\\\": \\\"Total Upgrade Cost (USD)\\\",\\n \\\"titleFontSize\\\": 12,\\n \\\"labelAngle\\\": -30\\n },\\n {\\n \\\"orient\\\": \\\"left\\\",\\n \\\"scale\\\": \\\"yscale\\\",\\n \\\"title\\\": \\\"Risk Tier\\\",\\n \\\"titleFontSize\\\": 12\\n }\\n ],\\n \\\"legends\\\": [\\n {\\n \\\"fill\\\": \\\"colorscale\\\",\\n \\\"title\\\": \\\"Category\\\",\\n \\\"symbolType\\\": \\\"circle\\\",\\n \\\"orient\\\": \\\"top-right\\\"\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 60 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"value\\\": \\\"CLASSICAL\\\", \\\"offset\\\": 40 },\\n \\\"text\\\": { \\\"value\\\": \\\"Quick Wins\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"fontStyle\\\": { \\\"value\\\": \\\"italic\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 100\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"value\\\": \\\"LEGACY\\\", \\\"offset\\\": -20 },\\n \\\"text\\\": { \\\"value\\\": \\\"Plan Carefully\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 11 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"fontStyle\\\": { \\\"value\\\": \\\"italic\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"all_items\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"tier\\\" },\\n \\\"size\\\": { \\\"scale\\\": \\\"sizescale\\\", \\\"field\\\": \\\"count\\\" },\\n \\\"fill\\\": { \\\"scale\\\": \\\"colorscale\\\", \\\"field\\\": \\\"source\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.65 },\\n \\\"stroke\\\": { \\\"scale\\\": \\\"colorscale\\\", \\\"field\\\": \\\"source\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.5 },\\n \\\"tooltip\\\": {\\n \\\"signal\\\": \\\"{'Label': datum.label, 'Tier': datum.tier, 'Category': datum.source, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Count': datum.count}\\\"\\n }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"all_items\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"tier\\\", \\\"offset\\\": -16 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#374151\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"label\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"53bd2970-764a-498b-9632-f3e37a82d528\",\"gridData\":{\"i\":\"53bd2970-764a-498b-9632-f3e37a82d528\",\"y\":15,\"x\":17,\"w\":31,\"h\":23}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"702a251d-4e87-5dbc-8cf6-25f5098c4de7\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Cost Composition by App Family (compact). Stacked bars: labor + license + hardware.\\\",\\n \\\"autosize\\\": { \\\"type\\\": \\\"fit\\\", \\\"contains\\\": \\\"padding\\\" },\\n \\\"padding\\\": { \\\"left\\\": 110, \\\"right\\\": 18, \\\"top\\\": 34, \\\"bottom\\\": 38 },\\n \\\"background\\\": \\\"#111111\\\",\\n\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"chartTitle\\\", \\\"value\\\": \\\"PQC COST COMPOSITION BY APP FAMILY\\\" },\\n { \\\"name\\\": \\\"topN\\\", \\\"value\\\": 10 }\\n ],\\n\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw_all\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment.app_group\\\" } },\\n \\\"aggs\\\": {\\n \\\"families\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.app_family\\\",\\n \\\"size\\\": 30,\\n \\\"order\\\": { \\\"total_cost\\\": \\\"desc\\\" }\\n },\\n \\\"aggs\\\": {\\n \\\"labor_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.labor_cost_usd\\\" } },\\n \\\"license_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.license_cost_usd\\\" } },\\n \\\"hardware_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.hardware_cost_usd\\\" } },\\n \\\"total_cost\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" } },\\n \\\"instances\\\": { \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.instance_count\\\" } },\\n \\\"tier_terms\\\": { \\\"terms\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.tier\\\", \\\"size\\\": 1 } }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.families.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum && datum.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app_family\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app_family_short\\\",\\n \\\"expr\\\": \\\"length(datum.key) > 14 ? substring(datum.key,0,11) + '...' : datum.key\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"labor\\\", \\\"expr\\\": \\\"isValid(datum.labor_cost) ? datum.labor_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"license\\\", \\\"expr\\\": \\\"isValid(datum.license_cost) ? datum.license_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hardware\\\", \\\"expr\\\": \\\"isValid(datum.hardware_cost) ? datum.hardware_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total\\\", \\\"expr\\\": \\\"isValid(datum.total_cost) ? datum.total_cost.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"instances\\\", \\\"expr\\\": \\\"isValid(datum.instances) ? datum.instances.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tier\\\",\\n \\\"expr\\\": \\\"isValid(datum.tier_terms) && datum.tier_terms.buckets.length > 0 ? datum.tier_terms.buckets[0].key : 'CLASSICAL'\\\"\\n },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isFinite(datum.total) && datum.total > 0\\\" },\\n { \\\"type\\\": \\\"collect\\\", \\\"sort\\\": { \\\"field\\\": \\\"total\\\", \\\"order\\\": \\\"descending\\\" } },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rank\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rank <= topN\\\" }\\n ]\\n },\\n\\n {\\n \\\"name\\\": \\\"components\\\",\\n \\\"source\\\": \\\"raw_all\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"labor\\\", \\\"license\\\", \\\"hardware\\\"], \\\"as\\\": [\\\"component\\\", \\\"value\\\"] },\\n { \\\"type\\\": \\\"stack\\\", \\\"groupby\\\": [\\\"app_family_short\\\"], \\\"sort\\\": { \\\"field\\\": \\\"component\\\" }, \\\"field\\\": \\\"value\\\", \\\"as\\\": [\\\"x0\\\", \\\"x1\\\"] }\\n ]\\n }\\n ],\\n\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"raw_all\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"range\\\": \\\"height\\\",\\n \\\"paddingInner\\\": 0.18,\\n \\\"paddingOuter\\\": 0.06\\n },\\n {\\n \\\"name\\\": \\\"xscale\\\",\\n \\\"type\\\": \\\"linear\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"raw_all\\\", \\\"field\\\": \\\"total\\\" },\\n \\\"nice\\\": true,\\n \\\"zero\\\": true,\\n \\\"range\\\": \\\"width\\\"\\n },\\n {\\n \\\"name\\\": \\\"cscale\\\",\\n \\\"type\\\": \\\"ordinal\\\",\\n \\\"domain\\\": [\\\"labor\\\", \\\"license\\\", \\\"hardware\\\"],\\n \\\"range\\\": [\\\"#f59e0b\\\", \\\"#3b82f6\\\", \\\"#ef4444\\\"]\\n }\\n ],\\n\\n \\\"axes\\\": [\\n {\\n \\\"orient\\\": \\\"left\\\",\\n \\\"scale\\\": \\\"yscale\\\",\\n \\\"labelLimit\\\": 96,\\n \\\"labelColor\\\": \\\"#d1d5db\\\",\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\",\\n \\\"title\\\": \\\"\\\",\\n \\\"zindex\\\": 1\\n },\\n {\\n \\\"orient\\\": \\\"bottom\\\",\\n \\\"scale\\\": \\\"xscale\\\",\\n \\\"format\\\": \\\"$,.2s\\\",\\n \\\"title\\\": \\\"Total Cost (USD)\\\",\\n \\\"titleColor\\\": \\\"#9ca3af\\\",\\n \\\"labelColor\\\": \\\"#9ca3af\\\",\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\"\\n }\\n ],\\n\\n \\\"legends\\\": [\\n {\\n \\\"fill\\\": \\\"cscale\\\",\\n \\\"title\\\": \\\"Cost Component\\\",\\n \\\"orient\\\": \\\"top-right\\\",\\n \\\"titleColor\\\": \\\"#d1d5db\\\",\\n \\\"labelColor\\\": \\\"#9ca3af\\\"\\n }\\n ],\\n\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": -10 },\\n \\\"text\\\": { \\\"signal\\\": \\\"chartTitle + ' (TOP ' + topN + ')'\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"letterSpacing\\\": { \\\"value\\\": 0.8 }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"components\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"height\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"band\\\": 1 },\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"x0\\\" },\\n \\\"x2\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"x1\\\" },\\n \\\"fill\\\": { \\\"scale\\\": \\\"cscale\\\", \\\"field\\\": \\\"component\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#0f0f0f\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 0.6 },\\n \\\"tooltip\\\": {\\n \\\"signal\\\": \\\"{'App Family': datum.app_family, 'Tier': datum.tier, 'Component': datum.component, 'Component Cost': '$' + format(datum.value, ',.0f'), 'Total Cost': '$' + format(datum.total, ',.0f'), 'Instances': datum.instances}\\\"\\n }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"raw_all\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"total\\\", \\\"offset\\\": 4 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\", \\\"band\\\": 0.5 },\\n \\\"text\\\": { \\\"signal\\\": \\\"'$' + format(datum.total, ',.2s')\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e5e7eb\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"align\\\": { \\\"value\\\": \\\"left\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"raw_all\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": -4 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\", \\\"band\\\": 0.5 },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.instances > 0 ? '(' + format(datum.instances, ',.0f') + ')' : ''\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#6b7280\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 8 },\\n \\\"align\\\": { \\\"value\\\": \\\"right\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3b9211b0-164b-495c-b3b6-479193fe6c1e\",\"gridData\":{\"i\":\"3b9211b0-164b-495c-b3b6-479193fe6c1e\",\"y\":38,\"x\":17,\"w\":15,\"h\":20}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"26ab7837-9182-5ae8-9186-6a46abbd5428\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"PQC Priority Matrix \\u2014 Tier x App Family heatmap. Responsive, compact layout.\\\",\\n \\\"autosize\\\": { \\\"type\\\": \\\"fit\\\", \\\"contains\\\": \\\"padding\\\" },\\n \\\"padding\\\": { \\\"left\\\": 92, \\\"right\\\": 16, \\\"top\\\": 34, \\\"bottom\\\": 46 },\\n \\\"background\\\": \\\"#111111\\\",\\n\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"topN\\\", \\\"value\\\": 10 },\\n { \\\"name\\\": \\\"showCellText\\\", \\\"update\\\": \\\"bandwidth('yscale') >= 18 && bandwidth('xscale') >= 64\\\" }\\n ],\\n\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"matrix_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-system-readiness*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"quantum_assessment.app_group\\\" } },\\n \\\"aggs\\\": {\\n \\\"families\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.app_family\\\",\\n \\\"size\\\": 40\\n },\\n \\\"aggs\\\": {\\n \\\"tiers\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"quantum_readiness.cost_analysis.tier\\\",\\n \\\"size\\\": 5\\n },\\n \\\"aggs\\\": {\\n \\\"cost_sum\\\": {\\n \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.total_cost_usd\\\" }\\n },\\n \\\"instances_sum\\\": {\\n \\\"sum\\\": { \\\"field\\\": \\\"quantum_readiness.cost_analysis.instance_count\\\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.families.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum && datum.key && datum.tiers && datum.tiers.buckets\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app_family\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"tiers.buckets\\\"], \\\"as\\\": [\\\"tier_bucket\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.tier_bucket && datum.tier_bucket.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.tier_bucket.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cost\\\", \\\"expr\\\": \\\"isValid(datum.tier_bucket.cost_sum) ? datum.tier_bucket.cost_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"instances\\\", \\\"expr\\\": \\\"isValid(datum.tier_bucket.instances_sum) ? datum.tier_bucket.instances_sum.value : 0\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isFinite(datum.cost) && datum.cost >= 0\\\" }\\n ]\\n },\\n\\n {\\n \\\"name\\\": \\\"family_order\\\",\\n \\\"source\\\": \\\"matrix_raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"app_family\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"cost\\\"], \\\"as\\\": [\\\"family_total_cost\\\"] },\\n { \\\"type\\\": \\\"collect\\\", \\\"sort\\\": { \\\"field\\\": \\\"family_total_cost\\\", \\\"order\\\": \\\"descending\\\" } },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rank\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rank <= topN\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app_family_short\\\",\\n \\\"expr\\\": \\\"length(datum.app_family) > 14 ? substring(datum.app_family,0,11) + '...' : datum.app_family\\\"\\n }\\n ]\\n },\\n\\n {\\n \\\"name\\\": \\\"matrix\\\",\\n \\\"source\\\": \\\"matrix_raw\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"lookup\\\",\\n \\\"from\\\": \\\"family_order\\\",\\n \\\"key\\\": \\\"app_family\\\",\\n \\\"fields\\\": [\\\"app_family\\\"],\\n \\\"values\\\": [\\\"rank\\\", \\\"app_family_short\\\", \\\"family_total_cost\\\"],\\n \\\"as\\\": [\\\"rank\\\", \\\"app_family_short\\\", \\\"family_total_cost\\\"]\\n },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.rank)\\\" }\\n ]\\n }\\n ],\\n\\n \\\"scales\\\": [\\n {\\n \\\"name\\\": \\\"xscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": [\\\"LEGACY\\\", \\\"CLASSICAL\\\"],\\n \\\"range\\\": \\\"width\\\",\\n \\\"paddingInner\\\": 0.08,\\n \\\"paddingOuter\\\": 0.03\\n },\\n {\\n \\\"name\\\": \\\"yscale\\\",\\n \\\"type\\\": \\\"band\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"family_order\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"range\\\": \\\"height\\\",\\n \\\"paddingInner\\\": 0.08,\\n \\\"paddingOuter\\\": 0.03\\n },\\n {\\n \\\"name\\\": \\\"cscale\\\",\\n \\\"type\\\": \\\"linear\\\",\\n \\\"domain\\\": { \\\"data\\\": \\\"matrix\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"range\\\": [\\\"#1f2937\\\", \\\"#2563eb\\\", \\\"#7c3aed\\\", \\\"#dc2626\\\"],\\n \\\"nice\\\": true,\\n \\\"zero\\\": true\\n }\\n ],\\n\\n \\\"axes\\\": [\\n {\\n \\\"orient\\\": \\\"bottom\\\",\\n \\\"scale\\\": \\\"xscale\\\",\\n \\\"title\\\": \\\"Tier\\\",\\n \\\"titleColor\\\": \\\"#d1d5db\\\",\\n \\\"labelColor\\\": \\\"#d1d5db\\\",\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\"\\n },\\n {\\n \\\"orient\\\": \\\"left\\\",\\n \\\"scale\\\": \\\"yscale\\\",\\n \\\"title\\\": \\\"\\\",\\n \\\"labelColor\\\": \\\"#d1d5db\\\",\\n \\\"labelLimit\\\": 86,\\n \\\"tickColor\\\": \\\"#333333\\\",\\n \\\"domainColor\\\": \\\"#333333\\\"\\n }\\n ],\\n\\n \\\"legends\\\": [\\n {\\n \\\"fill\\\": \\\"cscale\\\",\\n \\\"title\\\": \\\"Cost\\\",\\n \\\"orient\\\": \\\"right\\\",\\n \\\"titleColor\\\": \\\"#d1d5db\\\",\\n \\\"labelColor\\\": \\\"#9ca3af\\\",\\n \\\"format\\\": \\\"$,.2s\\\"\\n }\\n ],\\n\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": -12 },\\n \\\"text\\\": { \\\"value\\\": \\\"PRIORITY MATRIX (TOP APP FAMILIES)\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#d1d5db\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"letterSpacing\\\": { \\\"value\\\": 0.8 }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"matrix\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"tier\\\" },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\" },\\n \\\"width\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"band\\\": 1 },\\n \\\"height\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"band\\\": 1 },\\n \\\"fill\\\": { \\\"scale\\\": \\\"cscale\\\", \\\"field\\\": \\\"cost\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#1a1a1a\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"tooltip\\\": {\\n \\\"signal\\\": \\\"{'App Family': datum.app_family, 'Tier': datum.tier, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Instances': format(datum.instances, ',.0f')}\\\"\\n }\\n }\\n }\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"matrix\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"scale\\\": \\\"xscale\\\", \\\"field\\\": \\\"tier\\\", \\\"band\\\": 0.5 },\\n \\\"y\\\": { \\\"scale\\\": \\\"yscale\\\", \\\"field\\\": \\\"app_family_short\\\", \\\"band\\\": 0.5 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#f9fafb\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"showCellText && datum.instances > 0 ? format(datum.instances, ',.0f') : ''\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"279b7812-2cf0-43a2-8c2f-410ab21ba53d\",\"gridData\":{\"i\":\"279b7812-2cf0-43a2-8c2f-410ab21ba53d\",\"y\":38,\"x\":32,\"w\":16,\"h\":20}}]", - "refreshInterval": { - "pause": true, - "value": 60000 - }, - "timeFrom": "now-24h/h", - "timeRestore": true, - "timeTo": "now", - "title": "[TYCHON Quantum Command] Cost Analysis", - "version": 3 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", - "managed": false, - "originId": "1f8dd314-b88a-4fca-aca2-091d52c84ab2", - "references": [ - { - "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", - "name": "279b7812-2cf0-43a2-8c2f-410ab21ba53d:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:26ab7837-9182-5ae8-9186-6a46abbd5428:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", - "name": "3b9211b0-164b-495c-b3b6-479193fe6c1e:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:702a251d-4e87-5dbc-8cf6-25f5098c4de7:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", - "name": "499d6919-5d84-47bf-8bff-653bbd5d0ecd:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:939918a5-e238-5f2d-88ff-e2f67ab75598:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "53bd2970-764a-498b-9632-f3e37a82d528:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:3a5225f5-247d-560e-b33f-876471396e3f:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", - "name": "e96a3b6f-c862-4732-94f6-635d6e64c5d7:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:39e70128-521d-50c8-913c-d745903e2b64:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", - "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", - "type": "tag" - }, - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", - "type": "tag" - } - ], - "type": "dashboard", - "typeMigrationVersion": "10.2.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NzMsMzBd" -} + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "references": [ + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "279b7812-2cf0-43a2-8c2f-410ab21ba53d:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:26ab7837-9182-5ae8-9186-6a46abbd5428:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "3b9211b0-164b-495c-b3b6-479193fe6c1e:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:702a251d-4e87-5dbc-8cf6-25f5098c4de7:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "name": "499d6919-5d84-47bf-8bff-653bbd5d0ecd:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:939918a5-e238-5f2d-88ff-e2f67ab75598:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "53bd2970-764a-498b-9632-f3e37a82d528:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:3a5225f5-247d-560e-b33f-876471396e3f:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "e96a3b6f-c862-4732-94f6-635d6e64c5d7:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:39e70128-521d-50c8-913c-d745903e2b64:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.3.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json index c5b5d22962b..2b8625376a8 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json @@ -1,63 +1,579 @@ { - "attributes": { - "controlGroupInput": { - "chainingSystem": "HIERARCHICAL", - "controlStyle": "oneLine", - "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", - "panelsJSON": "{}", - "showApplySelections": false + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": {}, + "showApplySelections": false + }, + "description": "Aligns to schema version 2.0.3", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": true, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": false + }, + "panelsJSON": [ + { + "embeddableConfig": { + "enhancements": {}, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "Inventory | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 3, + "i": "tychon-quantum-command-nav", + "w": 48, + "x": 0, + "y": 0 + }, + "panelIndex": "tychon-quantum-command-nav", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Cost Analysis" + }, + "eventId": "57dde807-dddf-51b2-832a-36d295102863", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"totalHosts\",\n \"update\": \"length(data('hosts_total'))\u003e0 ? data('hosts_total')[0].n : 0\"\n },\n {\n \"name\": \"osReady\",\n \"update\": \"length(data('os_pqc'))\u003e0 ? data('os_pqc')[0].n : 0\"\n },\n {\n \"name\": \"osPct\",\n \"update\": \"totalHosts \u003e 0 ? round(osReady / totalHosts * 100) : 0\"\n },\n {\n \"name\": \"osClr\",\n \"update\": \"osPct\u003e=90 ? '#00c853' : osPct\u003e=60 ? '#448aff' : osPct\u003e=30 ? '#ffa726' : '#ef5350'\"\n },\n {\n \"name\": \"kexReady\",\n \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"\n },\n {\n \"name\": \"kexPct\",\n \"update\": \"totalHosts \u003e 0 ? round(kexReady / totalHosts * 100) : 0\"\n },\n {\n \"name\": \"kexClr\",\n \"update\": \"kexPct\u003e=90 ? '#00c853' : kexPct\u003e=60 ? '#448aff' : kexPct\u003e=30 ? '#ffa726' : '#ef5350'\"\n },\n {\n \"name\": \"barW\",\n \"update\": \"width * 0.62 - 18\"\n }\n ],\n \"data\": [\n {\n \"name\": \"hosts_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"host.id\"}}}}\n },\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}\n ]\n },\n {\n \"name\": \"hosts_total\",\n \"source\": \"hosts_raw\"\n },\n {\n \"name\": \"os_pqc_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"host.os_pqc_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}\n ]\n },\n {\n \"name\": \"os_pqc\",\n \"source\": \"os_pqc_raw\"\n },\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}\n ]\n },\n {\n \"name\": \"kex_pqc\",\n \"source\": \"kex_pqc_raw\"\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 22},\n \"text\": {\"value\": \"QUANTUM READINESS REPORT\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 40},\n \"text\": {\"value\": \"PQC COMPLIANCE PROGRESS — unique hosts at PQC READY tier\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"osClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 78},\n \"text\": {\"value\": \"OS READINESS\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 93},\n \"text\": {\"signal\": \"(osReady\u003e=1000?format(osReady,'.3~s'):format(osReady,',')) + ' of ' + (totalHosts\u003e=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106},\n \"width\": {\"signal\": \"max(0, barW * osPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"osClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"osPct + '%'\"},\n \"fill\": {\"signal\": \"osClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 158},\n \"text\": {\"value\": \"KEY EXCHANGE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 173},\n \"text\": {\"signal\": \"(kexReady\u003e=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalHosts\u003e=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186},\n \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 14, + "i": "0ccceeab-cd4b-4170-99a4-8e45770e048b", + "w": 31, + "x": 0, + "y": 2 + }, + "panelIndex": "0ccceeab-cd4b-4170-99a4-8e45770e048b", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Certificate Operations" + }, + "eventId": "30c0b8ba-7a54-5cab-ac59-232baa7bb8b8", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\"name\": \"headerH\", \"value\": 48},\n {\"name\": \"maxR\", \"update\": \"min(width * 0.36, (height - headerH) / 2 - 10)\"},\n {\"name\": \"cx\", \"update\": \"width * 0.40\"},\n {\"name\": \"cy\", \"update\": \"headerH + (height - headerH) / 2\"},\n {\"name\": \"startA\", \"value\": -1.5707963},\n {\"name\": \"pi2\", \"value\": 6.2831853},\n {\"name\": \"lx\", \"update\": \"cx + maxR + 18\"},\n\n {\"name\": \"hostsTotal\", \"update\": \"length(data('hosts_total'))\u003e0 ? data('hosts_total')[0].n : 0\"},\n {\"name\": \"appsTotal\", \"update\": \"length(data('apps_total'))\u003e0 ? data('apps_total')[0].n : 0\"},\n\n {\"name\": \"osReady\", \"update\": \"length(data('os_pqc'))\u003e0 ? data('os_pqc')[0].n : 0\"},\n {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"},\n {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))\u003e0 ? data('sig_pqc')[0].n : 0\"},\n {\"name\": \"tlsReady\", \"update\": \"length(data('tls_pqc'))\u003e0 ? data('tls_pqc')[0].n : 0\"},\n\n {\"name\": \"osPct\", \"update\": \"hostsTotal \u003e 0 ? round(osReady / hostsTotal * 100) : 0\"},\n {\"name\": \"kexPct\", \"update\": \"appsTotal \u003e 0 ? round(kexReady / appsTotal * 100) : 0\"},\n {\"name\": \"sigPct\", \"update\": \"appsTotal \u003e 0 ? round(sigReady / appsTotal * 100) : 0\"},\n {\"name\": \"tlsPct\", \"update\": \"appsTotal \u003e 0 ? round(tlsReady / appsTotal * 100) : 0\"},\n\n {\"name\": \"overallPct\", \"update\": \"round((osPct + kexPct + sigPct + tlsPct) / 4)\"},\n\n {\"name\": \"osClr\", \"update\": \"osPct\u003e=90?'#00c853':osPct\u003e=60?'#448aff':osPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"kexClr\", \"update\": \"kexPct\u003e=90?'#00c853':kexPct\u003e=60?'#448aff':kexPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"sigClr\", \"update\": \"sigPct\u003e=90?'#00c853':sigPct\u003e=60?'#448aff':sigPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"tlsClr\", \"update\": \"tlsPct\u003e=90?'#00c853':tlsPct\u003e=60?'#448aff':tlsPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"overallClr\", \"update\": \"overallPct\u003e=90?'#00c853':overallPct\u003e=60?'#448aff':overallPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"overallLbl\", \"update\": \"overallPct\u003e=90?'PQC READY':overallPct\u003e=60?'MODERN':overallPct\u003e=30?'CLASSICAL':'LEGACY'\"},\n\n {\"name\": \"lg\", \"update\": \"(height - headerH) / 5\"},\n {\"name\": \"ly0\", \"update\": \"headerH + lg * 0.8\"},\n {\"name\": \"ly1\", \"update\": \"headerH + lg * 1.8\"},\n {\"name\": \"ly2\", \"update\": \"headerH + lg * 2.8\"},\n {\"name\": \"ly3\", \"update\": \"headerH + lg * 3.8\"}\n ],\n \"data\": [\n {\n \"name\": \"hosts_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"host.id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"hosts_total\", \"source\": \"hosts_raw\"},\n {\n \"name\": \"apps_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"apps_total\", \"source\": \"apps_raw\"},\n {\n \"name\": \"os_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"host.os_pqc_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"os_pqc\", \"source\": \"os_pqc_raw\"},\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"},\n {\n \"name\": \"sig_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"},\n {\n \"name\": \"tls_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"tls_pqc\", \"source\": \"tls_pqc_raw\"}\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 20},\n \"text\": {\"value\": \"CRYPTO POSTURE\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 38},\n \"text\": {\"value\": \"4-DIMENSION PQC READINESS SCORE\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 46},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.875\"}, \"outerRadius\": {\"signal\": \"maxR\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.875\"}, \"outerRadius\": {\"signal\": \"maxR\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"osPct \u003e 0 ? startA + osPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"osClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.655\"}, \"outerRadius\": {\"signal\": \"maxR * 0.8\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.655\"}, \"outerRadius\": {\"signal\": \"maxR * 0.8\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"kexPct \u003e 0 ? startA + kexPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"kexClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.435\"}, \"outerRadius\": {\"signal\": \"maxR * 0.58\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.435\"}, \"outerRadius\": {\"signal\": \"maxR * 0.58\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"sigPct \u003e 0 ? startA + sigPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"sigClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.215\"}, \"outerRadius\": {\"signal\": \"maxR * 0.36\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.215\"}, \"outerRadius\": {\"signal\": \"maxR * 0.36\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"tlsPct \u003e 0 ? startA + tlsPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"tlsClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + maxR * 0.06\"},\n \"text\": {\"signal\": \"overallPct + '%'\"},\n \"fill\": {\"signal\": \"overallClr\"},\n \"fontSize\": {\"signal\": \"max(14, maxR * 0.21)\"},\n \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"},\n \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + maxR * 0.24\"},\n \"text\": {\"value\": \"OVERALL\"},\n \"fill\": {\"value\": \"#2e2e2e\"}, \"fontSize\": {\"value\": 8},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy - maxR * 0.1\"},\n \"text\": {\"signal\": \"overallLbl\"},\n \"fill\": {\"signal\": \"overallClr + '44'\"},\n \"fontSize\": {\"value\": 7}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.5}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly0\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"osClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly0 + 12\"},\n \"text\": {\"value\": \"OS PLATFORM\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly0 + 26\"},\n \"text\": {\"value\": \"by host\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly0 + 20\"},\n \"text\": {\"signal\": \"osPct + '%'\"},\n \"fill\": {\"signal\": \"osClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly1\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly1 + 12\"},\n \"text\": {\"value\": \"KEY EXCHANGE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly1 + 26\"},\n \"text\": {\"value\": \"by application\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly1 + 20\"},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly2\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly2 + 12\"},\n \"text\": {\"value\": \"CERT SIGNATURE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly2 + 26\"},\n \"text\": {\"value\": \"by application\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly2 + 20\"},\n \"text\": {\"signal\": \"sigPct + '%'\"},\n \"fill\": {\"signal\": \"sigClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly3\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"tlsClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly3 + 12\"},\n \"text\": {\"value\": \"TLS VERSION\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly3 + 26\"},\n \"text\": {\"value\": \"TLS 1.3 required\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly3 + 20\"},\n \"text\": {\"signal\": \"tlsPct + '%'\"},\n \"fill\": {\"signal\": \"tlsClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 14, + "i": "63e69b30-7da2-4962-ad90-575262384727", + "w": 17, + "x": 31, + "y": 2 + }, + "panelIndex": "63e69b30-7da2-4962-ad90-575262384727", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "6801ef79-6e41-585d-b31a-e75702561c24", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum — harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve — quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH — quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy — deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "Quantum Inventory Report", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "df9e2eaf-bfe4-4443-9b68-c192dee2365a", + "w": 16, + "x": 0, + "y": 16 + }, + "panelIndex": "df9e2eaf-bfe4-4443-9b68-c192dee2365a", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.protocol_tier\", \"size\": 50}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"TLS 1.3\", \"lbl\": \"TLS 1.3\", \"desc\": \"Required for PQC key exchange — carries ML-KEM key_share\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"TLS 1.2\", \"lbl\": \"TLS 1.2\", \"desc\": \"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\", \"badge\": \"NO KEM EXT\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1},\n {\"t\": \"LEGACY\", \"lbl\": \"TLS 1.1 or below\", \"desc\": \"Deprecated — contains known protocol vulnerabilities, should be disabled\", \"badge\": \"DEPRECATED\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"TLS PROTOCOL VERSION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"PREFERRED PROTOCOL — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "b36ed613-82db-46d9-9173-888fa0d6a3f3", + "w": 15, + "x": 16, + "y": 16 + }, + "panelIndex": "b36ed613-82db-46d9-9173-888fa0d6a3f3", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 20}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature — quantum-resistant\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve signature — efficient, quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA signature — quantum-vulnerable via Shor's algorithm\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"Broken hash — deprecated by all modern standards\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "5c4c8a1f-627a-4bc5-8a2c-a45cbfc1cd5b", + "w": 17, + "x": 31, + "y": 16 + }, + "panelIndex": "5c4c8a1f-627a-4bc5-8a2c-a45cbfc1cd5b", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Windows 10\", \"Windows 11\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"Windows 11\", \"lbl\": \"Windows 11\", \"desc\": \"ML-KEM hybrid KEX in Schannel TLS 1.3 (24H2 / build 26100+) — native PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"Windows 10\", \"lbl\": \"Windows 10\", \"desc\": \"TLS 1.3 capable — no native PQC algorithm support in any release\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"WINDOWS WORKSTATIONS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 22, + "i": "2c4f3e75-eaf8-437c-8d64-17d896a31239", + "w": 16, + "x": 0, + "y": 35 + }, + "panelIndex": "2c4f3e75-eaf8-437c-8d64-17d896a31239", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Server 2025\", \"Server 2022\", \"Server 2019\", \"Server 2016\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"Server 2025\", \"lbl\": \"Windows Server 2025\", \"desc\": \"PQC-capable — ML-KEM and ML-DSA available via Windows CNG\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"Server 2022\", \"lbl\": \"Windows Server 2022\", \"desc\": \"TLS 1.3 default — no native PQC algorithm support in CNG\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"Server 2019\", \"lbl\": \"Windows Server 2019\", \"desc\": \"TLS 1.2/1.3 supported — no PQC, mainstream support ends Jan 2029\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"Server 2016\", \"lbl\": \"Windows Server 2016\", \"desc\": \"TLS 1.2 only — no PQC support, mainstream support ended Jan 2022\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"WINDOWS SERVER\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 22, + "i": "b7978898-3127-443e-91fa-cf36712fc0b0", + "w": 15, + "x": 16, + "y": 35 + }, + "panelIndex": "b7978898-3127-443e-91fa-cf36712fc0b0", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"macOS 26\", \"macOS 15\", \"macOS 14\", \"macOS 13\", \"macOS 12\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"macOS 26\", \"lbl\": \"macOS 26 Tahoe\", \"desc\": \"ML-KEM, ML-DSA, SLH-DSA native via Security.framework — full PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"macOS 15\", \"lbl\": \"macOS 15 Sequoia\", \"desc\": \"ML-KEM hybrid KEX via Network.framework — partial PQC, not FIPS 203/204 compliant\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"macOS 14\", \"lbl\": \"macOS 14 Sonoma\", \"desc\": \"TLS 1.3 default — no native PQC algorithm support in Security.framework\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2},\n {\"t\": \"macOS 13\", \"lbl\": \"macOS 13 Ventura\", \"desc\": \"TLS 1.3 default — no native PQC algorithm support in Security.framework\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 3},\n {\"t\": \"macOS 12\", \"lbl\": \"macOS 12 Monterey\", \"desc\": \"TLS 1.3 capable — older cipher defaults, no PQC support\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 4}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"MACOS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 22, + "i": "aa1550df-8d69-4c14-92fb-6566f846bfce", + "w": 17, + "x": 31, + "y": 35 + }, + "panelIndex": "aa1550df-8d69-4c14-92fb-6566f846bfce", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"CentOS 9\", \"CentOS 8\", \"CentOS 7\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"CentOS 9\", \"lbl\": \"CentOS Stream 9\", \"desc\": \"OpenSSL 3.x — TLS 1.3 default, OQS PQC provider available\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 0},\n {\"t\": \"CentOS 8\", \"lbl\": \"CentOS Stream 8\", \"desc\": \"EOL May 2024 — OpenSSL 1.1.1, TLS 1.3 supported, no PQC\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 1},\n {\"t\": \"CentOS 7\", \"lbl\": \"CentOS 7\", \"desc\": \"EOL Jun 2024 — OpenSSL 1.0.2, TLS 1.2 only, no PQC support\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CENTOS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 18, + "i": "2d7ed859-178e-419d-9500-bfc7e9ee1448", + "w": 16, + "x": 0, + "y": 57 + }, + "panelIndex": "2d7ed859-178e-419d-9500-bfc7e9ee1448", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"RHEL 10\", \"RHEL 9\", \"RHEL 8\", \"RHEL 7\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"RHEL 10\", \"lbl\": \"RHEL 10\", \"desc\": \"OpenSSL 3.5.x — ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"RHEL 9\", \"lbl\": \"RHEL 9\", \"desc\": \"OpenSSL 3.x — TLS 1.3 default, OQS PQC provider available separately\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"RHEL 8\", \"lbl\": \"RHEL 8\", \"desc\": \"OpenSSL 1.1.1 — TLS 1.3 supported, no native PQC support\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"RHEL 7\", \"lbl\": \"RHEL 7\", \"desc\": \"OpenSSL 1.0.2 — EOL Jun 2024, TLS 1.2 only, no PQC support\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"RED HAT ENTERPRISE LINUX\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 18, + "i": "2b788a90-8404-40ce-832e-cbe6cdc4bfb5", + "w": 15, + "x": 16, + "y": 57 + }, + "panelIndex": "2b788a90-8404-40ce-832e-cbe6cdc4bfb5", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Ubuntu 26.04\", \"Ubuntu 25.04\", \"Ubuntu 24.04\", \"Ubuntu 22.04\", \"Ubuntu 20.04\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"Ubuntu 26.04\", \"lbl\": \"Ubuntu 26.04 LTS\", \"desc\": \"OpenSSL 3.5.x — ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"Ubuntu 25.04\", \"lbl\": \"Ubuntu 25.04\", \"desc\": \"OpenSSL 3.4.x — ML-KEM/ML-DSA built-in, NIST PQC without oqs-provider\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 1},\n {\"t\": \"Ubuntu 24.04\", \"lbl\": \"Ubuntu 24.04 LTS\", \"desc\": \"OpenSSL 3.0.x — TLS 1.3 default, OQS PQC provider available separately\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2},\n {\"t\": \"Ubuntu 22.04\", \"lbl\": \"Ubuntu 22.04 LTS\", \"desc\": \"OpenSSL 3.0.x — TLS 1.3 default, no native PQC support\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 3},\n {\"t\": \"Ubuntu 20.04\", \"lbl\": \"Ubuntu 20.04 LTS\", \"desc\": \"OpenSSL 1.1.1 — TLS 1.3 capable, standard support ends Apr 2025\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 4}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"UBUNTU\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 18, + "i": "31106bc5-1c4d-4890-a085-22581cdc5f4c", + "w": 17, + "x": 31, + "y": 57 + }, + "panelIndex": "31106bc5-1c4d-4890-a085-22581cdc5f4c", + "type": "visualization" + } + ], + "timeRestore": false, + "title": "[TYCHON Quantum Command] Inventory", + "version": 3 }, - "description": "Aligns to schema version 2.0.3", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "optionsJSON": "{\"useMargins\":false,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":true}", - "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"Inventory | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"57dde807-dddf-51b2-832a-36d295102863\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"totalHosts\\\",\\n \\\"update\\\": \\\"length(data('hosts_total'))>0 ? data('hosts_total')[0].n : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"osReady\\\",\\n \\\"update\\\": \\\"length(data('os_pqc'))>0 ? data('os_pqc')[0].n : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"osPct\\\",\\n \\\"update\\\": \\\"totalHosts > 0 ? round(osReady / totalHosts * 100) : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"osClr\\\",\\n \\\"update\\\": \\\"osPct>=90 ? '#00c853' : osPct>=60 ? '#448aff' : osPct>=30 ? '#ffa726' : '#ef5350'\\\"\\n },\\n {\\n \\\"name\\\": \\\"kexReady\\\",\\n \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"kexPct\\\",\\n \\\"update\\\": \\\"totalHosts > 0 ? round(kexReady / totalHosts * 100) : 0\\\"\\n },\\n {\\n \\\"name\\\": \\\"kexClr\\\",\\n \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"\\n },\\n {\\n \\\"name\\\": \\\"barW\\\",\\n \\\"update\\\": \\\"width * 0.62 - 18\\\"\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"hosts_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"hosts_total\\\",\\n \\\"source\\\": \\\"hosts_raw\\\"\\n },\\n {\\n \\\"name\\\": \\\"os_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"host.os_pqc_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"os_pqc\\\",\\n \\\"source\\\": \\\"os_pqc_raw\\\"\\n },\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"kex_pqc\\\",\\n \\\"source\\\": \\\"kex_pqc_raw\\\"\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"QUANTUM READINESS REPORT\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"value\\\": \\\"PQC COMPLIANCE PROGRESS \\u2014 unique hosts at PQC READY tier\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"OS READINESS\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(osReady>=1000?format(osReady,'.3~s'):format(osReady,',')) + ' of ' + (totalHosts>=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * osPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"osPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalHosts>=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"0ccceeab-cd4b-4170-99a4-8e45770e048b\",\"gridData\":{\"i\":\"0ccceeab-cd4b-4170-99a4-8e45770e048b\",\"y\":2,\"x\":0,\"w\":31,\"h\":14}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"30c0b8ba-7a54-5cab-ac59-232baa7bb8b8\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Certificate Operations\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"headerH\\\", \\\"value\\\": 48},\\n {\\\"name\\\": \\\"maxR\\\", \\\"update\\\": \\\"min(width * 0.36, (height - headerH) / 2 - 10)\\\"},\\n {\\\"name\\\": \\\"cx\\\", \\\"update\\\": \\\"width * 0.40\\\"},\\n {\\\"name\\\": \\\"cy\\\", \\\"update\\\": \\\"headerH + (height - headerH) / 2\\\"},\\n {\\\"name\\\": \\\"startA\\\", \\\"value\\\": -1.5707963},\\n {\\\"name\\\": \\\"pi2\\\", \\\"value\\\": 6.2831853},\\n {\\\"name\\\": \\\"lx\\\", \\\"update\\\": \\\"cx + maxR + 18\\\"},\\n\\n {\\\"name\\\": \\\"hostsTotal\\\", \\\"update\\\": \\\"length(data('hosts_total'))>0 ? data('hosts_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"appsTotal\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n\\n {\\\"name\\\": \\\"osReady\\\", \\\"update\\\": \\\"length(data('os_pqc'))>0 ? data('os_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"tlsReady\\\", \\\"update\\\": \\\"length(data('tls_pqc'))>0 ? data('tls_pqc')[0].n : 0\\\"},\\n\\n {\\\"name\\\": \\\"osPct\\\", \\\"update\\\": \\\"hostsTotal > 0 ? round(osReady / hostsTotal * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"appsTotal > 0 ? round(kexReady / appsTotal * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"appsTotal > 0 ? round(sigReady / appsTotal * 100) : 0\\\"},\\n {\\\"name\\\": \\\"tlsPct\\\", \\\"update\\\": \\\"appsTotal > 0 ? round(tlsReady / appsTotal * 100) : 0\\\"},\\n\\n {\\\"name\\\": \\\"overallPct\\\", \\\"update\\\": \\\"round((osPct + kexPct + sigPct + tlsPct) / 4)\\\"},\\n\\n {\\\"name\\\": \\\"osClr\\\", \\\"update\\\": \\\"osPct>=90?'#00c853':osPct>=60?'#448aff':osPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90?'#00c853':kexPct>=60?'#448aff':kexPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90?'#00c853':sigPct>=60?'#448aff':sigPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"tlsClr\\\", \\\"update\\\": \\\"tlsPct>=90?'#00c853':tlsPct>=60?'#448aff':tlsPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"overallClr\\\", \\\"update\\\": \\\"overallPct>=90?'#00c853':overallPct>=60?'#448aff':overallPct>=30?'#ffa726':'#ef5350'\\\"},\\n {\\\"name\\\": \\\"overallLbl\\\", \\\"update\\\": \\\"overallPct>=90?'PQC READY':overallPct>=60?'MODERN':overallPct>=30?'CLASSICAL':'LEGACY'\\\"},\\n\\n {\\\"name\\\": \\\"lg\\\", \\\"update\\\": \\\"(height - headerH) / 5\\\"},\\n {\\\"name\\\": \\\"ly0\\\", \\\"update\\\": \\\"headerH + lg * 0.8\\\"},\\n {\\\"name\\\": \\\"ly1\\\", \\\"update\\\": \\\"headerH + lg * 1.8\\\"},\\n {\\\"name\\\": \\\"ly2\\\", \\\"update\\\": \\\"headerH + lg * 2.8\\\"},\\n {\\\"name\\\": \\\"ly3\\\", \\\"update\\\": \\\"headerH + lg * 3.8\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"hosts_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"hosts_total\\\", \\\"source\\\": \\\"hosts_raw\\\"},\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"os_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"host.os_pqc_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"os_pqc\\\", \\\"source\\\": \\\"os_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"tls_pqc_raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"tls_pqc\\\", \\\"source\\\": \\\"tls_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 20},\\n \\\"text\\\": {\\\"value\\\": \\\"CRYPTO POSTURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38},\\n \\\"text\\\": {\\\"value\\\": \\\"4-DIMENSION PQC READINESS SCORE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 46},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.875\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.875\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"osPct > 0 ? startA + osPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.655\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.8\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.655\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.8\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"kexPct > 0 ? startA + kexPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.435\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.58\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.435\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.58\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"sigPct > 0 ? startA + sigPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.215\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.36\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -1.5707963}, \\\"endAngle\\\": {\\\"value\\\": 4.7123890},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.215\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"maxR * 0.36\\\"},\\n \\\"startAngle\\\": {\\\"signal\\\": \\\"startA\\\"},\\n \\\"endAngle\\\": {\\\"signal\\\": \\\"tlsPct > 0 ? startA + tlsPct/100 * pi2 : startA\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"tlsClr\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + maxR * 0.06\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"overallPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"overallClr\\\"},\\n \\\"fontSize\\\": {\\\"signal\\\": \\\"max(14, maxR * 0.21)\\\"},\\n \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"baseline\\\": {\\\"value\\\": \\\"middle\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + maxR * 0.24\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"OVERALL\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#2e2e2e\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy - maxR * 0.1\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"overallLbl\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"overallClr + '44'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 7}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.5}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"OS PLATFORM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"by host\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly0 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"osPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"osClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"by application\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly1 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"by application\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly2 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3\\\"},\\n \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"signal\\\": \\\"lg * 0.6\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"tlsClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3 + 12\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"TLS VERSION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"lx + 9\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3 + 26\\\"},\\n \\\"text\\\": {\\\"value\\\": \\\"TLS 1.3 required\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 12\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"ly3 + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"tlsPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"tlsClr\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"63e69b30-7da2-4962-ad90-575262384727\",\"gridData\":{\"i\":\"63e69b30-7da2-4962-ad90-575262384727\",\"y\":2,\"x\":31,\"w\":17,\"h\":14}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"6801ef79-6e41-585d-b31a-e75702561c24\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Quantum Inventory Report\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 20}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-KEM / Kyber\\\", \\\"desc\\\": \\\"Post-quantum \\u2014 harvest-proof\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"X25519 / ECDHE\\\", \\\"desc\\\": \\\"Elliptic curve \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"DHE / DH\\\", \\\"desc\\\": \\\"Finite-field DH \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"RSA Key Exchange\\\", \\\"desc\\\": \\\"No forward secrecy \\u2014 deprecated\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"POST-QUANTUM CRYPTOGRAPHY READINESS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"df9e2eaf-bfe4-4443-9b68-c192dee2365a\",\"gridData\":{\"i\":\"df9e2eaf-bfe4-4443-9b68-c192dee2365a\",\"y\":16,\"x\":0,\"w\":16,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.protocol_tier\\\", \\\"size\\\": 50}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"TLS 1.3\\\", \\\"lbl\\\": \\\"TLS 1.3\\\", \\\"desc\\\": \\\"Required for PQC key exchange \\u2014 carries ML-KEM key_share\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"TLS 1.2\\\", \\\"lbl\\\": \\\"TLS 1.2\\\", \\\"desc\\\": \\\"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\\\", \\\"badge\\\": \\\"NO KEM EXT\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"TLS 1.1 or below\\\", \\\"desc\\\": \\\"Deprecated \\u2014 contains known protocol vulnerabilities, should be disabled\\\", \\\"badge\\\": \\\"DEPRECATED\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"TLS PROTOCOL VERSION\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"PREFERRED PROTOCOL \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"b36ed613-82db-46d9-9173-888fa0d6a3f3\",\"gridData\":{\"i\":\"b36ed613-82db-46d9-9173-888fa0d6a3f3\",\"y\":16,\"x\":16,\"w\":15,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 20}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature \\u2014 quantum-resistant\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve signature \\u2014 efficient, quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA signature \\u2014 quantum-vulnerable via Shor's algorithm\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"Broken hash \\u2014 deprecated by all modern standards\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"5c4c8a1f-627a-4bc5-8a2c-a45cbfc1cd5b\",\"gridData\":{\"i\":\"5c4c8a1f-627a-4bc5-8a2c-a45cbfc1cd5b\",\"y\":16,\"x\":31,\"w\":17,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"Windows 10\\\", \\\"Windows 11\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"Windows 11\\\", \\\"lbl\\\": \\\"Windows 11\\\", \\\"desc\\\": \\\"ML-KEM hybrid KEX in Schannel TLS 1.3 (24H2 / build 26100+) \\u2014 native PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"Windows 10\\\", \\\"lbl\\\": \\\"Windows 10\\\", \\\"desc\\\": \\\"TLS 1.3 capable \\u2014 no native PQC algorithm support in any release\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"WINDOWS WORKSTATIONS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"2c4f3e75-eaf8-437c-8d64-17d896a31239\",\"gridData\":{\"i\":\"2c4f3e75-eaf8-437c-8d64-17d896a31239\",\"y\":35,\"x\":0,\"w\":16,\"h\":22}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"Server 2025\\\", \\\"Server 2022\\\", \\\"Server 2019\\\", \\\"Server 2016\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"Server 2025\\\", \\\"lbl\\\": \\\"Windows Server 2025\\\", \\\"desc\\\": \\\"PQC-capable \\u2014 ML-KEM and ML-DSA available via Windows CNG\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"Server 2022\\\", \\\"lbl\\\": \\\"Windows Server 2022\\\", \\\"desc\\\": \\\"TLS 1.3 default \\u2014 no native PQC algorithm support in CNG\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"Server 2019\\\", \\\"lbl\\\": \\\"Windows Server 2019\\\", \\\"desc\\\": \\\"TLS 1.2/1.3 supported \\u2014 no PQC, mainstream support ends Jan 2029\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"Server 2016\\\", \\\"lbl\\\": \\\"Windows Server 2016\\\", \\\"desc\\\": \\\"TLS 1.2 only \\u2014 no PQC support, mainstream support ended Jan 2022\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"WINDOWS SERVER\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"b7978898-3127-443e-91fa-cf36712fc0b0\",\"gridData\":{\"i\":\"b7978898-3127-443e-91fa-cf36712fc0b0\",\"y\":35,\"x\":16,\"w\":15,\"h\":22}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"macOS 26\\\", \\\"macOS 15\\\", \\\"macOS 14\\\", \\\"macOS 13\\\", \\\"macOS 12\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"macOS 26\\\", \\\"lbl\\\": \\\"macOS 26 Tahoe\\\", \\\"desc\\\": \\\"ML-KEM, ML-DSA, SLH-DSA native via Security.framework \\u2014 full PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"macOS 15\\\", \\\"lbl\\\": \\\"macOS 15 Sequoia\\\", \\\"desc\\\": \\\"ML-KEM hybrid KEX via Network.framework \\u2014 partial PQC, not FIPS 203/204 compliant\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"macOS 14\\\", \\\"lbl\\\": \\\"macOS 14 Sonoma\\\", \\\"desc\\\": \\\"TLS 1.3 default \\u2014 no native PQC algorithm support in Security.framework\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"macOS 13\\\", \\\"lbl\\\": \\\"macOS 13 Ventura\\\", \\\"desc\\\": \\\"TLS 1.3 default \\u2014 no native PQC algorithm support in Security.framework\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 3},\\n {\\\"t\\\": \\\"macOS 12\\\", \\\"lbl\\\": \\\"macOS 12 Monterey\\\", \\\"desc\\\": \\\"TLS 1.3 capable \\u2014 older cipher defaults, no PQC support\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 4}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"MACOS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"aa1550df-8d69-4c14-92fb-6566f846bfce\",\"gridData\":{\"i\":\"aa1550df-8d69-4c14-92fb-6566f846bfce\",\"y\":35,\"x\":31,\"w\":17,\"h\":22}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"CentOS 9\\\", \\\"CentOS 8\\\", \\\"CentOS 7\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"CentOS 9\\\", \\\"lbl\\\": \\\"CentOS Stream 9\\\", \\\"desc\\\": \\\"OpenSSL 3.x \\u2014 TLS 1.3 default, OQS PQC provider available\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"CentOS 8\\\", \\\"lbl\\\": \\\"CentOS Stream 8\\\", \\\"desc\\\": \\\"EOL May 2024 \\u2014 OpenSSL 1.1.1, TLS 1.3 supported, no PQC\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CentOS 7\\\", \\\"lbl\\\": \\\"CentOS 7\\\", \\\"desc\\\": \\\"EOL Jun 2024 \\u2014 OpenSSL 1.0.2, TLS 1.2 only, no PQC support\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CENTOS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"2d7ed859-178e-419d-9500-bfc7e9ee1448\",\"gridData\":{\"i\":\"2d7ed859-178e-419d-9500-bfc7e9ee1448\",\"y\":57,\"x\":0,\"w\":16,\"h\":18}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"RHEL 10\\\", \\\"RHEL 9\\\", \\\"RHEL 8\\\", \\\"RHEL 7\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"RHEL 10\\\", \\\"lbl\\\": \\\"RHEL 10\\\", \\\"desc\\\": \\\"OpenSSL 3.5.x \\u2014 ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"RHEL 9\\\", \\\"lbl\\\": \\\"RHEL 9\\\", \\\"desc\\\": \\\"OpenSSL 3.x \\u2014 TLS 1.3 default, OQS PQC provider available separately\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"RHEL 8\\\", \\\"lbl\\\": \\\"RHEL 8\\\", \\\"desc\\\": \\\"OpenSSL 1.1.1 \\u2014 TLS 1.3 supported, no native PQC support\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"RHEL 7\\\", \\\"lbl\\\": \\\"RHEL 7\\\", \\\"desc\\\": \\\"OpenSSL 1.0.2 \\u2014 EOL Jun 2024, TLS 1.2 only, no PQC support\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"RED HAT ENTERPRISE LINUX\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"2b788a90-8404-40ce-832e-cbe6cdc4bfb5\",\"gridData\":{\"i\":\"2b788a90-8404-40ce-832e-cbe6cdc4bfb5\",\"y\":57,\"x\":16,\"w\":15,\"h\":18}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"host.os_category\\\", \\\"size\\\": 20, \\\"include\\\": [\\\"Ubuntu 26.04\\\", \\\"Ubuntu 25.04\\\", \\\"Ubuntu 24.04\\\", \\\"Ubuntu 22.04\\\", \\\"Ubuntu 20.04\\\"]}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"Ubuntu 26.04\\\", \\\"lbl\\\": \\\"Ubuntu 26.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 3.5.x \\u2014 ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"Ubuntu 25.04\\\", \\\"lbl\\\": \\\"Ubuntu 25.04\\\", \\\"desc\\\": \\\"OpenSSL 3.4.x \\u2014 ML-KEM/ML-DSA built-in, NIST PQC without oqs-provider\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"Ubuntu 24.04\\\", \\\"lbl\\\": \\\"Ubuntu 24.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 3.0.x \\u2014 TLS 1.3 default, OQS PQC provider available separately\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"Ubuntu 22.04\\\", \\\"lbl\\\": \\\"Ubuntu 22.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 3.0.x \\u2014 TLS 1.3 default, no native PQC support\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 3},\\n {\\\"t\\\": \\\"Ubuntu 20.04\\\", \\\"lbl\\\": \\\"Ubuntu 20.04 LTS\\\", \\\"desc\\\": \\\"OpenSSL 1.1.1 \\u2014 TLS 1.3 capable, standard support ends Apr 2025\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 4}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"UBUNTU\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"OS VERSION \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.60-18\\\"}, \\\"ellipsis\\\": \\\"\\u2026\\\",\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"31106bc5-1c4d-4890-a085-22581cdc5f4c\",\"gridData\":{\"i\":\"31106bc5-1c4d-4890-a085-22581cdc5f4c\",\"y\":57,\"x\":31,\"w\":17,\"h\":18}}]", - "timeRestore": false, - "title": "[TYCHON Quantum Command] Inventory", - "version": 3 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", - "managed": false, - "originId": "12463d6e-8b26-40da-8b6f-b477801b0de2", - "references": [ - { - "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", - "name": "0ccceeab-cd4b-4170-99a4-8e45770e048b:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:57dde807-dddf-51b2-832a-36d295102863:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", - "name": "63e69b30-7da2-4962-ad90-575262384727:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:30c0b8ba-7a54-5cab-ac59-232baa7bb8b8:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "df9e2eaf-bfe4-4443-9b68-c192dee2365a:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:6801ef79-6e41-585d-b31a-e75702561c24:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-dacb217e-57b4-4296-8545-cbf6b5739344", - "type": "tag" - }, - { - "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", - "name": "tag-ref-e9b715ba-5f19-4f99-b837-2c1a24143212", - "type": "tag" - } - ], - "type": "dashboard", - "typeMigrationVersion": "10.2.0", - "updated_at": "2026-06-11T17:21:07.71Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY2MjUsMzBd" -} + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "references": [ + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "0ccceeab-cd4b-4170-99a4-8e45770e048b:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:57dde807-dddf-51b2-832a-36d295102863:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "name": "63e69b30-7da2-4962-ad90-575262384727:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:30c0b8ba-7a54-5cab-ac59-232baa7bb8b8:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "df9e2eaf-bfe4-4443-9b68-c192dee2365a:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:6801ef79-6e41-585d-b31a-e75702561c24:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.3.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json index a66869e78ac..35fc7f30977 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json @@ -1,134 +1,2533 @@ { - "attributes": { - "controlGroupInput": { - "chainingSystem": "HIERARCHICAL", - "controlStyle": "oneLine", - "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", - "panelsJSON": "{}", - "showApplySelections": false + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": {}, + "showApplySelections": false + }, + "description": "Aligns to schema 2.0.3.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": false, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": false + }, + "panelsJSON": [ + { + "embeddableConfig": { + "enhancements": {}, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | Application Report | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 3, + "i": "tychon-quantum-command-nav", + "w": 48, + "x": 0, + "y": 0 + }, + "panelIndex": "tychon-quantum-command-nav", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum — harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve — quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH — quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy — deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "b5127f43-801b-4411-a631-e5c71ca96645", + "w": 16, + "x": 0, + "y": 2 + }, + "panelIndex": "b5127f43-801b-4411-a631-e5c71ca96645", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\"name\": \"totalApps\", \"update\": \"length(data('apps_total'))\u003e0 ? data('apps_total')[0].n : 0\"},\n {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"},\n {\"name\": \"kexPct\", \"update\": \"totalApps \u003e 0 ? round(kexReady / totalApps * 100) : 0\"},\n {\"name\": \"kexClr\", \"update\": \"kexPct\u003e=90 ? '#00c853' : kexPct\u003e=60 ? '#448aff' : kexPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"protoReady\", \"update\": \"length(data('proto_pqc'))\u003e0 ? data('proto_pqc')[0].n : 0\"},\n {\"name\": \"protoPct\", \"update\": \"totalApps \u003e 0 ? round(protoReady / totalApps * 100) : 0\"},\n {\"name\": \"protoClr\", \"update\": \"protoPct\u003e=90 ? '#00c853' : protoPct\u003e=60 ? '#448aff' : protoPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))\u003e0 ? data('sig_pqc')[0].n : 0\"},\n {\"name\": \"sigPct\", \"update\": \"totalApps \u003e 0 ? round(sigReady / totalApps * 100) : 0\"},\n {\"name\": \"sigClr\", \"update\": \"sigPct\u003e=90 ? '#00c853' : sigPct\u003e=60 ? '#448aff' : sigPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"barW\", \"update\": \"width * 0.62 - 18\"}\n ],\n \"data\": [\n {\n \"name\": \"apps_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}\n },\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"apps_total\", \"source\": \"apps_raw\"},\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"},\n {\n \"name\": \"proto_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"proto_pqc\", \"source\": \"proto_pqc_raw\"},\n {\n \"name\": \"sig_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"}\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 22},\n \"text\": {\"value\": \"APPLICATION PQC DASHBOARD\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 40},\n \"text\": {\"signal\": \"'PQC COMPLIANCE PROGRESS — ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 78},\n \"text\": {\"value\": \"KEX COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 93},\n \"text\": {\"signal\": \"(kexReady\u003e=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY key exchange'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106},\n \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 158},\n \"text\": {\"value\": \"PROTOCOL COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 173},\n \"text\": {\"signal\": \"(protoReady\u003e=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — TLS 1.3 capable'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186},\n \"width\": {\"signal\": \"max(0, barW * protoPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202},\n \"text\": {\"signal\": \"protoPct + '%'\"},\n \"fill\": {\"signal\": \"protoClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 218},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 238},\n \"text\": {\"value\": \"CERT SIGNATURE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 253},\n \"text\": {\"signal\": \"(sigReady\u003e=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY signature'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266},\n \"width\": {\"signal\": \"max(0, barW * sigPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 282},\n \"text\": {\"signal\": \"sigPct + '%'\"},\n \"fill\": {\"signal\": \"sigClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "1192b05f-8047-4601-ba71-3f601169574b", + "w": 15, + "x": 16, + "y": 2 + }, + "panelIndex": "1192b05f-8047-4601-ba71-3f601169574b", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 20}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature — quantum-resistant\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve signature — efficient, quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA signature — quantum-vulnerable via Shor's algorithm\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"Broken hash — deprecated by all modern standards\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "3b53c655-5c7c-4910-9b19-657d22031234", + "w": 17, + "x": 31, + "y": 2 + }, + "panelIndex": "3b53c655-5c7c-4910-9b19-657d22031234", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [\n {\n \"events\": {\"type\": \"click\", \"markname\": \"rowBg\"},\n \"update\": \"datum.family === sel ? null : datum.family\",\n \"force\": true\n }\n ]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [\n {\n \"events\": {\"type\": \"click\", \"markname\": \"rowBg\"},\n \"update\": \"datum.family === sel ? kibanaRemoveFilter({'terms': {'process.name': datum.filterTerms}}) : kibanaAddFilter({'terms': {'process.name': datum.filterTerms}})\",\n \"force\": true\n }\n ]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"procs\": {\n \"terms\": {\"field\": \"process.name\", \"size\": 80},\n \"aggs\": {\n \"kex\": {\n \"terms\": {\"field\": \"omb.kex_tier\", \"size\": 5},\n \"aggs\": {\"thosts\": {\"cardinality\": {\"field\": \"host.id\"}}}\n }\n }\n }\n }\n }\n },\n \"format\": {\"property\": \"aggregations.procs.buckets\"},\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"family\",\n \"expr\": \"lower(datum.key)==='w3wp.exe'||lower(datum.key)==='iisexpress.exe'||lower(datum.key)==='inetinfo.exe' ? 'IIS' : lower(datum.key)==='node'||lower(datum.key)==='node.exe'||lower(datum.key)==='nodejs'||lower(datum.key)==='nodejs.exe' ? 'Node.js' : lower(datum.key)==='apache2'||lower(datum.key)==='httpd'||lower(datum.key)==='apache'||lower(datum.key)==='httpd.exe'||lower(datum.key)==='apache.exe'||lower(datum.key)==='httpd.worker' ? 'Apache' : lower(datum.key)==='nginx'||lower(datum.key)==='nginx.exe'||lower(datum.key)==='nginx-debug'||lower(datum.key)==='openresty' ? 'Nginx' : lower(datum.key)==='jsvc'||lower(datum.key)==='tomcat'||lower(datum.key)==='tomcat.exe'||lower(datum.key)==='tomcat9'||lower(datum.key)==='tomcat9.exe'||lower(datum.key)==='tomcat10'||lower(datum.key)==='tomcat10.exe'||lower(datum.key)==='tomcat8'||lower(datum.key)==='tomcat8.exe'||lower(datum.key)==='tomcat7'||lower(datum.key)==='tomcat7.exe'||lower(datum.key)==='catalina'||lower(datum.key)==='catalina.sh' ? 'Tomcat' : lower(datum.key)==='dotnet'||lower(datum.key)==='dotnet.exe' ? '.NET / Kestrel' : lower(datum.key)==='caddy'||lower(datum.key)==='caddy.exe' ? 'Caddy' : lower(datum.key)==='traefik'||lower(datum.key)==='traefik.exe' ? 'Traefik' : lower(datum.key)==='haproxy' ? 'HAProxy' : lower(datum.key)==='gunicorn' ? 'Gunicorn' : lower(datum.key)==='uwsgi' ? 'uWSGI' : lower(datum.key)==='puma'||lower(datum.key)==='passenger'||lower(datum.key)==='passenger-ruby' ? 'Puma' : lower(datum.key)==='varnishd' ? 'Varnish' : lower(datum.key)==='lighttpd' ? 'Lighttpd' : lower(datum.key)==='java'||lower(datum.key)==='java.exe'||lower(datum.key)==='javaw.exe' ? 'Java App Server' : 'Other'\"\n },\n {\"type\": \"filter\", \"expr\": \"datum.family != null\"}\n ]\n },\n {\n \"name\": \"mapped\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"flatten\", \"fields\": [\"kex.buckets\"], \"as\": [\"tb\"]},\n {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.tb.key\"},\n {\"type\": \"formula\", \"as\": \"tier_h\", \"expr\": \"datum.tb.thosts ? datum.tb.thosts.value : 0\"},\n {\"type\": \"formula\", \"as\": \"tier_ord\", \"expr\": \"datum.tier==='LEGACY' ? 0 : datum.tier==='CLASSICAL' ? 1 : datum.tier==='MODERN' ? 2 : datum.tier==='PQC READY' ? 3 : 4\"}\n ]\n },\n {\n \"name\": \"by_ft\",\n \"source\": \"mapped\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\", \"tier\", \"tier_ord\"],\n \"fields\": [\"tier_h\"],\n \"ops\": [\"sum\"],\n \"as\": [\"tier_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_totals\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\"],\n \"fields\": [\"tier_total\"],\n \"ops\": [\"sum\"],\n \"as\": [\"fam_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_risk\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\"type\": \"filter\", \"expr\": \"datum.tier === 'LEGACY' || datum.tier === 'CLASSICAL'\"},\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\"],\n \"fields\": [\"tier_total\"],\n \"ops\": [\"sum\"],\n \"as\": [\"risk_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_pqc\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\"type\": \"filter\", \"expr\": \"datum.tier === 'PQC READY'\"},\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\"],\n \"fields\": [\"tier_total\"],\n \"ops\": [\"sum\"],\n \"as\": [\"pqc_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_rows\",\n \"source\": \"fam_totals\",\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"fam_risk\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"risk_total\"], \"default\": 0},\n {\"type\": \"lookup\", \"from\": \"fam_pqc\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"pqc_total\"], \"default\": 0},\n {\n \"type\": \"formula\",\n \"as\": \"clr\",\n \"expr\": \"datum.family==='IIS' ? '#0078d4' : datum.family==='Node.js' ? '#68a063' : datum.family==='Apache' ? '#d22128' : datum.family==='Nginx' ? '#009900' : datum.family==='Tomcat' ? '#f8a51a' : datum.family==='.NET / Kestrel' ? '#7b5ea7' : datum.family==='Caddy' ? '#00acd7' : datum.family==='Traefik' ? '#24a1c1' : datum.family==='HAProxy' ? '#7db8e8' : datum.family==='Gunicorn' ? '#499848' : datum.family==='uWSGI' ? '#cc4125' : datum.family==='Puma' ? '#e040fb' : datum.family==='Varnish' ? '#ff6d00' : datum.family==='Lighttpd' ? '#909090' : datum.family==='Java App Server' ? '#c7a008' : '#666666'\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"filterTerms\",\n \"expr\": \"datum.family==='IIS' ? ['w3wp.exe','iisexpress.exe','inetinfo.exe'] : datum.family==='Node.js' ? ['node','node.exe','nodejs','nodejs.exe'] : datum.family==='Apache' ? ['apache2','httpd','apache','httpd.exe','apache.exe','httpd.worker'] : datum.family==='Nginx' ? ['nginx','nginx.exe','nginx-debug','openresty'] : datum.family==='Tomcat' ? ['jsvc','tomcat','tomcat.exe','tomcat9','tomcat9.exe','tomcat10','tomcat10.exe','tomcat8','tomcat8.exe','tomcat7','tomcat7.exe','catalina','catalina.sh'] : datum.family==='.NET / Kestrel' ? ['dotnet','dotnet.exe'] : datum.family==='Caddy' ? ['caddy','caddy.exe'] : datum.family==='Traefik' ? ['traefik','traefik.exe'] : datum.family==='HAProxy' ? ['haproxy'] : datum.family==='Gunicorn' ? ['gunicorn'] : datum.family==='uWSGI' ? ['uwsgi'] : datum.family==='Puma' ? ['puma','passenger','passenger-ruby'] : datum.family==='Varnish' ? ['varnishd'] : datum.family==='Lighttpd' ? ['lighttpd'] : datum.family==='Java App Server' ? ['java','java.exe','javaw.exe'] : [datum.family]\"\n },\n {\"type\": \"collect\", \"sort\": {\"field\": \"risk_total\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rowIdx\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rowIdx - 1) * 38 + 52\"}\n ]\n },\n {\n \"name\": \"stacked\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"fam_rows\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"y\", \"fam_total\", \"risk_total\"]},\n {\"type\": \"filter\", \"expr\": \"datum.y != null\"},\n {\"type\": \"formula\", \"as\": \"tier_clr\", \"expr\": \"datum.tier==='LEGACY' ? '#ef5350' : datum.tier==='CLASSICAL' ? '#ffa726' : datum.tier==='MODERN' ? '#42a5f5' : datum.tier==='PQC READY' ? '#66bb6a' : '#555555'\"},\n {\"type\": \"joinaggregate\", \"fields\": [\"fam_total\"], \"ops\": [\"max\"], \"as\": [\"max_fam\"]},\n {\n \"type\": \"window\",\n \"groupby\": [\"family\"],\n \"sort\": {\"field\": \"tier_ord\", \"order\": \"ascending\"},\n \"ops\": [\"sum\"],\n \"fields\": [\"tier_total\"],\n \"as\": [\"cumul\"]\n }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"WEB SERVER DISTRIBUTION\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 30},\n \"text\": {\"value\": \"HOSTS BY SERVER FAMILY \u0026 PQC KEX TIER · sorted by at-risk count · click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 170}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#ef5350\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 180}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"LEGACY\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 228}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#ffa726\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 238}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"CLASSICAL\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 300}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#42a5f5\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 310}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"MODERN\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 362}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#66bb6a\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 372}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"PQC READY\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 50},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"name\": \"rowBg\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"},\n \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 37},\n \"fill\": {\"signal\": \"datum.family===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"},\n \"width\": {\"value\": 4}, \"height\": {\"value\": 37},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 14\"},\n \"text\": {\"field\": \"family\"}, \"limit\": {\"value\": 148},\n \"fill\": {\"signal\": \"datum.family===sel ? '#ffffff' : '#e8e8e8'\"},\n \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 170}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"width\": {\"signal\": \"width - 245\"}, \"height\": {\"value\": 8},\n \"fill\": {\"value\": \"#1e1e1e\"}, \"cornerRadius\": {\"value\": 2}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"stacked\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"170 + ((datum.cumul - datum.tier_total) / (datum.max_fam \u003e 0 ? datum.max_fam : 1)) * (width - 245)\"},\n \"x2\": {\"signal\": \"170 + (datum.cumul / (datum.max_fam \u003e 0 ? datum.max_fam : 1)) * (width - 245)\"},\n \"y\": {\"signal\": \"datum.y + 22\"},\n \"height\": {\"value\": 8},\n \"fill\": {\"field\": \"tier_clr\"},\n \"fillOpacity\": {\"signal\": \"datum.family===sel ? 1 : 0.8\"},\n \"cornerRadius\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 14\"},\n \"text\": {\"signal\": \"datum.fam_total \u003e= 1000 ? format(datum.fam_total, '.3~s') : format(datum.fam_total, ',')\"},\n \"fill\": {\"signal\": \"datum.family===sel ? datum.clr : '#cccccc'\"},\n \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"},\n \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 35\"},\n \"text\": {\"signal\": \"datum.risk_total \u003e 0 ? format(datum.risk_total, ',') + ' AT RISK' : datum.pqc_total \u003e 0 ? 'PQC READY' : 'NOT PQC READY'\"},\n \"fill\": {\"signal\": \"datum.risk_total \u003e 0 ? '#ef5350' : datum.pqc_total \u003e 0 ? '#66bb6a' : '#ffa726'\"},\n \"fontSize\": {\"value\": 7}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"},\n \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 37\"},\n \"stroke\": {\"value\": \"#1e1e1e\"}, \"strokeWidth\": {\"value\": 1}\n }}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "0634e4b1-c33f-45ed-a33c-ba3937c4ed1f", + "w": 26, + "x": 0, + "y": 21 + }, + "panelIndex": "0634e4b1-c33f-45ed-a33c-ba3937c4ed1f", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "9110ccf0-1795-4d13-bab1-9a55f24a24a6": { + "columnOrder": [ + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0" + ], + "columns": { + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "App Process Count", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "process.executable" + }, + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Weak Cipher", + "operationType": "terms", + "params": { + "exclude": [ + "svchost.exe", + "dllhost.exe" + ], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 999 + }, + "scale": "ordinal", + "sourceField": "tls.weak_ciphers" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "isTransposed": false, + "oneClickFilter": true, + "width": 314 + }, + { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "isTransposed": false + } + ], + "layerId": "9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Detail" + }, + "eventId": "9c6edb36-c71b-5cf1-8dcd-a37de6214334", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 19, + "i": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657", + "w": 11, + "x": 26, + "y": 21 + }, + "panelIndex": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657", + "title": "Weak Ciphers In-Use", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "9110ccf0-1795-4d13-bab1-9a55f24a24a6": { + "columnOrder": [ + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0" + ], + "columns": { + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "App Count ", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "process.executable" + }, + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Insecure Cipher", + "operationType": "terms", + "params": { + "exclude": [ + "svchost.exe", + "dllhost.exe" + ], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 999 + }, + "scale": "ordinal", + "sourceField": "tls.insecure_ciphers" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "isTransposed": false, + "oneClickFilter": true + }, + { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "isTransposed": false + } + ], + "layerId": "9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Detail" + }, + "eventId": "b0c9f1de-0afd-5b7d-b3a1-fb28c055a10a", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 19, + "i": "ae78c400-d497-4d7f-9541-3e14fb724097", + "w": 11, + "x": 37, + "y": 21 + }, + "panelIndex": "ae78c400-d497-4d7f-9541-3e14fb724097", + "title": "Insecure Ciphers In-Use", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-8e8a2d62-de50-4140-91d5-4d323f4bfe51", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "8e8a2d62-de50-4140-91d5-4d323f4bfe51": { + "columnOrder": [ + "b9ce2593-2e18-4a93-997b-fea289547d59", + "119c83a6-13f7-4470-b14e-00f524c8f68c", + "57ed4372-97b0-41ed-a161-eb151f832cdb" + ], + "columns": { + "119c83a6-13f7-4470-b14e-00f524c8f68c": { + "customLabel": true, + "dataType": "number", + "filter": { + "language": "kuery", + "query": "omb.kex_primary_quantum_safe : false " + }, + "isBucketed": false, + "label": "Not Resilient", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "process.name" + }, + "57ed4372-97b0-41ed-a161-eb151f832cdb": { + "customLabel": true, + "dataType": "number", + "filter": { + "language": "kuery", + "query": "omb.kex_primary_quantum_safe : true " + }, + "isBucketed": false, + "label": "Quantum Resilient ", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "process.name" + }, + "b9ce2593-2e18-4a93-997b-fea289547d59": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Port Number", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "119c83a6-13f7-4470-b14e-00f524c8f68c", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 999 + }, + "scale": "ordinal", + "sourceField": "server.port" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "timeField": "@timestamp", + "title": "tychon-pqc*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "alignment": "center", + "columnId": "b9ce2593-2e18-4a93-997b-fea289547d59" + }, + { + "columnId": "119c83a6-13f7-4470-b14e-00f524c8f68c", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "57ed4372-97b0-41ed-a161-eb151f832cdb", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "8e8a2d62-de50-4140-91d5-4d323f4bfe51", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Connections Topology" + }, + "eventId": "0ba322cf-440b-5ad3-a615-62aad7cf634c", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 19, + "i": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091", + "w": 10, + "x": 0, + "y": 40 + }, + "panelIndex": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091", + "title": "Port Usage", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "9110ccf0-1795-4d13-bab1-9a55f24a24a6": { + "columnOrder": [ + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0" + ], + "columns": { + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Host Count", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Software Package Name", + "operationType": "terms", + "params": { + "exclude": [ + "svchost.exe", + "dllhost.exe" + ], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 999 + }, + "scale": "ordinal", + "sourceField": "process.name" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "tychon.index : \"inventory\" and quantum_ready: false " + }, + "visualization": { + "columns": [ + { + "columnId": "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "isTransposed": false, + "oneClickFilter": true + }, + { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "isTransposed": false + } + ], + "layerId": "9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Detail" + }, + "eventId": "d46a3ff4-c28b-57a1-a225-f58957519288", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "tychon.index : \"inventory\" and quantum_ready: false " + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 19, + "i": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1", + "w": 16, + "x": 10, + "y": 40 + }, + "panelIndex": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1", + "title": "Vulnerable Software", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "9110ccf0-1795-4d13-bab1-9a55f24a24a6": { + "columnOrder": [ + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0" + ], + "columns": { + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "App Count ", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "process.executable" + }, + "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Key Exchange", + "operationType": "terms", + "params": { + "exclude": [ + ".*(mlkem|ffdh).*" + ], + "excludeIsRegex": true, + "include": [ + "" + ], + "includeIsRegex": true, + "missingBucket": false, + "orderBy": { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 999 + }, + "scale": "ordinal", + "sourceField": "tls.supported_key_exchanges" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "omb.kex_tier", + "index": "9d644013-9636-4968-9154-38f0c5207120", + "key": "omb.kex_tier", + "negate": true, + "params": { + "query": "PQC READY" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "omb.kex_tier": "PQC READY" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "9c1ef140-d9ad-40dd-b4f7-5fffeb57893c", + "isTransposed": false, + "oneClickFilter": true, + "width": 314 + }, + { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "isTransposed": false + } + ], + "layerId": "9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Connections Topology" + }, + "eventId": "e17bab29-a9ff-52fc-911c-0fbbde37ba9b", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "omb.kex_tier", + "index": "9d644013-9636-4968-9154-38f0c5207120", + "key": "omb.kex_tier", + "negate": true, + "params": { + "query": "PQC READY" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "omb.kex_tier": "PQC READY" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 19, + "i": "d2885626-4e44-41c7-b5ba-45c5b524280a", + "w": 11, + "x": 26, + "y": 40 + }, + "panelIndex": "d2885626-4e44-41c7-b5ba-45c5b524280a", + "title": "Non-Quantum Ready KX", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "9110ccf0-1795-4d13-bab1-9a55f24a24a6": { + "columnOrder": [ + "7bb8af8f-5ff6-433e-9a1a-ca36a3af873d", + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0" + ], + "columns": { + "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "App Count ", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "process.executable" + }, + "7bb8af8f-5ff6-433e-9a1a-ca36a3af873d": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Signature", + "operationType": "terms", + "params": { + "exclude": [ + "(MLDSA|SLH|FND).*" + ], + "excludeIsRegex": true, + "include": [ + "" + ], + "includeIsRegex": true, + "missingBucket": false, + "orderBy": { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 50 + }, + "scale": "ordinal", + "sourceField": "x509.sig_algorithm" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "x509.signature_algorithm", + "index": "7503da64-ec7e-41aa-962f-15507a9e77a5", + "key": "x509.signature_algorithm", + "negate": true, + "params": { + "query": "PQC READY " + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "x509.signature_algorithm": "PQC READY " + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "7bb8af8f-5ff6-433e-9a1a-ca36a3af873d", + "isTransposed": false, + "oneClickFilter": true + }, + { + "columnId": "27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0", + "isTransposed": false + } + ], + "layerId": "9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Certificate Operations" + }, + "eventId": "dfda3f15-fd80-541a-a930-8a72e988f26d", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "x509.signature_algorithm", + "index": "7503da64-ec7e-41aa-962f-15507a9e77a5", + "key": "x509.signature_algorithm", + "negate": true, + "params": { + "query": "PQC READY " + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "x509.signature_algorithm": "PQC READY " + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 19, + "i": "01b3101c-246d-448d-a05d-3a05e7747926", + "w": 11, + "x": 37, + "y": 40 + }, + "panelIndex": "01b3101c-246d-448d-a05d-3a05e7747926", + "title": "Non-Quantum Ready Signatures", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-e75aaba0-a144-4cc0-a761-f8be87375cb4", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "e75aaba0-a144-4cc0-a761-f8be87375cb4": { + "columnOrder": [ + "b5fce59b-3087-426d-aab0-9b9bbecb3ed8", + "f9d9e11f-6962-422b-b6da-2fd7558dd085", + "c01e7181-5ff6-4dcf-acab-76dda3f5a746", + "590cd120-8a6e-4be0-bd3b-0ba0026d28a6", + "434e93db-3c69-4dae-807b-d0719c662bac", + "78f4e7ab-8d4a-44c8-a828-9c575851796c", + "eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2", + "a5eeb316-c12c-4532-b3d7-60b8f2f06876", + "f998a85c-6b52-4d94-9644-c76256e90cc5", + "3406b6a3-14cc-43af-9f24-ac050dd0a821", + "d4469a63-4cf7-4e5f-bdcc-b9a494d4a232", + "5b34e39e-686f-462c-9121-c0695e10982f", + "d80e5fa1-371d-4474-b958-366159cfdd27", + "331d730b-580a-4d92-a2fe-6a84c9d97da7" + ], + "columns": { + "331d730b-580a-4d92-a2fe-6a84c9d97da7": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Host Count", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "host.id" + }, + "3406b6a3-14cc-43af-9f24-ac050dd0a821": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "TLS Supported Ciphers", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "tls.supported_cipher_count" + }, + "434e93db-3c69-4dae-807b-d0719c662bac": { + "customLabel": true, + "dataType": "boolean", + "isBucketed": true, + "label": "Quantum Resilient", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 3 + }, + "scale": "ordinal", + "sourceField": "quantum_ready" + }, + "590cd120-8a6e-4be0-bd3b-0ba0026d28a6": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Primary Key Exchange", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 8 + }, + "scale": "ordinal", + "sourceField": "omb.kex_primary" + }, + "5b34e39e-686f-462c-9121-c0695e10982f": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "TLS Weak Ciphers", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "tls.weak_ciphers" + }, + "78f4e7ab-8d4a-44c8-a828-9c575851796c": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Cipher Suite", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 3 + }, + "scale": "ordinal", + "sourceField": "tychon.crypto.cipher" + }, + "a5eeb316-c12c-4532-b3d7-60b8f2f06876": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Certificate", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "tychon.crypto.certificate" + }, + "b5fce59b-3087-426d-aab0-9b9bbecb3ed8": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Process", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 100 + }, + "scale": "ordinal", + "sourceField": "process.name" + }, + "c01e7181-5ff6-4dcf-acab-76dda3f5a746": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Proto Version", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "tychon.crypto.protocol_version" + }, + "d4469a63-4cf7-4e5f-bdcc-b9a494d4a232": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "TLS Insecure Ciphers", + "operationType": "unique_count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "tls.insecure_cipher_count" + }, + "d80e5fa1-371d-4474-b958-366159cfdd27": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Total OS", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "observer.os.platform" + }, + "eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "MAC", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "tychon.crypto.mac" + }, + "f998a85c-6b52-4d94-9644-c76256e90cc5": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Port Count ", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "server.port" + }, + "f9d9e11f-6962-422b-b6da-2fd7558dd085": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Protocol", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 3 + }, + "scale": "ordinal", + "sourceField": "tychon.crypto.protocol" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "timeField": "@timestamp", + "title": "tychon-pqc*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "b5fce59b-3087-426d-aab0-9b9bbecb3ed8", + "oneClickFilter": true + }, + { + "alignment": "center", + "columnId": "590cd120-8a6e-4be0-bd3b-0ba0026d28a6", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "78f4e7ab-8d4a-44c8-a828-9c575851796c", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "colorMapping": { + "assignments": [ + { + "color": { + "colorIndex": 0, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLSv1.3" + ] + }, + "touched": false + }, + { + "color": { + "colorIndex": 5, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLSv1.2" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 2, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLSv1.1" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 2, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLS1.0" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 2, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLS1" + ] + }, + "touched": true + } + ], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "colorMode": "text", + "columnId": "f9d9e11f-6962-422b-b6da-2fd7558dd085", + "isMetric": false, + "isTransposed": false, + "palette": { + "name": "default", + "params": { + "stops": [ + { + "color": "#54B399", + "stop": 20 + }, + { + "color": "#6092C0", + "stop": 30 + }, + { + "color": "#D36086", + "stop": 40 + }, + { + "color": "#9170B8", + "stop": 50 + }, + { + "color": "#CA8EAE", + "stop": 60 + }, + { + "color": "#D6BF57", + "stop": 70 + }, + { + "color": "#B9A888", + "stop": 80 + }, + { + "color": "#DA8B45", + "stop": 90 + }, + { + "color": "#AA6556", + "stop": 100 + }, + { + "color": "#E7664C", + "stop": 110 + } + ] + }, + "type": "palette" + } + }, + { + "alignment": "center", + "colorMapping": { + "assignments": [ + { + "color": { + "colorIndex": 2, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "0" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 0, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "1" + ] + }, + "touched": true + } + ], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "colorMode": "cell", + "columnId": "434e93db-3c69-4dae-807b-d0719c662bac", + "isMetric": false, + "isTransposed": false, + "palette": { + "name": "default", + "params": { + "stops": [ + { + "color": "#54B399", + "stop": 20 + }, + { + "color": "#6092C0", + "stop": 30 + }, + { + "color": "#D36086", + "stop": 40 + }, + { + "color": "#9170B8", + "stop": 50 + }, + { + "color": "#CA8EAE", + "stop": 60 + }, + { + "color": "#D6BF57", + "stop": 70 + }, + { + "color": "#B9A888", + "stop": 80 + }, + { + "color": "#DA8B45", + "stop": 90 + }, + { + "color": "#AA6556", + "stop": 100 + }, + { + "color": "#E7664C", + "stop": 110 + } + ] + }, + "type": "palette" + } + }, + { + "alignment": "center", + "columnId": "f998a85c-6b52-4d94-9644-c76256e90cc5", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "d80e5fa1-371d-4474-b958-366159cfdd27", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "331d730b-580a-4d92-a2fe-6a84c9d97da7", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "3406b6a3-14cc-43af-9f24-ac050dd0a821", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "d4469a63-4cf7-4e5f-bdcc-b9a494d4a232", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "5b34e39e-686f-462c-9121-c0695e10982f", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "colorMapping": { + "assignments": [ + { + "color": { + "colorIndex": 2, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "1.0", + "1.1" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 5, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "1.2" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 0, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "1.3", + "2.0" + ] + }, + "touched": true + } + ], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "colorMode": "cell", + "columnId": "c01e7181-5ff6-4dcf-acab-76dda3f5a746", + "isMetric": false, + "isTransposed": false, + "palette": { + "name": "default", + "params": { + "stops": [ + { + "color": "#54B399", + "stop": 20 + }, + { + "color": "#6092C0", + "stop": 30 + }, + { + "color": "#D36086", + "stop": 40 + }, + { + "color": "#9170B8", + "stop": 50 + }, + { + "color": "#CA8EAE", + "stop": 60 + }, + { + "color": "#D6BF57", + "stop": 70 + }, + { + "color": "#B9A888", + "stop": 80 + }, + { + "color": "#DA8B45", + "stop": 90 + }, + { + "color": "#AA6556", + "stop": 100 + }, + { + "color": "#E7664C", + "stop": 110 + } + ] + }, + "type": "palette" + } + }, + { + "alignment": "center", + "columnId": "a5eeb316-c12c-4532-b3d7-60b8f2f06876", + "isMetric": false, + "isTransposed": false + } + ], + "headerRowHeightLines": 2, + "layerId": "e75aaba0-a144-4cc0-a761-f8be87375cb4", + "layerType": "data", + "paging": { + "enabled": true, + "size": 30 + } + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": true, + "useCurrentDateRange": true, + "useCurrentFilters": false + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Application Detail" + }, + "eventId": "d0188d05-be4a-474b-8825-cf250d80d88f", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 32, + "i": "07f49118-bcf0-44f7-875a-df393ce88c47", + "w": 48, + "x": 0, + "y": 59 + }, + "panelIndex": "07f49118-bcf0-44f7-875a-df393ce88c47", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-76c0d382-132a-4232-b1ba-2928d86d36eb", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "76c0d382-132a-4232-b1ba-2928d86d36eb": { + "columnOrder": [ + "c452013b-c1a4-444a-9861-fd5f8283dbb8", + "72caa386-75a2-404d-996c-609cc9ce8705", + "c38c78d3-f83a-4b39-8766-fd169aa8f1cf", + "496f4a9c-c379-4dfc-8e74-df11f73cfa52", + "d60e63d5-11c7-4413-b41f-139d3870723e", + "64bc500b-17f2-4b63-99de-710ec63da6b9", + "f1c203be-6445-4ac0-8f8f-64797cb120ba", + "98a06023-cab2-4907-bc55-dbb722c5294a", + "66633750-7aab-4f60-82cb-63d6b4fb604e", + "98a06023-cab2-4907-bc55-dbb722c5294aX0", + "98a06023-cab2-4907-bc55-dbb722c5294aX1", + "98a06023-cab2-4907-bc55-dbb722c5294aX2" + ], + "columns": { + "496f4a9c-c379-4dfc-8e74-df11f73cfa52": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Algorithm", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "66633750-7aab-4f60-82cb-63d6b4fb604e", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "x509.public_key_algorithm" + }, + "64bc500b-17f2-4b63-99de-710ec63da6b9": { + "customLabel": true, + "dataType": "date", + "filter": { + "language": "kuery", + "query": "\"x509.validity.not_before\": *" + }, + "isBucketed": false, + "label": "Issued", + "operationType": "last_value", + "params": { + "sortField": "@timestamp" + }, + "scale": "ratio", + "sourceField": "x509.validity.not_before" + }, + "66633750-7aab-4f60-82cb-63d6b4fb604e": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "72caa386-75a2-404d-996c-609cc9ce8705": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Lifespan", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "66633750-7aab-4f60-82cb-63d6b4fb604e", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "tychon.certificate_leaf_details.validity.duration_days" + }, + "98a06023-cab2-4907-bc55-dbb722c5294a": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Time Left", + "operationType": "formula", + "params": { + "format": { + "id": "duration", + "params": { + "decimals": 0, + "fromUnit": "milliseconds" + } + }, + "formula": "last_value(x509.not_after) - now()", + "isFormulaBroken": false + }, + "references": [ + "98a06023-cab2-4907-bc55-dbb722c5294aX2" + ], + "scale": "ratio" + }, + "98a06023-cab2-4907-bc55-dbb722c5294aX0": { + "customLabel": true, + "dataType": "date", + "filter": { + "language": "kuery", + "query": "\"x509.not_after\": *" + }, + "isBucketed": false, + "label": "Part of Time Left", + "operationType": "last_value", + "params": { + "sortField": "@timestamp" + }, + "scale": "ratio", + "sourceField": "x509.not_after" + }, + "98a06023-cab2-4907-bc55-dbb722c5294aX1": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Part of Time Left", + "operationType": "now", + "references": [], + "scale": "ratio" + }, + "98a06023-cab2-4907-bc55-dbb722c5294aX2": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Part of Time Left", + "operationType": "math", + "params": { + "tinymathAst": { + "args": [ + "98a06023-cab2-4907-bc55-dbb722c5294aX0", + "98a06023-cab2-4907-bc55-dbb722c5294aX1" + ], + "location": { + "max": 34, + "min": 0 + }, + "name": "subtract", + "text": "last_value(x509.not_after) - now()", + "type": "function" + } + }, + "references": [ + "98a06023-cab2-4907-bc55-dbb722c5294aX0", + "98a06023-cab2-4907-bc55-dbb722c5294aX1" + ], + "scale": "ratio" + }, + "c38c78d3-f83a-4b39-8766-fd169aa8f1cf": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Curve", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "66633750-7aab-4f60-82cb-63d6b4fb604e", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "x509.public_key_curve" + }, + "c452013b-c1a4-444a-9861-fd5f8283dbb8": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Subject", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "66633750-7aab-4f60-82cb-63d6b4fb604e", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 100 + }, + "scale": "ordinal", + "sourceField": "x509.subject.distinguished_name" + }, + "d60e63d5-11c7-4413-b41f-139d3870723e": { + "customLabel": true, + "dataType": "number", + "filter": { + "language": "kuery", + "query": "\"x509.public_key_size\": *" + }, + "isBucketed": false, + "label": "Key Size", + "operationType": "last_value", + "params": { + "sortField": "@timestamp" + }, + "scale": "ratio", + "sourceField": "x509.public_key_size" + }, + "f1c203be-6445-4ac0-8f8f-64797cb120ba": { + "customLabel": true, + "dataType": "date", + "filter": { + "language": "kuery", + "query": "\"x509.validity.not_after\": *" + }, + "isBucketed": false, + "label": "Expires", + "operationType": "last_value", + "params": { + "sortField": "@timestamp" + }, + "scale": "ratio", + "sourceField": "x509.validity.not_after" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "timeField": "@timestamp", + "title": "tychon-pqc*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "tychon.index: inventory" + }, + "visualization": { + "columns": [ + { + "columnId": "c452013b-c1a4-444a-9861-fd5f8283dbb8", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "66633750-7aab-4f60-82cb-63d6b4fb604e", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "64bc500b-17f2-4b63-99de-710ec63da6b9", + "isMetric": true, + "isTransposed": false + }, + { + "columnId": "f1c203be-6445-4ac0-8f8f-64797cb120ba", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "72caa386-75a2-404d-996c-609cc9ce8705", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "98a06023-cab2-4907-bc55-dbb722c5294a", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "c38c78d3-f83a-4b39-8766-fd169aa8f1cf", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "496f4a9c-c379-4dfc-8e74-df11f73cfa52", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "d60e63d5-11c7-4413-b41f-139d3870723e", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "76c0d382-132a-4232-b1ba-2928d86d36eb", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "tychon.index: inventory" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 12, + "i": "316d40b0-635e-4969-bf7a-b5e03e2834b4", + "w": 48, + "x": 0, + "y": 91 + }, + "panelIndex": "316d40b0-635e-4969-bf7a-b5e03e2834b4", + "type": "lens" + }, + { + "embeddableConfig": { + "description": "OMB Report for the Department of Defense", + "enhancements": { + "dynamicActions": { + "events": [] + } + } + }, + "gridData": { + "h": 54, + "i": "dab055a8-39ea-4507-a004-7e78a229d7e7", + "w": 48, + "x": 0, + "y": 103 + }, + "panelIndex": "dab055a8-39ea-4507-a004-7e78a229d7e7", + "panelRefName": "panel_dab055a8-39ea-4507-a004-7e78a229d7e7", + "title": "DoD OMB Report", + "type": "search" + } + ], + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "timeFrom": "now-1y/d", + "timeRestore": true, + "timeTo": "now", + "title": "[TYCHON Quantum Command] Application Report", + "version": 3 }, - "description": "Aligns to schema 2.0.3.", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "optionsJSON": "{\"useMargins\":false,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", - "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | Application Report | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 20}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-KEM / Kyber\\\", \\\"desc\\\": \\\"Post-quantum — harvest-proof\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"X25519 / ECDHE\\\", \\\"desc\\\": \\\"Elliptic curve — quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"DHE / DH\\\", \\\"desc\\\": \\\"Finite-field DH — quantum-vulnerable\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"RSA Key Exchange\\\", \\\"desc\\\": \\\"No forward secrecy — deprecated\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"POST-QUANTUM CRYPTOGRAPHY READINESS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE — click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"↑ at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"b5127f43-801b-4411-a631-e5c71ca96645\",\"gridData\":{\"i\":\"b5127f43-801b-4411-a631-e5c71ca96645\",\"y\":2,\"x\":0,\"w\":16,\"h\":19}},{\"type\":\"visualization\",\"title\":\"\",\"embeddableConfig\":{\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"totalApps\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"protoReady\\\", \\\"update\\\": \\\"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"protoPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"protoClr\\\", \\\"update\\\": \\\"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"barW\\\", \\\"update\\\": \\\"width * 0.62 - 18\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"proto_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"proto_pqc\\\", \\\"source\\\": \\\"proto_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"APPLICATION PQC DASHBOARD\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"signal\\\": \\\"'PQC COMPLIANCE PROGRESS — ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"KEX COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY key exchange'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"PROTOCOL COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — TLS 1.3 capable'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * protoPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"protoPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 218},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 238},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 253},\\n \\\"text\\\": {\\\"signal\\\": \\\"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY signature'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * sigPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 282},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"1192b05f-8047-4601-ba71-3f601169574b\",\"gridData\":{\"i\":\"1192b05f-8047-4601-ba71-3f601169574b\",\"y\":2,\"x\":16,\"w\":15,\"h\":19}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 20}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature — quantum-resistant\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve signature — efficient, quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA signature — quantum-vulnerable via Shor's algorithm\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"Broken hash — deprecated by all modern standards\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM — click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"↑ at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3b53c655-5c7c-4910-9b19-657d22031234\",\"gridData\":{\"i\":\"3b53c655-5c7c-4910-9b19-657d22031234\",\"y\":2,\"x\":31,\"w\":17,\"h\":19}},{\"type\":\"visualization\",\"title\":\"\",\"embeddableConfig\":{\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"rowBg\\\"},\\n \\\"update\\\": \\\"datum.family === sel ? null : datum.family\\\",\\n \\\"force\\\": true\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"rowBg\\\"},\\n \\\"update\\\": \\\"datum.family === sel ? kibanaRemoveFilter({'terms': {'process.name': datum.filterTerms}}) : kibanaAddFilter({'terms': {'process.name': datum.filterTerms}})\\\",\\n \\\"force\\\": true\\n }\\n ]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"procs\\\": {\\n \\\"terms\\\": {\\\"field\\\": \\\"process.name\\\", \\\"size\\\": 80},\\n \\\"aggs\\\": {\\n \\\"kex\\\": {\\n \\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 5},\\n \\\"aggs\\\": {\\\"thosts\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"host.id\\\"}}}\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.procs.buckets\\\"},\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"family\\\",\\n \\\"expr\\\": \\\"lower(datum.key)==='w3wp.exe'||lower(datum.key)==='iisexpress.exe'||lower(datum.key)==='inetinfo.exe' ? 'IIS' : lower(datum.key)==='node'||lower(datum.key)==='node.exe'||lower(datum.key)==='nodejs'||lower(datum.key)==='nodejs.exe' ? 'Node.js' : lower(datum.key)==='apache2'||lower(datum.key)==='httpd'||lower(datum.key)==='apache'||lower(datum.key)==='httpd.exe'||lower(datum.key)==='apache.exe'||lower(datum.key)==='httpd.worker' ? 'Apache' : lower(datum.key)==='nginx'||lower(datum.key)==='nginx.exe'||lower(datum.key)==='nginx-debug'||lower(datum.key)==='openresty' ? 'Nginx' : lower(datum.key)==='jsvc'||lower(datum.key)==='tomcat'||lower(datum.key)==='tomcat.exe'||lower(datum.key)==='tomcat9'||lower(datum.key)==='tomcat9.exe'||lower(datum.key)==='tomcat10'||lower(datum.key)==='tomcat10.exe'||lower(datum.key)==='tomcat8'||lower(datum.key)==='tomcat8.exe'||lower(datum.key)==='tomcat7'||lower(datum.key)==='tomcat7.exe'||lower(datum.key)==='catalina'||lower(datum.key)==='catalina.sh' ? 'Tomcat' : lower(datum.key)==='dotnet'||lower(datum.key)==='dotnet.exe' ? '.NET / Kestrel' : lower(datum.key)==='caddy'||lower(datum.key)==='caddy.exe' ? 'Caddy' : lower(datum.key)==='traefik'||lower(datum.key)==='traefik.exe' ? 'Traefik' : lower(datum.key)==='haproxy' ? 'HAProxy' : lower(datum.key)==='gunicorn' ? 'Gunicorn' : lower(datum.key)==='uwsgi' ? 'uWSGI' : lower(datum.key)==='puma'||lower(datum.key)==='passenger'||lower(datum.key)==='passenger-ruby' ? 'Puma' : lower(datum.key)==='varnishd' ? 'Varnish' : lower(datum.key)==='lighttpd' ? 'Lighttpd' : lower(datum.key)==='java'||lower(datum.key)==='java.exe'||lower(datum.key)==='javaw.exe' ? 'Java App Server' : 'Other'\\\"\\n },\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.family != null\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mapped\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"kex.buckets\\\"], \\\"as\\\": [\\\"tb\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.tb.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier_h\\\", \\\"expr\\\": \\\"datum.tb.thosts ? datum.tb.thosts.value : 0\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier_ord\\\", \\\"expr\\\": \\\"datum.tier==='LEGACY' ? 0 : datum.tier==='CLASSICAL' ? 1 : datum.tier==='MODERN' ? 2 : datum.tier==='PQC READY' ? 3 : 4\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"by_ft\\\",\\n \\\"source\\\": \\\"mapped\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\", \\\"tier\\\", \\\"tier_ord\\\"],\\n \\\"fields\\\": [\\\"tier_h\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"tier_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_totals\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"fam_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_risk\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.tier === 'LEGACY' || datum.tier === 'CLASSICAL'\\\"},\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"risk_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_pqc\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.tier === 'PQC READY'\\\"},\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"as\\\": [\\\"pqc_total\\\"]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"fam_rows\\\",\\n \\\"source\\\": \\\"fam_totals\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"fam_risk\\\", \\\"key\\\": \\\"family\\\", \\\"fields\\\": [\\\"family\\\"], \\\"values\\\": [\\\"risk_total\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"fam_pqc\\\", \\\"key\\\": \\\"family\\\", \\\"fields\\\": [\\\"family\\\"], \\\"values\\\": [\\\"pqc_total\\\"], \\\"default\\\": 0},\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"clr\\\",\\n \\\"expr\\\": \\\"datum.family==='IIS' ? '#0078d4' : datum.family==='Node.js' ? '#68a063' : datum.family==='Apache' ? '#d22128' : datum.family==='Nginx' ? '#009900' : datum.family==='Tomcat' ? '#f8a51a' : datum.family==='.NET / Kestrel' ? '#7b5ea7' : datum.family==='Caddy' ? '#00acd7' : datum.family==='Traefik' ? '#24a1c1' : datum.family==='HAProxy' ? '#7db8e8' : datum.family==='Gunicorn' ? '#499848' : datum.family==='uWSGI' ? '#cc4125' : datum.family==='Puma' ? '#e040fb' : datum.family==='Varnish' ? '#ff6d00' : datum.family==='Lighttpd' ? '#909090' : datum.family==='Java App Server' ? '#c7a008' : '#666666'\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"filterTerms\\\",\\n \\\"expr\\\": \\\"datum.family==='IIS' ? ['w3wp.exe','iisexpress.exe','inetinfo.exe'] : datum.family==='Node.js' ? ['node','node.exe','nodejs','nodejs.exe'] : datum.family==='Apache' ? ['apache2','httpd','apache','httpd.exe','apache.exe','httpd.worker'] : datum.family==='Nginx' ? ['nginx','nginx.exe','nginx-debug','openresty'] : datum.family==='Tomcat' ? ['jsvc','tomcat','tomcat.exe','tomcat9','tomcat9.exe','tomcat10','tomcat10.exe','tomcat8','tomcat8.exe','tomcat7','tomcat7.exe','catalina','catalina.sh'] : datum.family==='.NET / Kestrel' ? ['dotnet','dotnet.exe'] : datum.family==='Caddy' ? ['caddy','caddy.exe'] : datum.family==='Traefik' ? ['traefik','traefik.exe'] : datum.family==='HAProxy' ? ['haproxy'] : datum.family==='Gunicorn' ? ['gunicorn'] : datum.family==='uWSGI' ? ['uwsgi'] : datum.family==='Puma' ? ['puma','passenger','passenger-ruby'] : datum.family==='Varnish' ? ['varnishd'] : datum.family==='Lighttpd' ? ['lighttpd'] : datum.family==='Java App Server' ? ['java','java.exe','javaw.exe'] : [datum.family]\\\"\\n },\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"risk_total\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rowIdx\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rowIdx - 1) * 38 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"stacked\\\",\\n \\\"source\\\": \\\"by_ft\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"fam_rows\\\", \\\"key\\\": \\\"family\\\", \\\"fields\\\": [\\\"family\\\"], \\\"values\\\": [\\\"y\\\", \\\"fam_total\\\", \\\"risk_total\\\"]},\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.y != null\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier_clr\\\", \\\"expr\\\": \\\"datum.tier==='LEGACY' ? '#ef5350' : datum.tier==='CLASSICAL' ? '#ffa726' : datum.tier==='MODERN' ? '#42a5f5' : datum.tier==='PQC READY' ? '#66bb6a' : '#555555'\\\"},\\n {\\\"type\\\": \\\"joinaggregate\\\", \\\"fields\\\": [\\\"fam_total\\\"], \\\"ops\\\": [\\\"max\\\"], \\\"as\\\": [\\\"max_fam\\\"]},\\n {\\n \\\"type\\\": \\\"window\\\",\\n \\\"groupby\\\": [\\\"family\\\"],\\n \\\"sort\\\": {\\\"field\\\": \\\"tier_ord\\\", \\\"order\\\": \\\"ascending\\\"},\\n \\\"ops\\\": [\\\"sum\\\"],\\n \\\"fields\\\": [\\\"tier_total\\\"],\\n \\\"as\\\": [\\\"cumul\\\"]\\n }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"WEB SERVER DISTRIBUTION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 30},\\n \\\"text\\\": {\\\"value\\\": \\\"HOSTS BY SERVER FAMILY & PQC KEX TIER · sorted by at-risk count · click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 170}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#ef5350\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 180}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"LEGACY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 228}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#ffa726\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 238}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"CLASSICAL\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 300}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#42a5f5\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 310}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"MODERN\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\\"type\\\": \\\"rect\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 362}, \\\"y\\\": {\\\"value\\\": 37}, \\\"width\\\": {\\\"value\\\": 7}, \\\"height\\\": {\\\"value\\\": 6}, \\\"fill\\\": {\\\"value\\\": \\\"#66bb6a\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 1}}}},\\n {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 372}, \\\"y\\\": {\\\"value\\\": 44}, \\\"text\\\": {\\\"value\\\": \\\"PQC READY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}},\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 50},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"rowBg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 37},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.family===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"},\\n \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 37},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 14\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"family\\\"}, \\\"limit\\\": {\\\"value\\\": 148},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.family===sel ? '#ffffff' : '#e8e8e8'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 170}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"width - 245\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 2}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"stacked\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"170 + ((datum.cumul - datum.tier_total) / (datum.max_fam > 0 ? datum.max_fam : 1)) * (width - 245)\\\"},\\n \\\"x2\\\": {\\\"signal\\\": \\\"170 + (datum.cumul / (datum.max_fam > 0 ? datum.max_fam : 1)) * (width - 245)\\\"},\\n \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"height\\\": {\\\"value\\\": 8},\\n \\\"fill\\\": {\\\"field\\\": \\\"tier_clr\\\"},\\n \\\"fillOpacity\\\": {\\\"signal\\\": \\\"datum.family===sel ? 1 : 0.8\\\"},\\n \\\"cornerRadius\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 14\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.fam_total >= 1000 ? format(datum.fam_total, '.3~s') : format(datum.fam_total, ',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.family===sel ? datum.clr : '#cccccc'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 35\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.risk_total > 0 ? format(datum.risk_total, ',') + ' AT RISK' : datum.pqc_total > 0 ? 'PQC READY' : 'NOT PQC READY'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.risk_total > 0 ? '#ef5350' : datum.pqc_total > 0 ? '#66bb6a' : '#ffa726'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 7}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"fam_rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 37\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"0634e4b1-c33f-45ed-a33c-ba3937c4ed1f\",\"gridData\":{\"i\":\"0634e4b1-c33f-45ed-a33c-ba3937c4ed1f\",\"y\":21,\"x\":0,\"w\":26,\"h\":19}},{\"type\":\"lens\",\"title\":\"Weak Ciphers In-Use\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9c6edb36-c71b-5cf1-8dcd-a37de6214334\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true,\"width\":314},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Weak Cipher\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[\"svchost.exe\",\"dllhost.exe\"],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Process Count\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1}}}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"2e9c8eb8-3234-44f1-aaf7-95b6832d1657\",\"gridData\":{\"i\":\"2e9c8eb8-3234-44f1-aaf7-95b6832d1657\",\"y\":21,\"x\":26,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"title\":\"Insecure Ciphers In-Use\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"b0c9f1de-0afd-5b7d-b3a1-fb28c055a10a\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Insecure Cipher\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.insecure_ciphers\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[\"svchost.exe\",\"dllhost.exe\"],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"ae78c400-d497-4d7f-9541-3e14fb724097\",\"gridData\":{\"i\":\"ae78c400-d497-4d7f-9541-3e14fb724097\",\"y\":21,\"x\":37,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"title\":\"Port Usage\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"0ba322cf-440b-5ad3-a615-62aad7cf634c\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-8e8a2d62-de50-4140-91d5-4d323f4bfe51\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"8e8a2d62-de50-4140-91d5-4d323f4bfe51\",\"layerType\":\"data\",\"columns\":[{\"columnId\":\"b9ce2593-2e18-4a93-997b-fea289547d59\",\"alignment\":\"center\"},{\"columnId\":\"119c83a6-13f7-4470-b14e-00f524c8f68c\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"57ed4372-97b0-41ed-a161-eb151f832cdb\",\"isTransposed\":false,\"isMetric\":true}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"8e8a2d62-de50-4140-91d5-4d323f4bfe51\":{\"columns\":{\"b9ce2593-2e18-4a93-997b-fea289547d59\":{\"label\":\"Port Number\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"server.port\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"119c83a6-13f7-4470-b14e-00f524c8f68c\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"119c83a6-13f7-4470-b14e-00f524c8f68c\":{\"label\":\"Not Resilient\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.name\",\"isBucketed\":false,\"filter\":{\"query\":\"omb.kex_primary_quantum_safe : false \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"57ed4372-97b0-41ed-a161-eb151f832cdb\":{\"label\":\"Quantum Resilient \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.name\",\"isBucketed\":false,\"filter\":{\"query\":\"omb.kex_primary_quantum_safe : true \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true}},\"columnOrder\":[\"b9ce2593-2e18-4a93-997b-fea289547d59\",\"119c83a6-13f7-4470-b14e-00f524c8f68c\",\"57ed4372-97b0-41ed-a161-eb151f832cdb\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091\",\"gridData\":{\"i\":\"5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091\",\"y\":40,\"x\":0,\"w\":10,\"h\":19}},{\"type\":\"lens\",\"title\":\"Vulnerable Software\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"d46a3ff4-c28b-57a1-a225-f58957519288\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"tychon.index : \\\"inventory\\\" and quantum_ready: false \",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"tychon.index : \\\"inventory\\\" and quantum_ready: false \",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Software Package Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[\"svchost.exe\",\"dllhost.exe\"],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"Host Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1}}}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1\",\"gridData\":{\"i\":\"bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1\",\"y\":40,\"x\":10,\"w\":16,\"h\":19}},{\"type\":\"lens\",\"title\":\"Non-Quantum Ready KX\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"e17bab29-a9ff-52fc-911c-0fbbde37ba9b\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"9d644013-9636-4968-9154-38f0c5207120\",\"key\":\"omb.kex_tier\",\"field\":\"omb.kex_tier\",\"params\":{\"query\":\"PQC READY\"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"omb.kex_tier\":\"PQC READY\"}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"oneClickFilter\":true,\"width\":314},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"9d644013-9636-4968-9154-38f0c5207120\",\"key\":\"omb.kex_tier\",\"field\":\"omb.kex_tier\",\"params\":{\"query\":\"PQC READY\"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"omb.kex_tier\":\"PQC READY\"}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\":{\"label\":\"Key Exchange\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.supported_key_exchanges\",\"isBucketed\":true,\"params\":{\"size\":999,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[\"\"],\"exclude\":[\".*(mlkem|ffdh).*\"],\"includeIsRegex\":true,\"excludeIsRegex\":true},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c1ef140-d9ad-40dd-b4f7-5fffeb57893c\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"d2885626-4e44-41c7-b5ba-45c5b524280a\",\"gridData\":{\"i\":\"d2885626-4e44-41c7-b5ba-45c5b524280a\",\"y\":40,\"x\":26,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"title\":\"Non-Quantum Ready Signatures\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"dfda3f15-fd80-541a-a930-8a72e988f26d\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Certificate Operations\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"7503da64-ec7e-41aa-962f-15507a9e77a5\",\"key\":\"x509.signature_algorithm\",\"field\":\"x509.signature_algorithm\",\"params\":{\"query\":\"PQC READY \"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"x509.signature_algorithm\":\"PQC READY \"}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"7bb8af8f-5ff6-433e-9a1a-ca36a3af873d\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"}],\"layerId\":\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"7503da64-ec7e-41aa-962f-15507a9e77a5\",\"key\":\"x509.signature_algorithm\",\"field\":\"x509.signature_algorithm\",\"params\":{\"query\":\"PQC READY \"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"x509.signature_algorithm\":\"PQC READY \"}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"9110ccf0-1795-4d13-bab1-9a55f24a24a6\":{\"columns\":{\"7bb8af8f-5ff6-433e-9a1a-ca36a3af873d\":{\"label\":\"Signature\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.sig_algorithm\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[\"\"],\"exclude\":[\"(MLDSA|SLH|FND).*\"],\"includeIsRegex\":true,\"excludeIsRegex\":true},\"customLabel\":true},\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\":{\"label\":\"App Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"process.executable\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"7bb8af8f-5ff6-433e-9a1a-ca36a3af873d\",\"27ead65c-5a7b-4ce3-83ff-bc77a2cc20a0\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"01b3101c-246d-448d-a05d-3a05e7747926\",\"gridData\":{\"i\":\"01b3101c-246d-448d-a05d-3a05e7747926\",\"y\":40,\"x\":37,\"w\":11,\"h\":19}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"d0188d05-be4a-474b-8825-cf250d80d88f\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Application Detail\",\"config\":{\"openInNewTab\":true,\"useCurrentDateRange\":true,\"useCurrentFilters\":false}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-e75aaba0-a144-4cc0-a761-f8be87375cb4\"}],\"state\":{\"visualization\":{\"layerId\":\"e75aaba0-a144-4cc0-a761-f8be87375cb4\",\"layerType\":\"data\",\"columns\":[{\"columnId\":\"b5fce59b-3087-426d-aab0-9b9bbecb3ed8\",\"oneClickFilter\":true},{\"columnId\":\"590cd120-8a6e-4be0-bd3b-0ba0026d28a6\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"78f4e7ab-8d4a-44c8-a828-9c575851796c\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"f9d9e11f-6962-422b-b6da-2fd7558dd085\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"text\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.3\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":false},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.2\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":5},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLS1.0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLS1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"434e93db-3c69-4dae-807b-d0719c662bac\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"d80e5fa1-371d-4474-b958-366159cfdd27\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"331d730b-580a-4d92-a2fe-6a84c9d97da7\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"3406b6a3-14cc-43af-9f24-ac050dd0a821\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"d4469a63-4cf7-4e5f-bdcc-b9a494d4a232\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"5b34e39e-686f-462c-9121-c0695e10982f\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"c01e7181-5ff6-4dcf-acab-76dda3f5a746\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1.0\",\"1.1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":2},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1.2\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":5},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1.3\",\"2.0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"a5eeb316-c12c-4532-b3d7-60b8f2f06876\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"}],\"paging\":{\"enabled\":true,\"size\":30},\"headerRowHeightLines\":2},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"e75aaba0-a144-4cc0-a761-f8be87375cb4\":{\"columns\":{\"b5fce59b-3087-426d-aab0-9b9bbecb3ed8\":{\"label\":\"Process\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":100,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"590cd120-8a6e-4be0-bd3b-0ba0026d28a6\":{\"label\":\"Primary Key Exchange\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.kex_primary\",\"isBucketed\":true,\"params\":{\"size\":8,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"78f4e7ab-8d4a-44c8-a828-9c575851796c\":{\"label\":\"Cipher Suite\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.cipher\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"f9d9e11f-6962-422b-b6da-2fd7558dd085\":{\"label\":\"Protocol\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.protocol\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"434e93db-3c69-4dae-807b-d0719c662bac\":{\"label\":\"Quantum Resilient\",\"dataType\":\"boolean\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"quantum_ready\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"f998a85c-6b52-4d94-9644-c76256e90cc5\":{\"label\":\"Port Count \",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"server.port\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"d80e5fa1-371d-4474-b958-366159cfdd27\":{\"label\":\"Total OS\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"observer.os.platform\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"331d730b-580a-4d92-a2fe-6a84c9d97da7\":{\"label\":\"Host Count\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"host.id\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"3406b6a3-14cc-43af-9f24-ac050dd0a821\":{\"label\":\"TLS Supported Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"d4469a63-4cf7-4e5f-bdcc-b9a494d4a232\":{\"label\":\"TLS Insecure Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.insecure_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"5b34e39e-686f-462c-9121-c0695e10982f\":{\"label\":\"TLS Weak Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2\":{\"label\":\"MAC\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.mac\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"c01e7181-5ff6-4dcf-acab-76dda3f5a746\":{\"label\":\"Proto Version\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.protocol_version\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"a5eeb316-c12c-4532-b3d7-60b8f2f06876\":{\"label\":\"Certificate\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.crypto.certificate\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f998a85c-6b52-4d94-9644-c76256e90cc5\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"b5fce59b-3087-426d-aab0-9b9bbecb3ed8\",\"f9d9e11f-6962-422b-b6da-2fd7558dd085\",\"c01e7181-5ff6-4dcf-acab-76dda3f5a746\",\"590cd120-8a6e-4be0-bd3b-0ba0026d28a6\",\"434e93db-3c69-4dae-807b-d0719c662bac\",\"78f4e7ab-8d4a-44c8-a828-9c575851796c\",\"eae233bd-7ec6-46a2-8f6b-85fb3c94e9a2\",\"a5eeb316-c12c-4532-b3d7-60b8f2f06876\",\"f998a85c-6b52-4d94-9644-c76256e90cc5\",\"3406b6a3-14cc-43af-9f24-ac050dd0a821\",\"d4469a63-4cf7-4e5f-bdcc-b9a494d4a232\",\"5b34e39e-686f-462c-9121-c0695e10982f\",\"d80e5fa1-371d-4474-b958-366159cfdd27\",\"331d730b-580a-4d92-a2fe-6a84c9d97da7\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"07f49118-bcf0-44f7-875a-df393ce88c47\",\"gridData\":{\"i\":\"07f49118-bcf0-44f7-875a-df393ce88c47\",\"y\":59,\"x\":0,\"w\":48,\"h\":32}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"tychon.index: inventory\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-76c0d382-132a-4232-b1ba-2928d86d36eb\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"c452013b-c1a4-444a-9861-fd5f8283dbb8\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"64bc500b-17f2-4b63-99de-710ec63da6b9\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"f1c203be-6445-4ac0-8f8f-64797cb120ba\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"72caa386-75a2-404d-996c-609cc9ce8705\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"98a06023-cab2-4907-bc55-dbb722c5294a\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"c38c78d3-f83a-4b39-8766-fd169aa8f1cf\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"496f4a9c-c379-4dfc-8e74-df11f73cfa52\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"d60e63d5-11c7-4413-b41f-139d3870723e\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"}],\"layerId\":\"76c0d382-132a-4232-b1ba-2928d86d36eb\",\"layerType\":\"data\"},\"query\":{\"query\":\"tychon.index: inventory\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"76c0d382-132a-4232-b1ba-2928d86d36eb\":{\"columns\":{\"c452013b-c1a4-444a-9861-fd5f8283dbb8\":{\"label\":\"Subject\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.subject.distinguished_name\",\"isBucketed\":true,\"params\":{\"size\":100,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"66633750-7aab-4f60-82cb-63d6b4fb604e\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"64bc500b-17f2-4b63-99de-710ec63da6b9\":{\"label\":\"Issued\",\"dataType\":\"date\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.validity.not_before\",\"filter\":{\"query\":\"\\\"x509.validity.not_before\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"f1c203be-6445-4ac0-8f8f-64797cb120ba\":{\"label\":\"Expires\",\"dataType\":\"date\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.validity.not_after\",\"filter\":{\"query\":\"\\\"x509.validity.not_after\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"72caa386-75a2-404d-996c-609cc9ce8705\":{\"label\":\"Lifespan\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tychon.certificate_leaf_details.validity.duration_days\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294aX0\":{\"label\":\"Part of Time Left\",\"dataType\":\"date\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.not_after\",\"filter\":{\"query\":\"\\\"x509.not_after\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294aX1\":{\"label\":\"Part of Time Left\",\"dataType\":\"number\",\"operationType\":\"now\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[],\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294aX2\":{\"label\":\"Part of Time Left\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"subtract\",\"args\":[\"98a06023-cab2-4907-bc55-dbb722c5294aX0\",\"98a06023-cab2-4907-bc55-dbb722c5294aX1\"],\"location\":{\"min\":0,\"max\":34},\"text\":\"last_value(x509.not_after) - now()\"}},\"references\":[\"98a06023-cab2-4907-bc55-dbb722c5294aX0\",\"98a06023-cab2-4907-bc55-dbb722c5294aX1\"],\"customLabel\":true},\"98a06023-cab2-4907-bc55-dbb722c5294a\":{\"label\":\"Time Left\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"last_value(x509.not_after) - now()\",\"isFormulaBroken\":false,\"format\":{\"id\":\"duration\",\"params\":{\"decimals\":0,\"fromUnit\":\"milliseconds\"}}},\"references\":[\"98a06023-cab2-4907-bc55-dbb722c5294aX2\"],\"customLabel\":true},\"c38c78d3-f83a-4b39-8766-fd169aa8f1cf\":{\"label\":\"Curve\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.public_key_curve\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"496f4a9c-c379-4dfc-8e74-df11f73cfa52\":{\"label\":\"Algorithm\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"x509.public_key_algorithm\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"66633750-7aab-4f60-82cb-63d6b4fb604e\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"d60e63d5-11c7-4413-b41f-139d3870723e\":{\"label\":\"Key Size\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"x509.public_key_size\",\"filter\":{\"query\":\"\\\"x509.public_key_size\\\": *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true}},\"columnOrder\":[\"c452013b-c1a4-444a-9861-fd5f8283dbb8\",\"72caa386-75a2-404d-996c-609cc9ce8705\",\"c38c78d3-f83a-4b39-8766-fd169aa8f1cf\",\"496f4a9c-c379-4dfc-8e74-df11f73cfa52\",\"d60e63d5-11c7-4413-b41f-139d3870723e\",\"64bc500b-17f2-4b63-99de-710ec63da6b9\",\"f1c203be-6445-4ac0-8f8f-64797cb120ba\",\"98a06023-cab2-4907-bc55-dbb722c5294a\",\"66633750-7aab-4f60-82cb-63d6b4fb604e\",\"98a06023-cab2-4907-bc55-dbb722c5294aX0\",\"98a06023-cab2-4907-bc55-dbb722c5294aX1\",\"98a06023-cab2-4907-bc55-dbb722c5294aX2\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"316d40b0-635e-4969-bf7a-b5e03e2834b4\",\"gridData\":{\"i\":\"316d40b0-635e-4969-bf7a-b5e03e2834b4\",\"y\":91,\"x\":0,\"w\":48,\"h\":12}},{\"type\":\"search\",\"title\":\"DoD OMB Report\",\"panelIndex\":\"dab055a8-39ea-4507-a004-7e78a229d7e7\",\"gridData\":{\"i\":\"dab055a8-39ea-4507-a004-7e78a229d7e7\",\"y\":103,\"x\":0,\"w\":48,\"h\":54},\"embeddableConfig\":{\"description\":\"OMB Report for the Department of Defense\",\"enhancements\":{\"dynamicActions\":{\"events\":[]}}},\"panelRefName\":\"panel_dab055a8-39ea-4507-a004-7e78a229d7e7\"}]", - "refreshInterval": { - "pause": true, - "value": 60000 - }, - "timeFrom": "now-1y/d", - "timeRestore": true, - "timeTo": "now", - "title": "[TYCHON Quantum Command] Application Report", - "version": 3 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "managed": false, - "originId": "601ec774-d72f-415f-90e8-df3569fa8eab", - "references": [ - { - "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", - "name": "01b3101c-246d-448d-a05d-3a05e7747926:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:dfda3f15-fd80-541a-a930-8a72e988f26d:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", - "name": "07f49118-bcf0-44f7-875a-df393ce88c47:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d0188d05-be4a-474b-8825-cf250d80d88f:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", - "name": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9c6edb36-c71b-5cf1-8dcd-a37de6214334:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", - "name": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:0ba322cf-440b-5ad3-a615-62aad7cf634c:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", - "name": "ae78c400-d497-4d7f-9541-3e14fb724097:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b0c9f1de-0afd-5b7d-b3a1-fb28c055a10a:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", - "name": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d46a3ff4-c28b-57a1-a225-f58957519288:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", - "name": "d2885626-4e44-41c7-b5ba-45c5b524280a:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:e17bab29-a9ff-52fc-911c-0fbbde37ba9b:dashboardId", - "type": "dashboard" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "01b3101c-246d-448d-a05d-3a05e7747926:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "07f49118-bcf0-44f7-875a-df393ce88c47:indexpattern-datasource-layer-e75aaba0-a144-4cc0-a761-f8be87375cb4", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "316d40b0-635e-4969-bf7a-b5e03e2834b4:indexpattern-datasource-layer-76c0d382-132a-4232-b1ba-2928d86d36eb", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091:indexpattern-datasource-layer-8e8a2d62-de50-4140-91d5-4d323f4bfe51", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "ae78c400-d497-4d7f-9541-3e14fb724097:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "d2885626-4e44-41c7-b5ba-45c5b524280a:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", - "type": "index-pattern" - }, - { - "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", - "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", - "type": "tag" - }, - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", - "type": "tag" - }, - { - "id": "tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report", - "name": "dab055a8-39ea-4507-a004-7e78a229d7e7:panel_dab055a8-39ea-4507-a004-7e78a229d7e7", - "type": "search" - } - ], - "type": "dashboard", - "typeMigrationVersion": "10.2.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NjUsMzBd" -} + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "references": [ + { + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "name": "01b3101c-246d-448d-a05d-3a05e7747926:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:dfda3f15-fd80-541a-a930-8a72e988f26d:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "07f49118-bcf0-44f7-875a-df393ce88c47:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d0188d05-be4a-474b-8825-cf250d80d88f:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9c6edb36-c71b-5cf1-8dcd-a37de6214334:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:0ba322cf-440b-5ad3-a615-62aad7cf634c:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "ae78c400-d497-4d7f-9541-3e14fb724097:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b0c9f1de-0afd-5b7d-b3a1-fb28c055a10a:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d46a3ff4-c28b-57a1-a225-f58957519288:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "d2885626-4e44-41c7-b5ba-45c5b524280a:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:e17bab29-a9ff-52fc-911c-0fbbde37ba9b:dashboardId", + "type": "dashboard" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "01b3101c-246d-448d-a05d-3a05e7747926:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "07f49118-bcf0-44f7-875a-df393ce88c47:indexpattern-datasource-layer-e75aaba0-a144-4cc0-a761-f8be87375cb4", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "2e9c8eb8-3234-44f1-aaf7-95b6832d1657:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "316d40b0-635e-4969-bf7a-b5e03e2834b4:indexpattern-datasource-layer-76c0d382-132a-4232-b1ba-2928d86d36eb", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "5a1a9fd8-a9e5-4333-ad15-e08a3b6cb091:indexpattern-datasource-layer-8e8a2d62-de50-4140-91d5-4d323f4bfe51", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "ae78c400-d497-4d7f-9541-3e14fb724097:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "bd58f6e5-41a8-4bd7-9b5b-c8f2502833b1:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "d2885626-4e44-41c7-b5ba-45c5b524280a:indexpattern-datasource-layer-9110ccf0-1795-4d13-bab1-9a55f24a24a6", + "type": "index-pattern" + }, + { + "id": "tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report", + "name": "dab055a8-39ea-4507-a004-7e78a229d7e7:panel_dab055a8-39ea-4507-a004-7e78a229d7e7", + "type": "search" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.3.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json index c00e42c7eb5..e96c00b11a2 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json @@ -1,113 +1,2235 @@ { - "attributes": { - "controlGroupInput": { - "chainingSystem": "HIERARCHICAL", - "controlStyle": "oneLine", - "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", - "panelsJSON": "{}", - "showApplySelections": false + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": {}, + "showApplySelections": false + }, + "description": "Aligns to schema 2.0.3.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": false, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": true + }, + "panelsJSON": [ + { + "embeddableConfig": { + "enhancements": {}, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | Application Detail | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 3, + "i": "tychon-quantum-command-nav", + "w": 48, + "x": 0, + "y": 0 + }, + "panelIndex": "tychon-quantum-command-nav", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "name": "indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": { + "341cf49e-257b-48f0-af62-9d0ae3420573": { + "columnOrder": [ + "babddc5e-7343-42a8-941a-4d81e5d985ae", + "53541012-c568-493f-87d8-0a4800cc6dab" + ], + "columns": { + "53541012-c568-493f-87d8-0a4800cc6dab": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "babddc5e-7343-42a8-941a-4d81e5d985ae": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Process Name", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "53541012-c568-493f-87d8-0a4800cc6dab", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "process.name" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "timeField": "@timestamp", + "title": "tychon-pqc-inventory*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "babddc5e-7343-42a8-941a-4d81e5d985ae", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "53541012-c568-493f-87d8-0a4800cc6dab", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "341cf49e-257b-48f0-af62-9d0ae3420573", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 7, + "i": "0f84ffed-4e62-4c1c-bedc-be51e098a775", + "w": 11, + "x": 0, + "y": 2 + }, + "panelIndex": "0f84ffed-4e62-4c1c-bedc-be51e098a775", + "type": "lens" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum — harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve — quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH — quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy — deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 14, + "i": "5863cc6f-de20-4892-891f-069d5a9316f9", + "w": 11, + "x": 11, + "y": 2 + }, + "panelIndex": "5863cc6f-de20-4892-891f-069d5a9316f9", + "type": "visualization" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.protocol_tier\", \"size\": 50}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"TLS 1.3\", \"lbl\": \"TLS 1.3\", \"desc\": \"Required for PQC key exchange — carries ML-KEM key_share\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"TLS 1.2\", \"lbl\": \"TLS 1.2\", \"desc\": \"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\", \"badge\": \"NO KEM EXT\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1},\n {\"t\": \"LEGACY\", \"lbl\": \"TLS 1.1 or below\", \"desc\": \"Deprecated — contains known protocol vulnerabilities, should be disabled\", \"badge\": \"DEPRECATED\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"TLS PROTOCOL VERSION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"PREFERRED PROTOCOL — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + }, + "title": "", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 14, + "i": "a293b107-7762-4b76-a2f8-6497e1d52dbf", + "w": 12, + "x": 22, + "y": 2 + }, + "panelIndex": "a293b107-7762-4b76-a2f8-6497e1d52dbf", + "type": "visualization" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "a3b23fce-41b6-41ac-bf8c-8434eafb70cd": { + "columnOrder": [ + "3863f9f1-0deb-4fcd-bf1c-c344bc19f579", + "a506ec6b-bb03-4116-884b-04cea6bcb388" + ], + "columns": { + "3863f9f1-0deb-4fcd-bf1c-c344bc19f579": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Ports ", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "a506ec6b-bb03-4116-884b-04cea6bcb388", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 50 + }, + "scale": "ordinal", + "sourceField": "server.port" + }, + "a506ec6b-bb03-4116-884b-04cea6bcb388": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "timeField": "@timestamp", + "title": "tychon-pqc*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "alignment": "center", + "columnId": "3863f9f1-0deb-4fcd-bf1c-c344bc19f579", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "a506ec6b-bb03-4116-884b-04cea6bcb388", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Connections Topology" + }, + "eventId": "b5e53a68-24f0-5385-8498-35d2b3d898cc", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 14, + "i": "716deebb-7717-49ad-b463-7f8880f050bf", + "w": 6, + "x": 34, + "y": 2 + }, + "panelIndex": "716deebb-7717-49ad-b463-7f8880f050bf", + "title": "Ports Identified", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "a3b23fce-41b6-41ac-bf8c-8434eafb70cd": { + "columnOrder": [ + "3863f9f1-0deb-4fcd-bf1c-c344bc19f579", + "a506ec6b-bb03-4116-884b-04cea6bcb388" + ], + "columns": { + "3863f9f1-0deb-4fcd-bf1c-c344bc19f579": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Version", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "a506ec6b-bb03-4116-884b-04cea6bcb388", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 50 + }, + "scale": "ordinal", + "sourceField": "omb.software_package_version" + }, + "a506ec6b-bb03-4116-884b-04cea6bcb388": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count of records ", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "timeField": "@timestamp", + "title": "tychon-pqc-inventory*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "3863f9f1-0deb-4fcd-bf1c-c344bc19f579", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "a506ec6b-bb03-4116-884b-04cea6bcb388", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 14, + "i": "5b71a4a3-dde9-4d62-9791-475787c052df", + "w": 8, + "x": 40, + "y": 2 + }, + "panelIndex": "5b71a4a3-dde9-4d62-9791-475787c052df", + "title": "Versions Found", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "name": "indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": { + "341cf49e-257b-48f0-af62-9d0ae3420573": { + "columnOrder": [ + "babddc5e-7343-42a8-941a-4d81e5d985ae", + "53541012-c568-493f-87d8-0a4800cc6dab" + ], + "columns": { + "53541012-c568-493f-87d8-0a4800cc6dab": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "babddc5e-7343-42a8-941a-4d81e5d985ae": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Directory Path", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "53541012-c568-493f-87d8-0a4800cc6dab", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 20 + }, + "scale": "ordinal", + "sourceField": "process.executable_directory" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "timeField": "@timestamp", + "title": "tychon-pqc-inventory*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "babddc5e-7343-42a8-941a-4d81e5d985ae", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "53541012-c568-493f-87d8-0a4800cc6dab", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "341cf49e-257b-48f0-af62-9d0ae3420573", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 7, + "i": "541e6258-f438-4fd0-b039-adcdc944bb8a", + "w": 11, + "x": 0, + "y": 9 + }, + "panelIndex": "541e6258-f438-4fd0-b039-adcdc944bb8a", + "title": "", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-978e2a9e-6e77-4b60-a432-ebb35f2ad6c1", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "978e2a9e-6e77-4b60-a432-ebb35f2ad6c1": { + "columnOrder": [ + "bacbe082-96df-43d0-9e2b-1a8a1740c574", + "14f48029-f56d-4db1-8a48-e990270bbb64", + "8902ba19-daec-484d-aea3-8b4ac1cce646", + "dd8a939b-f0f8-4a4b-9b34-56bde897441c", + "340cf762-1dc6-49b8-ade4-a9d707dd978d", + "690b2f8e-0eac-4633-bfa7-47ece118fe33", + "e2845484-f680-42cd-9636-e215edfe9f78", + "b4b643e9-ab88-4830-89c5-aa80ca3bdb7a", + "e4717f8a-c09e-407b-b9ea-673d108cec27" + ], + "columns": { + "14f48029-f56d-4db1-8a48-e990270bbb64": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Domain", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "e4717f8a-c09e-407b-b9ea-673d108cec27", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "host.domain" + }, + "340cf762-1dc6-49b8-ade4-a9d707dd978d": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "OS Name", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "e4717f8a-c09e-407b-b9ea-673d108cec27", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "host.os.name" + }, + "690b2f8e-0eac-4633-bfa7-47ece118fe33": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "OS Version ", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "e4717f8a-c09e-407b-b9ea-673d108cec27", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "host.os.version" + }, + "8902ba19-daec-484d-aea3-8b4ac1cce646": { + "customLabel": true, + "dataType": "ip", + "isBucketed": true, + "label": "IP", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "e4717f8a-c09e-407b-b9ea-673d108cec27", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 1 + }, + "scale": "ordinal", + "sourceField": "host.ip" + }, + "b4b643e9-ab88-4830-89c5-aa80ca3bdb7a": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Weak TLS Ciphers", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "tls.weak_ciphers" + }, + "bacbe082-96df-43d0-9e2b-1a8a1740c574": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Hostname", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "e4717f8a-c09e-407b-b9ea-673d108cec27", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 500 + }, + "scale": "ordinal", + "sourceField": "host.hostname" + }, + "dd8a939b-f0f8-4a4b-9b34-56bde897441c": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "OS Platform", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "e4717f8a-c09e-407b-b9ea-673d108cec27", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "host.os.platform" + }, + "e2845484-f680-42cd-9636-e215edfe9f78": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Unique TLS Ciphers", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "tls.insecure_cipher_count" + }, + "e4717f8a-c09e-407b-b9ea-673d108cec27": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Ports", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "server.port" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "timeField": "@timestamp", + "title": "tychon-pqc*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "bacbe082-96df-43d0-9e2b-1a8a1740c574", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "e4717f8a-c09e-407b-b9ea-673d108cec27", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "14f48029-f56d-4db1-8a48-e990270bbb64", + "isMetric": false, + "isTransposed": false, + "oneClickFilter": true + }, + { + "alignment": "center", + "columnId": "8902ba19-daec-484d-aea3-8b4ac1cce646", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "dd8a939b-f0f8-4a4b-9b34-56bde897441c", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "340cf762-1dc6-49b8-ade4-a9d707dd978d", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "690b2f8e-0eac-4633-bfa7-47ece118fe33", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "b4b643e9-ab88-4830-89c5-aa80ca3bdb7a", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "e2845484-f680-42cd-9636-e215edfe9f78", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "978e2a9e-6e77-4b60-a432-ebb35f2ad6c1", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Connections Topology" + }, + "eventId": "0b95bb86-15cd-5498-b469-92e6120e762b", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 13, + "i": "c35ba11c-8005-4653-b5c4-0e658b426ef9", + "w": 48, + "x": 0, + "y": 16 + }, + "panelIndex": "c35ba11c-8005-4653-b5c4-0e658b426ef9", + "title": "Found On Assets", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "name": "indexpattern-datasource-layer-efd1c1c6-66da-400d-b474-d14414080249", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": { + "efd1c1c6-66da-400d-b474-d14414080249": { + "columnOrder": [ + "3b1be2af-eeaa-4415-8c4d-007b2881bb77", + "96808911-ee68-4654-9dad-f5ec6c1e4136", + "f3b310d9-1571-4d39-8e93-884fd27edcd7", + "e5bdf109-436f-4b84-bd6e-80c86e7c0db4", + "5a5b6100-a1f3-4104-a958-fd5e97733081", + "e9535d81-cde5-48f2-8b39-795b363dc5b3", + "5bf22b6b-946b-4fb0-b457-f3f292f546da", + "c5807b1d-23db-4d1a-8498-e89968ea63c7", + "2dbbc91f-11c4-4396-8a71-3bd2e20b1b19", + "8904b583-14e3-46d5-a978-46c337227a48", + "3243578e-4af0-438a-879e-94b256f1d9ee", + "8de5e4b3-d909-49c4-bb76-ec27660a8af6" + ], + "columns": { + "2dbbc91f-11c4-4396-8a71-3bd2e20b1b19": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "KX Count", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "tls.supported_key_exchange_count" + }, + "3243578e-4af0-438a-879e-94b256f1d9ee": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Ciphers", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "tls.supported_cipher_count" + }, + "3b1be2af-eeaa-4415-8c4d-007b2881bb77": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "App Process", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "process.name" + }, + "5a5b6100-a1f3-4104-a958-fd5e97733081": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Resilient", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "omb.kex_primary_quantum_safe" + }, + "5bf22b6b-946b-4fb0-b457-f3f292f546da": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Cipher Suite", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "tls.preferred_cipher" + }, + "8904b583-14e3-46d5-a978-46c337227a48": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Protocols", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "tls.supported_protocol_count" + }, + "8de5e4b3-d909-49c4-bb76-ec27660a8af6": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "96808911-ee68-4654-9dad-f5ec6c1e4136": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Path", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 100 + }, + "scale": "ordinal", + "sourceField": "process.executable_directory" + }, + "c5807b1d-23db-4d1a-8498-e89968ea63c7": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Protocol", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "tls.preferred_protocol" + }, + "e5bdf109-436f-4b84-bd6e-80c86e7c0db4": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Package Name", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 5 + }, + "scale": "ordinal", + "sourceField": "omb.software_package_name" + }, + "e9535d81-cde5-48f2-8b39-795b363dc5b3": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Key Exchange", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": true, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 6 + }, + "scale": "ordinal", + "sourceField": "omb.kex_primary" + }, + "f3b310d9-1571-4d39-8e93-884fd27edcd7": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Listening On", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "server.port" + } + }, + "incompleteColumns": {}, + "indexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "timeField": "@timestamp", + "title": "tychon-pqc-inventory*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "3b1be2af-eeaa-4415-8c4d-007b2881bb77", + "isTransposed": false, + "oneClickFilter": true + }, + { + "columnId": "8de5e4b3-d909-49c4-bb76-ec27660a8af6", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "f3b310d9-1571-4d39-8e93-884fd27edcd7", + "isMetric": false, + "isTransposed": false + }, + { + "alignment": "center", + "colorMapping": { + "assignments": [ + { + "color": { + "colorIndex": 9, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "0" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 0, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "1" + ] + }, + "touched": false + } + ], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "colorMode": "cell", + "columnId": "5a5b6100-a1f3-4104-a958-fd5e97733081", + "isMetric": false, + "isTransposed": false, + "palette": { + "name": "default", + "params": { + "stops": [ + { + "color": "#54B399", + "stop": 20 + }, + { + "color": "#6092C0", + "stop": 30 + }, + { + "color": "#D36086", + "stop": 40 + }, + { + "color": "#9170B8", + "stop": 50 + }, + { + "color": "#CA8EAE", + "stop": 60 + }, + { + "color": "#D6BF57", + "stop": 70 + }, + { + "color": "#B9A888", + "stop": 80 + }, + { + "color": "#DA8B45", + "stop": 90 + }, + { + "color": "#AA6556", + "stop": 100 + }, + { + "color": "#E7664C", + "stop": 110 + } + ] + }, + "type": "palette" + } + }, + { + "alignment": "center", + "colorMode": "none", + "columnId": "e9535d81-cde5-48f2-8b39-795b363dc5b3", + "isMetric": false, + "isTransposed": false, + "oneClickFilter": true + }, + { + "alignment": "center", + "columnId": "5bf22b6b-946b-4fb0-b457-f3f292f546da", + "isMetric": false, + "isTransposed": false, + "width": 213.33333333333334 + }, + { + "alignment": "center", + "colorMapping": { + "assignments": [ + { + "color": { + "colorIndex": 0, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLSv1.3" + ] + }, + "touched": false + }, + { + "color": { + "colorIndex": 5, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLSv1.2" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 9, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLSv1.1" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 9, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLSv1.0" + ] + }, + "touched": true + }, + { + "color": { + "colorIndex": 9, + "paletteId": "eui_amsterdam_color_blind", + "type": "categorical" + }, + "rule": { + "type": "matchExactly", + "values": [ + "TLS1" + ] + }, + "touched": true + } + ], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "colorMode": "cell", + "columnId": "c5807b1d-23db-4d1a-8498-e89968ea63c7", + "isMetric": false, + "isTransposed": false, + "palette": { + "name": "default", + "params": { + "stops": [ + { + "color": "#54B399", + "stop": 20 + }, + { + "color": "#6092C0", + "stop": 30 + }, + { + "color": "#D36086", + "stop": 40 + }, + { + "color": "#9170B8", + "stop": 50 + }, + { + "color": "#CA8EAE", + "stop": 60 + }, + { + "color": "#D6BF57", + "stop": 70 + }, + { + "color": "#B9A888", + "stop": 80 + }, + { + "color": "#DA8B45", + "stop": 90 + }, + { + "color": "#AA6556", + "stop": 100 + }, + { + "color": "#E7664C", + "stop": 110 + } + ] + }, + "type": "palette" + } + }, + { + "columnId": "e5bdf109-436f-4b84-bd6e-80c86e7c0db4", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "96808911-ee68-4654-9dad-f5ec6c1e4136", + "isMetric": false, + "isTransposed": false, + "oneClickFilter": true + }, + { + "alignment": "center", + "columnId": "2dbbc91f-11c4-4396-8a71-3bd2e20b1b19", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "8904b583-14e3-46d5-a978-46c337227a48", + "isMetric": true, + "isTransposed": false + }, + { + "alignment": "center", + "columnId": "3243578e-4af0-438a-879e-94b256f1d9ee", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "efd1c1c6-66da-400d-b474-d14414080249", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 15, + "i": "fb740713-8d4d-4114-8816-739a35cf7b68", + "w": 48, + "x": 0, + "y": 29 + }, + "panelIndex": "fb740713-8d4d-4114-8816-739a35cf7b68", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1": { + "columnOrder": [ + "fccc8673-7024-4075-bd07-b717a834dfbf", + "76043fbd-8e84-4b5d-83da-3712770265b8" + ], + "columns": { + "76043fbd-8e84-4b5d-83da-3712770265b8": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "fccc8673-7024-4075-bd07-b717a834dfbf": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Weak Ciphers ", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "76043fbd-8e84-4b5d-83da-3712770265b8", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 50 + }, + "scale": "ordinal", + "sourceField": "tls.weak_ciphers" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "timeField": "@timestamp", + "title": "tychon-pqc-inventory*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "fccc8673-7024-4075-bd07-b717a834dfbf", + "isTransposed": false + }, + { + "columnId": "76043fbd-8e84-4b5d-83da-3712770265b8", + "isTransposed": false + } + ], + "layerId": "bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "a8bb1dca-9e7f-55bc-b777-050d845c3d7a", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 18, + "i": "686a9532-a314-4685-b25c-7de7c957f361", + "w": 16, + "x": 0, + "y": 44 + }, + "panelIndex": "686a9532-a314-4685-b25c-7de7c957f361", + "title": "Supported Weak Ciphers", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1": { + "columnOrder": [ + "fccc8673-7024-4075-bd07-b717a834dfbf", + "76043fbd-8e84-4b5d-83da-3712770265b8" + ], + "columns": { + "76043fbd-8e84-4b5d-83da-3712770265b8": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "fccc8673-7024-4075-bd07-b717a834dfbf": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Insecure Ciphers ", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "76043fbd-8e84-4b5d-83da-3712770265b8", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 50 + }, + "scale": "ordinal", + "sourceField": "tls.insecure_ciphers" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "timeField": "@timestamp", + "title": "tychon-pqc-inventory*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "fccc8673-7024-4075-bd07-b717a834dfbf", + "isTransposed": false + }, + { + "columnId": "76043fbd-8e84-4b5d-83da-3712770265b8", + "isTransposed": false + } + ], + "layerId": "bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "08ff1cd0-f8eb-53f9-9be5-24cff120f036", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 18, + "i": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f", + "w": 16, + "x": 16, + "y": 44 + }, + "panelIndex": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f", + "title": "Supported Insecure Ciphers", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "name": "indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "layers": { + "bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1": { + "columnOrder": [ + "fccc8673-7024-4075-bd07-b717a834dfbf", + "76043fbd-8e84-4b5d-83da-3712770265b8" + ], + "columns": { + "76043fbd-8e84-4b5d-83da-3712770265b8": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count of records ", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "fccc8673-7024-4075-bd07-b717a834dfbf": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Supported Ciphers", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "76043fbd-8e84-4b5d-83da-3712770265b8", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 50 + }, + "scale": "ordinal", + "sourceField": "tls.supported_ciphers" + } + }, + "incompleteColumns": {}, + "indexPatternId": "0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "7eee23b7-ddb2-4c12-ad44-a12d7e8301cf", + "timeField": "@timestamp", + "title": "tychon-pqc-inventory*" + } + ], + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "fccc8673-7024-4075-bd07-b717a834dfbf", + "isTransposed": false + }, + { + "columnId": "76043fbd-8e84-4b5d-83da-3712770265b8", + "isTransposed": false + } + ], + "layerId": "bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 18, + "i": "fe8e72b0-98d0-4252-bec5-c56732ed1f12", + "w": 16, + "x": 32, + "y": 44 + }, + "panelIndex": "fe8e72b0-98d0-4252-bec5-c56732ed1f12", + "type": "lens" + } + ], + "timeRestore": false, + "title": "[TYCHON Quantum Command] Application Detail", + "version": 3 }, - "description": "Aligns to schema 2.0.3.", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "optionsJSON": "{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", - "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | Application Detail | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"name\":\"indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"341cf49e-257b-48f0-af62-9d0ae3420573\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"341cf49e-257b-48f0-af62-9d0ae3420573\":{\"columns\":{\"babddc5e-7343-42a8-941a-4d81e5d985ae\":{\"label\":\"Process Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"53541012-c568-493f-87d8-0a4800cc6dab\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"53541012-c568-493f-87d8-0a4800cc6dab\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"}},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"0f84ffed-4e62-4c1c-bedc-be51e098a775\",\"gridData\":{\"i\":\"0f84ffed-4e62-4c1c-bedc-be51e098a775\",\"y\":2,\"x\":0,\"w\":11,\"h\":7}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.kex_tier\\\", \\\"size\\\": 20}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"hcount\\\", \\\"expr\\\": \\\"datum.u ? datum.u.value : 0\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"hcount\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-KEM / Kyber\\\", \\\"desc\\\": \\\"Post-quantum \\u2014 harvest-proof\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"X25519 / ECDHE\\\", \\\"desc\\\": \\\"Elliptic curve \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"MODERN\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"DHE / DH\\\", \\\"desc\\\": \\\"Finite-field DH \\u2014 quantum-vulnerable\\\", \\\"badge\\\": \\\"CLASSICAL\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"RSA Key Exchange\\\", \\\"desc\\\": \\\"No forward secrecy \\u2014 deprecated\\\", \\\"badge\\\": \\\"LEGACY\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 3}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"POST-QUANTUM CRYPTOGRAPHY READINESS\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"KEY EXCHANGE \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"5863cc6f-de20-4892-891f-069d5a9316f9\",\"gridData\":{\"i\":\"5863cc6f-de20-4892-891f-069d5a9316f9\",\"y\":2,\"x\":11,\"w\":11,\"h\":14}},{\"type\":\"visualization\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\",\\n \\\"force\\\": true\\n }]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [{\\n \\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"},\\n \\\"update\\\": \\\"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\\\",\\n \\\"force\\\": true\\n }]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.protocol_tier\\\", \\\"size\\\": 50}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tc\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"doc_count\\\"], \\\"as\\\": [\\\"n\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"tc\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"values\\\": [\\n {\\\"t\\\": \\\"TLS 1.3\\\", \\\"lbl\\\": \\\"TLS 1.3\\\", \\\"desc\\\": \\\"Required for PQC key exchange \\u2014 carries ML-KEM key_share\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0},\\n {\\\"t\\\": \\\"TLS 1.2\\\", \\\"lbl\\\": \\\"TLS 1.2\\\", \\\"desc\\\": \\\"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\\\", \\\"badge\\\": \\\"NO KEM EXT\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1},\\n {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"TLS 1.1 or below\\\", \\\"desc\\\": \\\"Deprecated \\u2014 contains known protocol vulnerabilities, should be disabled\\\", \\\"badge\\\": \\\"DEPRECATED\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}\\n ],\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"TLS PROTOCOL VERSION\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"PREFERRED PROTOCOL \\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width*0.62-18\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.bg:'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.badge\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#383838'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 31\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 17}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"'#1a1a1a'\\\"},\\n \\\"stroke\\\": {\\\"signal\\\": \\\"'#333333'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width*0.65+41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 43\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.t===sel?'SELECTED':''\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:'#448aff'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width-10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width/2\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"height-8\\\"}, \\\"text\\\": {\\\"value\\\": \\\"\\u2191 at the highest tier\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"a293b107-7762-4b76-a2f8-6497e1d52dbf\",\"gridData\":{\"i\":\"a293b107-7762-4b76-a2f8-6497e1d52dbf\",\"y\":2,\"x\":22,\"w\":12,\"h\":14}},{\"type\":\"lens\",\"title\":\"Ports Identified\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"b5e53a68-24f0-5385-8498-35d2b3d898cc\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\":{\"columns\":{\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\":{\"label\":\"Ports \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"server.port\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"a506ec6b-bb03-4116-884b-04cea6bcb388\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"a506ec6b-bb03-4116-884b-04cea6bcb388\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"716deebb-7717-49ad-b463-7f8880f050bf\",\"gridData\":{\"i\":\"716deebb-7717-49ad-b463-7f8880f050bf\",\"y\":2,\"x\":34,\"w\":6,\"h\":14}},{\"type\":\"lens\",\"title\":\"Versions Found\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a3b23fce-41b6-41ac-bf8c-8434eafb70cd\":{\"columns\":{\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\":{\"label\":\"Version\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.software_package_version\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a506ec6b-bb03-4116-884b-04cea6bcb388\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"a506ec6b-bb03-4116-884b-04cea6bcb388\":{\"label\":\"Count of records \",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"3863f9f1-0deb-4fcd-bf1c-c344bc19f579\",\"a506ec6b-bb03-4116-884b-04cea6bcb388\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"5b71a4a3-dde9-4d62-9791-475787c052df\",\"gridData\":{\"i\":\"5b71a4a3-dde9-4d62-9791-475787c052df\",\"y\":2,\"x\":40,\"w\":8,\"h\":14}},{\"type\":\"lens\",\"title\":\"\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"name\":\"indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\",\"isTransposed\":false,\"isMetric\":true}],\"layerId\":\"341cf49e-257b-48f0-af62-9d0ae3420573\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"341cf49e-257b-48f0-af62-9d0ae3420573\":{\"columns\":{\"babddc5e-7343-42a8-941a-4d81e5d985ae\":{\"label\":\"Directory Path\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.executable_directory\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"53541012-c568-493f-87d8-0a4800cc6dab\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"53541012-c568-493f-87d8-0a4800cc6dab\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"babddc5e-7343-42a8-941a-4d81e5d985ae\",\"53541012-c568-493f-87d8-0a4800cc6dab\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"}},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"541e6258-f438-4fd0-b039-adcdc944bb8a\",\"gridData\":{\"i\":\"541e6258-f438-4fd0-b039-adcdc944bb8a\",\"y\":9,\"x\":0,\"w\":11,\"h\":7}},{\"type\":\"lens\",\"title\":\"Found On Assets\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"0b95bb86-15cd-5498-b469-92e6120e762b\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Connections Topology\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-978e2a9e-6e77-4b60-a432-ebb35f2ad6c1\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"bacbe082-96df-43d0-9e2b-1a8a1740c574\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\",\"isTransposed\":false,\"isMetric\":true},{\"columnId\":\"14f48029-f56d-4db1-8a48-e990270bbb64\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"oneClickFilter\":true},{\"columnId\":\"8902ba19-daec-484d-aea3-8b4ac1cce646\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"dd8a939b-f0f8-4a4b-9b34-56bde897441c\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"340cf762-1dc6-49b8-ade4-a9d707dd978d\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"690b2f8e-0eac-4633-bfa7-47ece118fe33\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"b4b643e9-ab88-4830-89c5-aa80ca3bdb7a\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"e2845484-f680-42cd-9636-e215edfe9f78\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"}],\"layerId\":\"978e2a9e-6e77-4b60-a432-ebb35f2ad6c1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"978e2a9e-6e77-4b60-a432-ebb35f2ad6c1\":{\"columns\":{\"bacbe082-96df-43d0-9e2b-1a8a1740c574\":{\"label\":\"Hostname\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.hostname\",\"isBucketed\":true,\"params\":{\"size\":500,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e4717f8a-c09e-407b-b9ea-673d108cec27\":{\"label\":\"Ports\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"server.port\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"14f48029-f56d-4db1-8a48-e990270bbb64\":{\"label\":\"Domain\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.domain\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"8902ba19-daec-484d-aea3-8b4ac1cce646\":{\"label\":\"IP\",\"dataType\":\"ip\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.ip\",\"isBucketed\":true,\"params\":{\"size\":1,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"dd8a939b-f0f8-4a4b-9b34-56bde897441c\":{\"label\":\"OS Platform\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.os.platform\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"340cf762-1dc6-49b8-ade4-a9d707dd978d\":{\"label\":\"OS Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.os.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"690b2f8e-0eac-4633-bfa7-47ece118fe33\":{\"label\":\"OS Version \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"host.os.version\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e4717f8a-c09e-407b-b9ea-673d108cec27\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"b4b643e9-ab88-4830-89c5-aa80ca3bdb7a\":{\"label\":\"Weak TLS Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"e2845484-f680-42cd-9636-e215edfe9f78\":{\"label\":\"Unique TLS Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.insecure_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"bacbe082-96df-43d0-9e2b-1a8a1740c574\",\"14f48029-f56d-4db1-8a48-e990270bbb64\",\"8902ba19-daec-484d-aea3-8b4ac1cce646\",\"dd8a939b-f0f8-4a4b-9b34-56bde897441c\",\"340cf762-1dc6-49b8-ade4-a9d707dd978d\",\"690b2f8e-0eac-4633-bfa7-47ece118fe33\",\"e2845484-f680-42cd-9636-e215edfe9f78\",\"b4b643e9-ab88-4830-89c5-aa80ca3bdb7a\",\"e4717f8a-c09e-407b-b9ea-673d108cec27\"],\"sampling\":1,\"ignoreGlobalFilters\":false,\"incompleteColumns\":{},\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"title\":\"tychon-pqc*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"c35ba11c-8005-4653-b5c4-0e658b426ef9\",\"gridData\":{\"i\":\"c35ba11c-8005-4653-b5c4-0e658b426ef9\",\"y\":16,\"x\":0,\"w\":48,\"h\":13}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"name\":\"indexpattern-datasource-layer-efd1c1c6-66da-400d-b474-d14414080249\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"3b1be2af-eeaa-4415-8c4d-007b2881bb77\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\",\"isMetric\":true},{\"columnId\":\"f3b310d9-1571-4d39-8e93-884fd27edcd7\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\"},{\"columnId\":\"5a5b6100-a1f3-4104-a958-fd5e97733081\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":false}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"e9535d81-cde5-48f2-8b39-795b363dc5b3\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"oneClickFilter\":true,\"colorMode\":\"none\"},{\"columnId\":\"5bf22b6b-946b-4fb0-b457-f3f292f546da\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"width\":213.33333333333334},{\"columnId\":\"c5807b1d-23db-4d1a-8498-e89968ea63c7\",\"isTransposed\":false,\"isMetric\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"type\":\"palette\",\"name\":\"default\",\"params\":{\"stops\":[{\"color\":\"#54B399\",\"stop\":20},{\"color\":\"#6092C0\",\"stop\":30},{\"color\":\"#D36086\",\"stop\":40},{\"color\":\"#9170B8\",\"stop\":50},{\"color\":\"#CA8EAE\",\"stop\":60},{\"color\":\"#D6BF57\",\"stop\":70},{\"color\":\"#B9A888\",\"stop\":80},{\"color\":\"#DA8B45\",\"stop\":90},{\"color\":\"#AA6556\",\"stop\":100},{\"color\":\"#E7664C\",\"stop\":110}]}},\"colorMapping\":{\"assignments\":[{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.3\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":0},\"touched\":false},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.2\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":5},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLSv1.0\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true},{\"rule\":{\"type\":\"matchExactly\",\"values\":[\"TLS1\"]},\"color\":{\"type\":\"categorical\",\"paletteId\":\"eui_amsterdam_color_blind\",\"colorIndex\":9},\"touched\":true}],\"specialAssignments\":[{\"rule\":{\"type\":\"other\"},\"color\":{\"type\":\"loop\"},\"touched\":false}],\"paletteId\":\"eui_amsterdam_color_blind\",\"colorMode\":{\"type\":\"categorical\"}}},{\"columnId\":\"e5bdf109-436f-4b84-bd6e-80c86e7c0db4\",\"isTransposed\":false,\"isMetric\":false},{\"columnId\":\"96808911-ee68-4654-9dad-f5ec6c1e4136\",\"isTransposed\":false,\"isMetric\":false,\"oneClickFilter\":true},{\"columnId\":\"2dbbc91f-11c4-4396-8a71-3bd2e20b1b19\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"8904b583-14e3-46d5-a978-46c337227a48\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"},{\"columnId\":\"3243578e-4af0-438a-879e-94b256f1d9ee\",\"isTransposed\":false,\"isMetric\":true,\"alignment\":\"center\"}],\"layerId\":\"efd1c1c6-66da-400d-b474-d14414080249\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"efd1c1c6-66da-400d-b474-d14414080249\":{\"columns\":{\"3b1be2af-eeaa-4415-8c4d-007b2881bb77\":{\"label\":\"App Process\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"f3b310d9-1571-4d39-8e93-884fd27edcd7\":{\"label\":\"Listening On\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"server.port\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"5a5b6100-a1f3-4104-a958-fd5e97733081\":{\"label\":\"Resilient\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.kex_primary_quantum_safe\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e9535d81-cde5-48f2-8b39-795b363dc5b3\":{\"label\":\"Key Exchange\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.kex_primary\",\"isBucketed\":true,\"params\":{\"size\":6,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"5bf22b6b-946b-4fb0-b457-f3f292f546da\":{\"label\":\"Cipher Suite\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.preferred_cipher\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"c5807b1d-23db-4d1a-8498-e89968ea63c7\":{\"label\":\"Protocol\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.preferred_protocol\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e5bdf109-436f-4b84-bd6e-80c86e7c0db4\":{\"label\":\"Package Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"omb.software_package_name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"96808911-ee68-4654-9dad-f5ec6c1e4136\":{\"label\":\"Path\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"process.executable_directory\",\"isBucketed\":true,\"params\":{\"size\":100,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":true,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"2dbbc91f-11c4-4396-8a71-3bd2e20b1b19\":{\"label\":\"KX Count\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_key_exchange_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"8904b583-14e3-46d5-a978-46c337227a48\":{\"label\":\"Protocols\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_protocol_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"3243578e-4af0-438a-879e-94b256f1d9ee\":{\"label\":\"Ciphers\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"tls.supported_cipher_count\",\"isBucketed\":false,\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"3b1be2af-eeaa-4415-8c4d-007b2881bb77\",\"96808911-ee68-4654-9dad-f5ec6c1e4136\",\"f3b310d9-1571-4d39-8e93-884fd27edcd7\",\"e5bdf109-436f-4b84-bd6e-80c86e7c0db4\",\"5a5b6100-a1f3-4104-a958-fd5e97733081\",\"e9535d81-cde5-48f2-8b39-795b363dc5b3\",\"5bf22b6b-946b-4fb0-b457-f3f292f546da\",\"c5807b1d-23db-4d1a-8498-e89968ea63c7\",\"2dbbc91f-11c4-4396-8a71-3bd2e20b1b19\",\"8904b583-14e3-46d5-a978-46c337227a48\",\"3243578e-4af0-438a-879e-94b256f1d9ee\",\"8de5e4b3-d909-49c4-bb76-ec27660a8af6\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"}},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"fb740713-8d4d-4114-8816-739a35cf7b68\",\"gridData\":{\"i\":\"fb740713-8d4d-4114-8816-739a35cf7b68\",\"y\":29,\"x\":0,\"w\":48,\"h\":15}},{\"type\":\"lens\",\"title\":\"Supported Weak Ciphers\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"a8bb1dca-9e7f-55bc-b777-050d845c3d7a\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"fccc8673-7024-4075-bd07-b717a834dfbf\"},{\"isTransposed\":false,\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"}],\"layerId\":\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\":{\"columns\":{\"fccc8673-7024-4075-bd07-b717a834dfbf\":{\"label\":\"Weak Ciphers \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.weak_ciphers\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"76043fbd-8e84-4b5d-83da-3712770265b8\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"fccc8673-7024-4075-bd07-b717a834dfbf\",\"76043fbd-8e84-4b5d-83da-3712770265b8\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"686a9532-a314-4685-b25c-7de7c957f361\",\"gridData\":{\"i\":\"686a9532-a314-4685-b25c-7de7c957f361\",\"y\":44,\"x\":0,\"w\":16,\"h\":18}},{\"type\":\"lens\",\"title\":\"Supported Insecure Ciphers\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"08ff1cd0-f8eb-53f9-9be5-24cff120f036\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"fccc8673-7024-4075-bd07-b717a834dfbf\"},{\"isTransposed\":false,\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"}],\"layerId\":\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\":{\"columns\":{\"fccc8673-7024-4075-bd07-b717a834dfbf\":{\"label\":\"Insecure Ciphers \",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.insecure_ciphers\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"76043fbd-8e84-4b5d-83da-3712770265b8\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"fccc8673-7024-4075-bd07-b717a834dfbf\",\"76043fbd-8e84-4b5d-83da-3712770265b8\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"511cf538-0abc-44f0-a54c-3ccc2a58ba7f\",\"gridData\":{\"i\":\"511cf538-0abc-44f0-a54c-3ccc2a58ba7f\",\"y\":44,\"x\":16,\"w\":16,\"h\":18}},{\"type\":\"lens\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"filters\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\",\"name\":\"indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"fccc8673-7024-4075-bd07-b717a834dfbf\"},{\"isTransposed\":false,\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"}],\"layerId\":\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\",\"layerType\":\"data\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1\":{\"columns\":{\"fccc8673-7024-4075-bd07-b717a834dfbf\":{\"label\":\"Supported Ciphers\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"tls.supported_ciphers\",\"isBucketed\":true,\"params\":{\"size\":50,\"orderBy\":{\"type\":\"column\",\"columnId\":\"76043fbd-8e84-4b5d-83da-3712770265b8\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"76043fbd-8e84-4b5d-83da-3712770265b8\":{\"label\":\"Count of records \",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"fccc8673-7024-4075-bd07-b717a834dfbf\",\"76043fbd-8e84-4b5d-83da-3712770265b8\"],\"incompleteColumns\":{},\"sampling\":1,\"indexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"}},\"currentIndexPatternId\":\"0e56225a-3b03-4f4e-bdbc-2fd59f0ef78c\"},\"indexpattern\":{\"layers\":{},\"currentIndexPatternId\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\"},\"textBased\":{\"layers\":{},\"indexPatternRefs\":[{\"id\":\"7eee23b7-ddb2-4c12-ad44-a12d7e8301cf\",\"title\":\"tychon-pqc-inventory*\",\"timeField\":\"@timestamp\"}]}},\"internalReferences\":[],\"adHocDataViews\":{}}}},\"panelIndex\":\"fe8e72b0-98d0-4252-bec5-c56732ed1f12\",\"gridData\":{\"i\":\"fe8e72b0-98d0-4252-bec5-c56732ed1f12\",\"y\":44,\"x\":32,\"w\":16,\"h\":18}}]", - "timeRestore": false, - "title": "[TYCHON Quantum Command] Application Detail", - "version": 3 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", - "managed": false, - "originId": "d871606c-7231-4508-88b0-2a4228e4ff3d", - "references": [ - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:08ff1cd0-f8eb-53f9-9be5-24cff120f036:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "686a9532-a314-4685-b25c-7de7c957f361:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:a8bb1dca-9e7f-55bc-b777-050d845c3d7a:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", - "name": "716deebb-7717-49ad-b463-7f8880f050bf:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b5e53a68-24f0-5385-8498-35d2b3d898cc:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", - "name": "c35ba11c-8005-4653-b5c4-0e658b426ef9:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:0b95bb86-15cd-5498-b469-92e6120e762b:dashboardId", - "type": "dashboard" - }, - { - "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", - "name": "0f84ffed-4e62-4c1c-bedc-be51e098a775:indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", - "type": "index-pattern" - }, - { - "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", - "name": "541e6258-f438-4fd0-b039-adcdc944bb8a:indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "5b71a4a3-dde9-4d62-9791-475787c052df:indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "686a9532-a314-4685-b25c-7de7c957f361:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "716deebb-7717-49ad-b463-7f8880f050bf:indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "c35ba11c-8005-4653-b5c4-0e658b426ef9:indexpattern-datasource-layer-978e2a9e-6e77-4b60-a432-ebb35f2ad6c1", - "type": "index-pattern" - }, - { - "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", - "name": "fb740713-8d4d-4114-8816-739a35cf7b68:indexpattern-datasource-layer-efd1c1c6-66da-400d-b474-d14414080249", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "fe8e72b0-98d0-4252-bec5-c56732ed1f12:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", - "type": "index-pattern" - }, - { - "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", - "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", - "type": "tag" - }, - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", - "type": "tag" - } - ], - "type": "dashboard", - "typeMigrationVersion": "10.2.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NjYsMzBd" -} + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "references": [ + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:08ff1cd0-f8eb-53f9-9be5-24cff120f036:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "686a9532-a314-4685-b25c-7de7c957f361:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:a8bb1dca-9e7f-55bc-b777-050d845c3d7a:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "716deebb-7717-49ad-b463-7f8880f050bf:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b5e53a68-24f0-5385-8498-35d2b3d898cc:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "name": "c35ba11c-8005-4653-b5c4-0e658b426ef9:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:0b95bb86-15cd-5498-b469-92e6120e762b:dashboardId", + "type": "dashboard" + }, + { + "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", + "name": "0f84ffed-4e62-4c1c-bedc-be51e098a775:indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "511cf538-0abc-44f0-a54c-3ccc2a58ba7f:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + }, + { + "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", + "name": "541e6258-f438-4fd0-b039-adcdc944bb8a:indexpattern-datasource-layer-341cf49e-257b-48f0-af62-9d0ae3420573", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "5b71a4a3-dde9-4d62-9791-475787c052df:indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "686a9532-a314-4685-b25c-7de7c957f361:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "716deebb-7717-49ad-b463-7f8880f050bf:indexpattern-datasource-layer-a3b23fce-41b6-41ac-bf8c-8434eafb70cd", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "c35ba11c-8005-4653-b5c4-0e658b426ef9:indexpattern-datasource-layer-978e2a9e-6e77-4b60-a432-ebb35f2ad6c1", + "type": "index-pattern" + }, + { + "id": "852a2806-9a09-4c17-bcea-b54e7b69f3bc", + "name": "fb740713-8d4d-4114-8816-739a35cf7b68:indexpattern-datasource-layer-efd1c1c6-66da-400d-b474-d14414080249", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "fe8e72b0-98d0-4252-bec5-c56732ed1f12:indexpattern-datasource-layer-bd94c8fb-80f3-4090-b11f-5c3c6b7ce3b1", + "type": "index-pattern" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.3.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json index 97572d9665b..9554c9c02e3 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json @@ -1,68 +1,386 @@ { - "attributes": { - "controlGroupInput": { - "chainingSystem": "HIERARCHICAL", - "controlStyle": "oneLine", - "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", - "panelsJSON": "{}", - "showApplySelections": false + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": {}, + "showApplySelections": false + }, + "description": "Aligns to schema 2.0.3", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": false, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": true + }, + "panelsJSON": [ + { + "embeddableConfig": { + "enhancements": {}, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | Application Connections Topology | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 3, + "i": "tychon-quantum-command-nav", + "w": 48, + "x": 0, + "y": 0 + }, + "panelIndex": "tychon-quantum-command-nav", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Detail" + }, + "eventId": "754afa08-289f-5a39-bc46-04d2b9e6e76a", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"Application filter list panel (multi-select) with dashboard filter integration.\",\n \"autosize\": \"fit\",\n \"padding\": 10,\n \"background\": \"#000000\",\n \"signals\": [\n {\n \"name\": \"selectedApps\",\n \"value\": \"|\",\n \"on\": [\n {\n \"events\": \"@appRowBg:click\",\n \"update\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? replace(selectedApps, '|' + datum.app + '|', '|') : selectedApps + datum.app + '|'\"\n }\n ]\n },\n {\n \"name\": \"selectedAppsArray\",\n \"update\": \"selectedApps == '|' ? [] : split(slice(selectedApps, 1, length(selectedApps)-1), '|')\"\n },\n {\n \"name\": \"activeFilter\",\n \"update\": \"length(selectedAppsArray) \u003e 0 ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'terms': {'tychon.application.name': selectedAppsArray}}]}} : {'term': {'event.dataset': 'tychon.application'}}\"\n },\n {\n \"name\": \"_applyAppFilter\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"@applyBtn:click\",\n \"update\": \"kibanaAddFilter(activeFilter)\",\n \"force\": true\n }\n ]\n }\n ],\n \"data\": [\n {\n \"name\": \"apps\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-applications\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"tychon.application\" } },\n \"aggs\": {\n \"app_names\": {\n \"terms\": {\n \"field\": \"tychon.application.name\",\n \"size\": 200,\n \"order\": { \"_count\": \"desc\" }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.app_only.app_names.buckets\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"app\", \"expr\": \"datum.key\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"datum.doc_count\" },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rn\"] },\n { \"type\": \"formula\", \"as\": \"y\", \"expr\": \"72 + (datum.rn - 1) * 26\" },\n { \"type\": \"filter\", \"expr\": \"datum.rn \u003c= 15\" }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"signal\": \"height - 10\" },\n \"fill\": { \"value\": \"#0f1115\" },\n \"fillOpacity\": { \"value\": 0.96 },\n \"stroke\": { \"value\": \"#2b3440\" },\n \"strokeWidth\": { \"value\": 1.2 },\n \"cornerRadius\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"value\": 42 },\n \"fill\": { \"value\": \"#17324a\" },\n \"fillOpacity\": { \"value\": 0.92 },\n \"cornerRadiusTopLeft\": { \"value\": 8 },\n \"cornerRadiusTopRight\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 24 },\n \"y\": { \"value\": 30 },\n \"text\": { \"value\": \"APPLICATION FILTER\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 12 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#e8f3ff\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"name\": \"applyBtn\",\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"width - 92\" },\n \"y\": { \"value\": 16 },\n \"width\": { \"value\": 76 },\n \"height\": { \"value\": 20 },\n \"cornerRadius\": { \"value\": 10 },\n \"fill\": { \"value\": \"#17324a\" },\n \"stroke\": { \"value\": \"#9fd7ff\" },\n \"strokeWidth\": { \"value\": 1 },\n \"cursor\": { \"value\": \"pointer\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"width - 54\" },\n \"y\": { \"value\": 26 },\n \"text\": { \"value\": \"APPLY\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#dff0ff\" },\n \"align\": { \"value\": \"center\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"from\": { \"data\": \"apps\" },\n \"name\": \"appRowBg\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 18 },\n \"y\": { \"signal\": \"datum.y - 10\" },\n \"x2\": { \"signal\": \"width - 18\" },\n \"y2\": { \"signal\": \"datum.y + 10\" },\n \"cornerRadius\": { \"value\": 6 },\n \"fill\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#1f4d74' : '#0f1115'\" },\n \"stroke\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#9fd7ff' : '#253241'\" },\n \"strokeWidth\": { \"value\": 1 },\n \"cursor\": { \"value\": \"pointer\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"apps\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 30 },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"field\": \"app\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#e8f3ff' : '#c9d7e5'\" },\n \"baseline\": { \"value\": \"middle\" },\n \"limit\": { \"signal\": \"width - 110\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"apps\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"width - 30\" },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"signal\": \"format(datum.count, ',')\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#d9eeff' : '#8ea3b8'\" },\n \"align\": { \"value\": \"right\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n }\n ]\n}" + }, + "title": "QuantumApplicationList", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 19, + "i": "5de2ae04-5993-4e9b-9c32-674ec15c23cb", + "w": 8, + "x": 0, + "y": 2 + }, + "panelIndex": "5de2ae04-5993-4e9b-9c32-674ec15c23cb", + "title": "QuantumApplicationList", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"autosize\": \"fit\",\n \"padding\": 8,\n \"background\": \"#000000\",\n \"signals\": [\n {\n \"name\": \"zoom\",\n \"value\": 0.55,\n \"on\": [\n {\n \"events\": { \"type\": \"wheel\" },\n \"update\": \"clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6)\"\n }\n ]\n },\n {\n \"name\": \"panX\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": { \"type\": \"wheel\" },\n \"update\": \"((panX - (width/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (width/2)\"\n },\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"mousemove\",\n \"between\": [\n { \"source\": \"view\", \"type\": \"mousedown\" },\n { \"source\": \"window\", \"type\": \"mouseup\" }\n ]\n },\n \"update\": \"panX + event.movementX\"\n }\n ]\n },\n {\n \"name\": \"panY\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": { \"type\": \"wheel\" },\n \"update\": \"((panY - (height/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (height/2)\"\n },\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"mousemove\",\n \"between\": [\n { \"source\": \"view\", \"type\": \"mousedown\" },\n { \"source\": \"window\", \"type\": \"mouseup\" }\n ]\n },\n \"update\": \"panY + event.movementY\"\n }\n ]\n },\n {\n \"name\": \"selectedNode\",\n \"value\": null,\n \"on\": [\n {\n \"events\": \"@nodeMark:click\",\n \"update\": \"datum \u0026\u0026 isValid(datum.id) ? (selectedNode \u0026\u0026 selectedNode.id===datum.id ? null : datum) : selectedNode\"\n }\n ]\n },\n {\n \"name\": \"_applyNodeFilter\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"@nodeMark:dblclick\",\n \"update\": \"datum \u0026\u0026 isValid(datum.id) ? kibanaAddFilter((datum.nodeType === 'application' ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'tychon.application.name': toString(datum.id)}}]}} : {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'host.hostname': toString(datum.id)}}]}})) : 0\",\n \"force\": true\n }\n ]\n },\n {\n \"name\": \"adjPeerIds\",\n \"update\": \"isArray(data('adjacency')) ? pluck(data('adjacency'), 'peer') : []\"\n },\n {\n \"name\": \"adjPeer2Ids\",\n \"update\": \"isArray(data('adjacency2')) ? pluck(data('adjacency2'), 'peer') : []\"\n },\n {\n \"name\": \"highlightNodeIdsCsv\",\n \"update\": \"selectedNode ? (',' + toString(selectedNode.id) + ',' + join(adjPeerIds, ',') + ',' + join(adjPeer2Ids, ',') + ',') : ''\"\n },\n {\n \"name\": \"autoPanX\",\n \"update\": \"length(data('layout_center')) \u003e 0 \u0026\u0026 isFinite(data('layout_center')[0].cx) ? (width * 0.5) - (data('layout_center')[0].cx * zoom) : (width * (1 - zoom) * 0.5)\"\n },\n {\n \"name\": \"autoPanY\",\n \"update\": \"length(data('layout_center')) \u003e 0 \u0026\u0026 isFinite(data('layout_center')[0].cy) ? (height * 0.52) - (data('layout_center')[0].cy * zoom) : (height * (1 - zoom) * 0.5)\"\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-applications\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"pairs\": {\n \"filter\": {\n \"bool\": {\n \"must\": [\n { \"exists\": { \"field\": \"host.hostname\" } },\n { \"exists\": { \"field\": \"tychon.application.name\" } },\n { \"term\": { \"event.dataset\": \"tychon.application\" } }\n ]\n }\n },\n \"aggs\": {\n \"links\": {\n \"composite\": {\n \"size\": 500,\n \"sources\": [\n { \"src\": { \"terms\": { \"field\": \"host.hostname\" } } },\n { \"dst\": { \"terms\": { \"field\": \"tychon.application.name\" } } }\n ]\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.pairs.links.buckets\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"datum.key.src\" },\n { \"type\": \"formula\", \"as\": \"target\", \"expr\": \"datum.key.dst\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"toNumber(datum.doc_count)\" },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.target) \u0026\u0026 datum.source!='' \u0026\u0026 datum.target!=''\" }\n ]\n },\n {\n \"name\": \"nodes\",\n \"source\": \"raw\",\n \"transform\": [\n { \"type\": \"fold\", \"fields\": [\"source\", \"target\"], \"as\": [\"side\", \"id\"] },\n { \"type\": \"aggregate\", \"groupby\": [\"id\", \"side\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"] },\n { \"type\": \"formula\", \"as\": \"nodeType\", \"expr\": \"datum.side==='source' ? 'host' : 'application'\" }\n ]\n },\n {\n \"name\": \"edges\",\n \"source\": \"raw\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"target\", \"expr\": \"toString(datum.target)\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"toNumber(datum.count)\" },\n { \"type\": \"filter\", \"expr\": \"datum.source != '' \u0026\u0026 datum.target != ''\" }\n ]\n },\n {\n \"name\": \"layout\",\n \"source\": \"nodes\",\n \"transform\": [\n {\n \"type\": \"force\",\n \"iterations\": 300,\n \"static\": true,\n \"forces\": [\n { \"force\": \"center\", \"x\": { \"signal\": \"width * 0.5\" }, \"y\": { \"signal\": \"height * 0.52\" } },\n { \"force\": \"collide\", \"radius\": 20 },\n { \"force\": \"nbody\", \"strength\": -180 },\n { \"force\": \"link\", \"links\": \"edges\", \"id\": \"id\", \"distance\": 130 }\n ]\n }\n ]\n },\n {\n \"name\": \"layout_center\",\n \"source\": \"layout\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"ops\": [\"median\", \"median\"],\n \"fields\": [\"x\", \"y\"],\n \"as\": [\"cx\", \"cy\"]\n },\n { \"type\": \"formula\", \"as\": \"cx\", \"expr\": \"isFinite(datum.cx) ? datum.cx : 0\" },\n { \"type\": \"formula\", \"as\": \"cy\", \"expr\": \"isFinite(datum.cy) ? datum.cy : 0\" }\n ]\n },\n {\n \"name\": \"edges_draw\",\n \"source\": \"edges\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\" },\n { \"type\": \"formula\", \"as\": \"sx\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.x) ? datum.source.x * zoom + autoPanX + panX : null\" },\n { \"type\": \"formula\", \"as\": \"sy\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.y) ? datum.source.y * zoom + autoPanY + panY : null\" },\n { \"type\": \"formula\", \"as\": \"tx\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.x) ? datum.target.x * zoom + autoPanX + panX : null\" },\n { \"type\": \"formula\", \"as\": \"ty\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.y) ? datum.target.y * zoom + autoPanY + panY : null\" },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.sx) \u0026\u0026 isValid(datum.sy) \u0026\u0026 isValid(datum.tx) \u0026\u0026 isValid(datum.ty)\" }\n ]\n },\n {\n \"name\": \"adjacency\",\n \"source\": \"edges\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\" },\n { \"type\": \"filter\", \"expr\": \"selectedNode \u0026\u0026 (datum.srcId===toString(selectedNode.id) || datum.dstId===toString(selectedNode.id))\" },\n { \"type\": \"fold\", \"fields\": [\"srcId\", \"dstId\"], \"as\": [\"side\", \"peer\"] },\n { \"type\": \"filter\", \"expr\": \"datum.peer !== toString(selectedNode.id)\" },\n { \"type\": \"aggregate\", \"groupby\": [\"peer\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"] }\n ]\n },\n {\n \"name\": \"adjacency2\",\n \"source\": \"edges\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\" },\n { \"type\": \"filter\", \"expr\": \"selectedNode \u0026\u0026 (indexof(adjPeerIds, datum.srcId) \u003e= 0 || indexof(adjPeerIds, datum.dstId) \u003e= 0)\" },\n { \"type\": \"fold\", \"fields\": [\"srcId\", \"dstId\"], \"as\": [\"side\", \"peer\"] },\n { \"type\": \"filter\", \"expr\": \"datum.peer !== toString(selectedNode.id) \u0026\u0026 indexof(adjPeerIds, datum.peer) \u003c 0\" },\n { \"type\": \"aggregate\", \"groupby\": [\"peer\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"] }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 0 },\n \"y\": { \"value\": 0 },\n \"x2\": { \"signal\": \"width\" },\n \"y2\": { \"signal\": \"height\" },\n \"fill\": { \"value\": \"#000000\" }\n }\n }\n },\n {\n \"type\": \"rule\",\n \"from\": { \"data\": \"edges_draw\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"field\": \"sx\" },\n \"y\": { \"field\": \"sy\" },\n \"x2\": { \"field\": \"tx\" },\n \"y2\": { \"field\": \"ty\" },\n \"stroke\": {\n \"signal\": \"!selectedNode ? '#4fc3f7' : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') \u003e= 0 \u0026\u0026 indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') \u003e= 0) ? '#7fe8ff' : '#213240')\"\n },\n \"strokeOpacity\": {\n \"signal\": \"!selectedNode ? 0.42 : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') \u003e= 0 \u0026\u0026 indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') \u003e= 0) ? 0.75 : 0.08)\"\n },\n \"strokeWidth\": { \"value\": 0.9 }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": { \"data\": \"layout\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"datum.x * zoom + autoPanX + panX\" },\n \"y\": { \"signal\": \"datum.y * zoom + autoPanY + panY\" },\n \"size\": { \"value\": 980 },\n \"fill\": { \"signal\": \"datum.nodeType==='application' ? '#3b2b1a' : '#1a2c3b'\" },\n \"fillOpacity\": { \"value\": 0.9 },\n \"stroke\": { \"signal\": \"datum.nodeType==='application' ? '#ffd7a2' : '#a9dbff'\" },\n \"strokeWidth\": { \"value\": 1.2 },\n \"opacity\": { \"signal\": \"!selectedNode ? 1 : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') \u003e= 0 ? 1 : 0.2)\" }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"name\": \"nodeMark\",\n \"from\": { \"data\": \"layout\" },\n \"encode\": {\n \"enter\": {\n \"size\": { \"value\": 980 },\n \"fill\": { \"value\": \"#000000\" },\n \"fillOpacity\": { \"value\": 0.001 },\n \"stroke\": { \"value\": \"#000000\" },\n \"strokeOpacity\": { \"value\": 0.001 },\n \"cursor\": { \"value\": \"pointer\" }\n },\n \"update\": {\n \"x\": { \"signal\": \"datum.x * zoom + autoPanX + panX\" },\n \"y\": { \"signal\": \"datum.y * zoom + autoPanY + panY\" },\n \"size\": { \"value\": 980 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"layout\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"datum.x * zoom + autoPanX + panX\" },\n \"y\": { \"signal\": \"datum.y * zoom + autoPanY + panY - 14\" },\n \"text\": { \"field\": \"id\" },\n \"fill\": { \"signal\": \"!selectedNode ? '#e0e0e0' : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') \u003e= 0 ? '#f2f7ff' : '#4f5f6f')\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 9 },\n \"align\": { \"value\": \"center\" },\n \"baseline\": { \"value\": \"bottom\" }\n }\n }\n }\n ]\n}\n" + }, + "title": "PQC Connections Topology", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 36, + "i": "b07160f8-34a0-4c9c-b8e0-40c7841c9f86", + "w": 30, + "x": 8, + "y": 2 + }, + "panelIndex": "b07160f8-34a0-4c9c-b8e0-40c7841c9f86", + "title": "PQC Connections Topology", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Detail" + }, + "eventId": "28bdb45d-bec5-5991-b0c4-e7c31df068c4", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"Selection details panel for host/application context using dashboard filters.\",\n \"autosize\": \"fit\",\n \"padding\": 10,\n \"background\": \"#000000\",\n \"signals\": [\n { \"name\": \"panelW\", \"update\": \"width - 20\" },\n { \"name\": \"labelX\", \"value\": 26 },\n { \"name\": \"valueX\", \"update\": \"width * 0.42\" },\n { \"name\": \"row0\", \"value\": 74 },\n { \"name\": \"rowH\", \"value\": 24 }\n ],\n \"data\": [\n {\n \"name\": \"context\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"host\": { \"terms\": { \"field\": \"observer.hostname\", \"size\": 1 } },\n \"app\": { \"terms\": { \"field\": \"tychon.application.name.keyword\", \"size\": 1 } },\n \"dst\": { \"terms\": { \"field\": \"server.address\", \"size\": 1 } },\n \"proto\": { \"terms\": { \"field\": \"network.protocol\", \"size\": 1 } },\n \"tls_ver\": { \"terms\": { \"field\": \"tls.preferred_protocol\", \"size\": 1 } },\n \"cipher\": { \"terms\": { \"field\": \"tls.preferred_cipher\", \"size\": 1 } },\n \"events\": { \"value_count\": { \"field\": \"@timestamp\" } },\n \"first_seen\": { \"min\": { \"field\": \"@timestamp\" } },\n \"last_seen\": { \"max\": { \"field\": \"@timestamp\" } }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"host\",\n \"expr\": \"datum.host \u0026\u0026 datum.host.buckets \u0026\u0026 length(datum.host.buckets)\u003e0 ? datum.host.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"app\",\n \"expr\": \"datum.app \u0026\u0026 datum.app.buckets \u0026\u0026 length(datum.app.buckets)\u003e0 ? datum.app.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"dst\",\n \"expr\": \"datum.dst \u0026\u0026 datum.dst.buckets \u0026\u0026 length(datum.dst.buckets)\u003e0 ? datum.dst.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"proto\",\n \"expr\": \"datum.proto \u0026\u0026 datum.proto.buckets \u0026\u0026 length(datum.proto.buckets)\u003e0 ? datum.proto.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"tlsVer\",\n \"expr\": \"datum.tls_ver \u0026\u0026 datum.tls_ver.buckets \u0026\u0026 length(datum.tls_ver.buckets)\u003e0 ? datum.tls_ver.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"cipher\",\n \"expr\": \"datum.cipher \u0026\u0026 datum.cipher.buckets \u0026\u0026 length(datum.cipher.buckets)\u003e0 ? datum.cipher.buckets[0].key : ''\"\n },\n { \"type\": \"formula\", \"as\": \"events\", \"expr\": \"datum.events ? datum.events.value : 0\" },\n {\n \"type\": \"formula\",\n \"as\": \"firstSeen\",\n \"expr\": \"datum.first_seen \u0026\u0026 isValid(datum.first_seen.value_as_string) ? datum.first_seen.value_as_string : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"lastSeen\",\n \"expr\": \"datum.last_seen \u0026\u0026 isValid(datum.last_seen.value_as_string) ? datum.last_seen.value_as_string : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"selectionType\",\n \"expr\": \"datum.app != '' ? 'APPLICATION CONTEXT' : (datum.host != '' ? 'HOST CONTEXT' : 'NO SELECTION')\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"selectionId\",\n \"expr\": \"datum.app != '' ? datum.app : (datum.host != '' ? datum.host : 'Select a host/app in the graph')\"\n }\n ]\n },\n {\n \"name\": \"rows\",\n \"source\": \"context\",\n \"transform\": [\n {\n \"type\": \"project\",\n \"fields\": [\n \"selectionType\",\n \"selectionId\",\n \"host\",\n \"app\",\n \"dst\",\n \"proto\",\n \"tlsVer\",\n \"cipher\",\n \"events\",\n \"firstSeen\",\n \"lastSeen\"\n ],\n \"as\": [\n \"selectionType\",\n \"selectionId\",\n \"host\",\n \"app\",\n \"dst\",\n \"proto\",\n \"tlsVer\",\n \"cipher\",\n \"events\",\n \"firstSeen\",\n \"lastSeen\"\n ]\n },\n {\n \"type\": \"formula\",\n \"as\": \"kv\",\n \"expr\": \"[{k:'Context',v:datum.selectionType},{k:'Selection',v:datum.selectionId},{k:'Source Host',v:datum.host},{k:'Application',v:datum.app},{k:'Destination',v:datum.dst},{k:'Protocol',v:datum.proto},{k:'TLS Version',v:datum.tlsVer},{k:'Cipher',v:datum.cipher},{k:'Event Count',v:format(datum.events, ',')},{k:'First Seen',v:datum.firstSeen},{k:'Last Seen',v:datum.lastSeen}]\"\n },\n { \"type\": \"flatten\", \"fields\": [\"kv\"], \"as\": [\"row\"] },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rn\"] },\n { \"type\": \"formula\", \"as\": \"y\", \"expr\": \"row0 + (datum.rn - 1) * rowH\" }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"signal\": \"height - 10\" },\n \"fill\": { \"value\": \"#0f1115\" },\n \"fillOpacity\": { \"value\": 0.96 },\n \"stroke\": { \"value\": \"#2b3440\" },\n \"strokeWidth\": { \"value\": 1.2 },\n \"cornerRadius\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"value\": 42 },\n \"fill\": { \"value\": \"#17324a\" },\n \"fillOpacity\": { \"value\": 0.92 },\n \"cornerRadiusTopLeft\": { \"value\": 8 },\n \"cornerRadiusTopRight\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 24 },\n \"y\": { \"value\": 30 },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 12 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#e8f3ff\" },\n \"text\": { \"value\": \"SELECTION DETAILS\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"rule\",\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"valueX - 10\" },\n \"y\": { \"value\": 54 },\n \"y2\": { \"signal\": \"height - 20\" },\n \"stroke\": { \"value\": \"#1f2a36\" },\n \"strokeWidth\": { \"value\": 1 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"rows\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"labelX\" },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"signal\": \"datum.row.k\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#9fc4e0\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"rows\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"valueX\" },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"signal\": \"datum.row.v == '' ? '—' : datum.row.v\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"value\": \"#e8eef5\" },\n \"baseline\": { \"value\": \"middle\" },\n \"limit\": { \"signal\": \"width - valueX - 18\" }\n }\n }\n }\n ]\n}\n" + }, + "title": "Connections Selection Details", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 15, + "i": "903af92d-f9ab-4b97-8f31-4f46b66f7b49", + "w": 10, + "x": 38, + "y": 2 + }, + "panelIndex": "903af92d-f9ab-4b97-8f31-4f46b66f7b49", + "title": "Connections Selection Details", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "9ee0be55-05bd-533b-b46b-ac541ed779ff", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#000000\",\n \"signals\": [\n {\"name\": \"totalApps\", \"update\": \"length(data('apps_total'))\u003e0 ? data('apps_total')[0].n : 0\"},\n {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"},\n {\"name\": \"kexPct\", \"update\": \"totalApps \u003e 0 ? round(kexReady / totalApps * 100) : 0\"},\n {\"name\": \"kexClr\", \"update\": \"kexPct\u003e=90 ? '#00c853' : kexPct\u003e=60 ? '#448aff' : kexPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"protoReady\", \"update\": \"length(data('proto_pqc'))\u003e0 ? data('proto_pqc')[0].n : 0\"},\n {\"name\": \"protoPct\", \"update\": \"totalApps \u003e 0 ? round(protoReady / totalApps * 100) : 0\"},\n {\"name\": \"protoClr\", \"update\": \"protoPct\u003e=90 ? '#00c853' : protoPct\u003e=60 ? '#448aff' : protoPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))\u003e0 ? data('sig_pqc')[0].n : 0\"},\n {\"name\": \"sigPct\", \"update\": \"totalApps \u003e 0 ? round(sigReady / totalApps * 100) : 0\"},\n {\"name\": \"sigClr\", \"update\": \"sigPct\u003e=90 ? '#00c853' : sigPct\u003e=60 ? '#448aff' : sigPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"barW\", \"update\": \"width * 0.62 - 18\"}\n ],\n \"data\": [\n {\n \"name\": \"apps_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}\n },\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"apps_total\", \"source\": \"apps_raw\"},\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"},\n {\n \"name\": \"proto_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"proto_pqc\", \"source\": \"proto_pqc_raw\"},\n {\n \"name\": \"sig_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"}\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 22},\n \"text\": {\"value\": \"APPLICATION PQC DASHBOARD\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 40},\n \"text\": {\"signal\": \"'PQC COMPLIANCE PROGRESS — ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 78},\n \"text\": {\"value\": \"KEX COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 93},\n \"text\": {\"signal\": \"(kexReady\u003e=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY key exchange'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106},\n \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 158},\n \"text\": {\"value\": \"PROTOCOL COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 173},\n \"text\": {\"signal\": \"(protoReady\u003e=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — TLS 1.3 capable'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186},\n \"width\": {\"signal\": \"max(0, barW * protoPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202},\n \"text\": {\"signal\": \"protoPct + '%'\"},\n \"fill\": {\"signal\": \"protoClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 218},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 238},\n \"text\": {\"value\": \"CERT SIGNATURE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 253},\n \"text\": {\"signal\": \"(sigReady\u003e=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY signature'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266},\n \"width\": {\"signal\": \"max(0, barW * sigPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 282},\n \"text\": {\"signal\": \"sigPct + '%'\"},\n \"fill\": {\"signal\": \"sigClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "Application PQC Dashboard Risk", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 12, + "i": "6f785f49-4d43-42cb-92f3-c80b2c06f45d", + "w": 10, + "x": 38, + "y": 17 + }, + "panelIndex": "6f785f49-4d43-42cb-92f3-c80b2c06f45d", + "title": "Application PQC Dashboard Risk", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Cost Analysis" + }, + "eventId": "6e39195a-0cb6-50af-9f4c-94de184a31c3", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"Selection risk dial aligned to inventory OMB readiness tiers.\",\n \"autosize\": \"fit\",\n \"padding\": 10,\n \"background\": \"#000000\",\n \"signals\": [\n { \"name\": \"cx\", \"update\": \"width/2\" },\n { \"name\": \"cy\", \"update\": \"height*0.56\" },\n { \"name\": \"r\", \"update\": \"min(width, height) * 0.34\" }\n ],\n \"data\": [\n {\n \"name\": \"risk\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"apps_total\": { \"cardinality\": { \"field\": \"process.executable\" } },\n \"kex_ready\": {\n \"filter\": { \"term\": { \"omb.kex_tier\": \"PQC READY\" } },\n \"aggs\": { \"u\": { \"cardinality\": { \"field\": \"process.executable\" } } }\n },\n \"proto_ready\": {\n \"filter\": { \"term\": { \"omb.protocol_tier\": \"TLS 1.3\" } },\n \"aggs\": { \"u\": { \"cardinality\": { \"field\": \"process.executable\" } } }\n },\n \"sig_ready\": {\n \"filter\": { \"term\": { \"omb.sig_tier\": \"PQC READY\" } },\n \"aggs\": { \"u\": { \"cardinality\": { \"field\": \"process.executable\" } } }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"n\", \"expr\": \"isValid(datum.apps_total) \u0026\u0026 isValid(datum.apps_total.value) ? max(1, datum.apps_total.value) : 1\" },\n { \"type\": \"formula\", \"as\": \"kex_ready_n\", \"expr\": \"isValid(datum.kex_ready) \u0026\u0026 isValid(datum.kex_ready.u) \u0026\u0026 isValid(datum.kex_ready.u.value) ? datum.kex_ready.u.value : 0\" },\n { \"type\": \"formula\", \"as\": \"proto_ready_n\", \"expr\": \"isValid(datum.proto_ready) \u0026\u0026 isValid(datum.proto_ready.u) \u0026\u0026 isValid(datum.proto_ready.u.value) ? datum.proto_ready.u.value : 0\" },\n { \"type\": \"formula\", \"as\": \"sig_ready_n\", \"expr\": \"isValid(datum.sig_ready) \u0026\u0026 isValid(datum.sig_ready.u) \u0026\u0026 isValid(datum.sig_ready.u.value) ? datum.sig_ready.u.value : 0\" },\n { \"type\": \"formula\", \"as\": \"p_kex_ready\", \"expr\": \"100 * datum.kex_ready_n / datum.n\" },\n { \"type\": \"formula\", \"as\": \"p_proto_ready\", \"expr\": \"100 * datum.proto_ready_n / datum.n\" },\n { \"type\": \"formula\", \"as\": \"p_sig_ready\", \"expr\": \"100 * datum.sig_ready_n / datum.n\" },\n { \"type\": \"formula\", \"as\": \"readiness\", \"expr\": \"clamp(round((datum.p_kex_ready + datum.p_proto_ready + datum.p_sig_ready) / 3), 0, 100)\" },\n { \"type\": \"formula\", \"as\": \"score\", \"expr\": \"clamp(100 - datum.readiness, 0, 100)\" },\n { \"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.readiness \u003e= 90 ? 'LOW' : datum.readiness \u003e= 60 ? 'MEDIUM' : 'HIGH'\" },\n { \"type\": \"formula\", \"as\": \"color\", \"expr\": \"datum.readiness \u003e= 90 ? '#22c55e' : datum.readiness \u003e= 60 ? '#f59e0b' : '#ef4444'\" },\n { \"type\": \"formula\", \"as\": \"angle\", \"expr\": \"-3.1415926 + (datum.score/100) * 3.1415926 * 2\" }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"arc\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"r-18\"}, \"outerRadius\": {\"signal\": \"r\"},\n \"startAngle\": {\"value\": -3.1415926}, \"endAngle\": {\"value\": 3.1415926},\n \"fill\": {\"value\": \"#1f2937\"}\n }}\n },\n {\n \"type\": \"arc\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"r-18\"}, \"outerRadius\": {\"signal\": \"r\"},\n \"startAngle\": {\"value\": -3.1415926}, \"endAngle\": {\"field\": \"angle\"},\n \"fill\": {\"field\": \"color\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy - 6\"}, \"align\": {\"value\": \"center\"},\n \"text\": {\"signal\": \"format(datum.score, 'd') + '/100'\"}, \"font\": {\"value\": \"monospace\"},\n \"fontSize\": {\"value\": 28}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"field\": \"color\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + 24\"}, \"align\": {\"value\": \"center\"},\n \"text\": {\"signal\": \"datum.tier + ' RISK'\"}, \"font\": {\"value\": \"monospace\"},\n \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#cfe3f7\"}\n }}\n }\n ]\n}\n" + }, + "title": "QuantumRiskRadial", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 11, + "i": "7bb23bb3-53f1-48c8-914c-4108cf26dc05", + "w": 8, + "x": 0, + "y": 21 + }, + "panelIndex": "7bb23bb3-53f1-48c8-914c-4108cf26dc05", + "title": "Aggregate Risk Determination", + "type": "visualization" + } + ], + "timeRestore": false, + "title": "[TYCHON Quantum Command] Application Connections Topology", + "version": 3 }, - "description": "Aligns to schema 2.0.3", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"}}" - }, - "optionsJSON": "{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", - "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | [Certificate Report](/app/dashboards#/view/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard) | Application Connections Topology | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"title\":\"QuantumApplicationList\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"754afa08-289f-5a39-bc46-04d2b9e6e76a\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"QuantumApplicationList\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Application filter list panel (multi-select) with dashboard filter integration.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"selectedApps\\\",\\n \\\"value\\\": \\\"|\\\",\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@appRowBg:click\\\",\\n \\\"update\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? replace(selectedApps, '|' + datum.app + '|', '|') : selectedApps + datum.app + '|'\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedAppsArray\\\",\\n \\\"update\\\": \\\"selectedApps == '|' ? [] : split(slice(selectedApps, 1, length(selectedApps)-1), '|')\\\"\\n },\\n {\\n \\\"name\\\": \\\"activeFilter\\\",\\n \\\"update\\\": \\\"length(selectedAppsArray) > 0 ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'terms': {'tychon.application.name': selectedAppsArray}}]}} : {'term': {'event.dataset': 'tychon.application'}}\\\"\\n },\\n {\\n \\\"name\\\": \\\"_applyAppFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@applyBtn:click\\\",\\n \\\"update\\\": \\\"kibanaAddFilter(activeFilter)\\\",\\n \\\"force\\\": true\\n }\\n ]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } },\\n \\\"aggs\\\": {\\n \\\"app_names\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"tychon.application.name\\\",\\n \\\"size\\\": 200,\\n \\\"order\\\": { \\\"_count\\\": \\\"desc\\\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.app_names.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"datum.doc_count\\\" },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"72 + (datum.rn - 1) * 26\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rn <= 15\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLICATION FILTER\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"applyBtn\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 92\\\" },\\n \\\"y\\\": { \\\"value\\\": 16 },\\n \\\"width\\\": { \\\"value\\\": 76 },\\n \\\"height\\\": { \\\"value\\\": 20 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#9fd7ff\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 54\\\" },\\n \\\"y\\\": { \\\"value\\\": 26 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLY\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#dff0ff\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"name\\\": \\\"appRowBg\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 18 },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y - 10\\\" },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 18\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"datum.y + 10\\\" },\\n \\\"cornerRadius\\\": { \\\"value\\\": 6 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#1f4d74' : '#0f1115'\\\" },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#9fd7ff' : '#253241'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 30 },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"app\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#e8f3ff' : '#c9d7e5'\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - 110\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 30\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(datum.count, ',')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#d9eeff' : '#8ea3b8'\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"right\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n }\\n ]\\n}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"5de2ae04-5993-4e9b-9c32-674ec15c23cb\",\"gridData\":{\"i\":\"5de2ae04-5993-4e9b-9c32-674ec15c23cb\",\"y\":2,\"x\":0,\"w\":8,\"h\":19}},{\"type\":\"visualization\",\"title\":\"PQC Connections Topology\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"PQC Connections Topology\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 8,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"zoom\\\",\\n \\\"value\\\": 0.55,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6)\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panX\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panX - (width/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (width/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panX + event.movementX\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panY\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panY - (height/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (height/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panY + event.movementY\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedNode\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:click\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? (selectedNode && selectedNode.id===datum.id ? null : datum) : selectedNode\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"_applyNodeFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:dblclick\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? kibanaAddFilter((datum.nodeType === 'application' ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'tychon.application.name': toString(datum.id)}}]}} : {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'host.hostname': toString(datum.id)}}]}})) : 0\\\",\\n \\\"force\\\": true\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjPeerIds\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency')) ? pluck(data('adjacency'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"adjPeer2Ids\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency2')) ? pluck(data('adjacency2'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"highlightNodeIdsCsv\\\",\\n \\\"update\\\": \\\"selectedNode ? (',' + toString(selectedNode.id) + ',' + join(adjPeerIds, ',') + ',' + join(adjPeer2Ids, ',') + ',') : ''\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanX\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cx) ? (width * 0.5) - (data('layout_center')[0].cx * zoom) : (width * (1 - zoom) * 0.5)\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanY\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cy) ? (height * 0.52) - (data('layout_center')[0].cy * zoom) : (height * (1 - zoom) * 0.5)\\\"\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"pairs\\\": {\\n \\\"filter\\\": {\\n \\\"bool\\\": {\\n \\\"must\\\": [\\n { \\\"exists\\\": { \\\"field\\\": \\\"host.hostname\\\" } },\\n { \\\"exists\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } },\\n { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } }\\n ]\\n }\\n },\\n \\\"aggs\\\": {\\n \\\"links\\\": {\\n \\\"composite\\\": {\\n \\\"size\\\": 500,\\n \\\"sources\\\": [\\n { \\\"src\\\": { \\\"terms\\\": { \\\"field\\\": \\\"host.hostname\\\" } } },\\n { \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } } }\\n ]\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.pairs.links.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"datum.key.src\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"datum.key.dst\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.doc_count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.target) && datum.source!='' && datum.target!=''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"nodes\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"source\\\", \\\"target\\\"], \\\"as\\\": [\\\"side\\\", \\\"id\\\"] },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"id\\\", \\\"side\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"nodeType\\\", \\\"expr\\\": \\\"datum.side==='source' ? 'host' : 'application'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.source != '' && datum.target != ''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout\\\",\\n \\\"source\\\": \\\"nodes\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"force\\\",\\n \\\"iterations\\\": 300,\\n \\\"static\\\": true,\\n \\\"forces\\\": [\\n { \\\"force\\\": \\\"center\\\", \\\"x\\\": { \\\"signal\\\": \\\"width * 0.5\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"height * 0.52\\\" } },\\n { \\\"force\\\": \\\"collide\\\", \\\"radius\\\": 20 },\\n { \\\"force\\\": \\\"nbody\\\", \\\"strength\\\": -180 },\\n { \\\"force\\\": \\\"link\\\", \\\"links\\\": \\\"edges\\\", \\\"id\\\": \\\"id\\\", \\\"distance\\\": 130 }\\n ]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout_center\\\",\\n \\\"source\\\": \\\"layout\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"ops\\\": [\\\"median\\\", \\\"median\\\"],\\n \\\"fields\\\": [\\\"x\\\", \\\"y\\\"],\\n \\\"as\\\": [\\\"cx\\\", \\\"cy\\\"]\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cx\\\", \\\"expr\\\": \\\"isFinite(datum.cx) ? datum.cx : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cy\\\", \\\"expr\\\": \\\"isFinite(datum.cy) ? datum.cy : 0\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges_draw\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sx\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.x) ? datum.source.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sy\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.y) ? datum.source.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tx\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.x) ? datum.target.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"ty\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.y) ? datum.target.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.sx) && isValid(datum.sy) && isValid(datum.tx) && isValid(datum.ty)\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (datum.srcId===toString(selectedNode.id) || datum.dstId===toString(selectedNode.id))\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id)\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency2\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (indexof(adjPeerIds, datum.srcId) >= 0 || indexof(adjPeerIds, datum.dstId) >= 0)\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id) && indexof(adjPeerIds, datum.peer) < 0\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"edges_draw\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"field\\\": \\\"sx\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"sy\\\" },\\n \\\"x2\\\": { \\\"field\\\": \\\"tx\\\" },\\n \\\"y2\\\": { \\\"field\\\": \\\"ty\\\" },\\n \\\"stroke\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? '#4fc3f7' : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? '#7fe8ff' : '#213240')\\\"\\n },\\n \\\"strokeOpacity\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? 0.42 : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? 0.75 : 0.08)\\\"\\n },\\n \\\"strokeWidth\\\": { \\\"value\\\": 0.9 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#3b2b1a' : '#1a2c3b'\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.9 },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#ffd7a2' : '#a9dbff'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"opacity\\\": { \\\"signal\\\": \\\"!selectedNode ? 1 : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? 1 : 0.2)\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"name\\\": \\\"nodeMark\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"strokeOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n },\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY - 14\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"id\\\" },\\n \\\"fill\\\": { \\\"signal\\\": \\\"!selectedNode ? '#e0e0e0' : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? '#f2f7ff' : '#4f5f6f')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"bottom\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"b07160f8-34a0-4c9c-b8e0-40c7841c9f86\",\"gridData\":{\"i\":\"b07160f8-34a0-4c9c-b8e0-40c7841c9f86\",\"y\":2,\"x\":8,\"w\":30,\"h\":36}},{\"type\":\"visualization\",\"title\":\"Connections Selection Details\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"28bdb45d-bec5-5991-b0c4-e7c31df068c4\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Detail\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Connections Selection Details\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection details panel for host/application context using dashboard filters.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"panelW\\\", \\\"update\\\": \\\"width - 20\\\" },\\n { \\\"name\\\": \\\"labelX\\\", \\\"value\\\": 26 },\\n { \\\"name\\\": \\\"valueX\\\", \\\"update\\\": \\\"width * 0.42\\\" },\\n { \\\"name\\\": \\\"row0\\\", \\\"value\\\": 74 },\\n { \\\"name\\\": \\\"rowH\\\", \\\"value\\\": 24 }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"context\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"host\\\": { \\\"terms\\\": { \\\"field\\\": \\\"observer.hostname\\\", \\\"size\\\": 1 } },\\n \\\"app\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name.keyword\\\", \\\"size\\\": 1 } },\\n \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"server.address\\\", \\\"size\\\": 1 } },\\n \\\"proto\\\": { \\\"terms\\\": { \\\"field\\\": \\\"network.protocol\\\", \\\"size\\\": 1 } },\\n \\\"tls_ver\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_protocol\\\", \\\"size\\\": 1 } },\\n \\\"cipher\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_cipher\\\", \\\"size\\\": 1 } },\\n \\\"events\\\": { \\\"value_count\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"first_seen\\\": { \\\"min\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"last_seen\\\": { \\\"max\\\": { \\\"field\\\": \\\"@timestamp\\\" } }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"host\\\",\\n \\\"expr\\\": \\\"datum.host && datum.host.buckets && length(datum.host.buckets)>0 ? datum.host.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app\\\",\\n \\\"expr\\\": \\\"datum.app && datum.app.buckets && length(datum.app.buckets)>0 ? datum.app.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"dst\\\",\\n \\\"expr\\\": \\\"datum.dst && datum.dst.buckets && length(datum.dst.buckets)>0 ? datum.dst.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"proto\\\",\\n \\\"expr\\\": \\\"datum.proto && datum.proto.buckets && length(datum.proto.buckets)>0 ? datum.proto.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tlsVer\\\",\\n \\\"expr\\\": \\\"datum.tls_ver && datum.tls_ver.buckets && length(datum.tls_ver.buckets)>0 ? datum.tls_ver.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"cipher\\\",\\n \\\"expr\\\": \\\"datum.cipher && datum.cipher.buckets && length(datum.cipher.buckets)>0 ? datum.cipher.buckets[0].key : ''\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"events\\\", \\\"expr\\\": \\\"datum.events ? datum.events.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"firstSeen\\\",\\n \\\"expr\\\": \\\"datum.first_seen && isValid(datum.first_seen.value_as_string) ? datum.first_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"lastSeen\\\",\\n \\\"expr\\\": \\\"datum.last_seen && isValid(datum.last_seen.value_as_string) ? datum.last_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionType\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? 'APPLICATION CONTEXT' : (datum.host != '' ? 'HOST CONTEXT' : 'NO SELECTION')\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionId\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? datum.app : (datum.host != '' ? datum.host : 'Select a host/app in the graph')\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"context\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"project\\\",\\n \\\"fields\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ],\\n \\\"as\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ]\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"kv\\\",\\n \\\"expr\\\": \\\"[{k:'Context',v:datum.selectionType},{k:'Selection',v:datum.selectionId},{k:'Source Host',v:datum.host},{k:'Application',v:datum.app},{k:'Destination',v:datum.dst},{k:'Protocol',v:datum.proto},{k:'TLS Version',v:datum.tlsVer},{k:'Cipher',v:datum.cipher},{k:'Event Count',v:format(datum.events, ',')},{k:'First Seen',v:datum.firstSeen},{k:'Last Seen',v:datum.lastSeen}]\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"kv\\\"], \\\"as\\\": [\\\"row\\\"] },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"row0 + (datum.rn - 1) * rowH\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"SELECTION DETAILS\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX - 10\\\" },\\n \\\"y\\\": { \\\"value\\\": 54 },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 20\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#1f2a36\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"labelX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.k\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#9fc4e0\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.v == '' ? '\\u2014' : datum.row.v\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8eef5\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - valueX - 18\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"903af92d-f9ab-4b97-8f31-4f46b66f7b49\",\"gridData\":{\"i\":\"903af92d-f9ab-4b97-8f31-4f46b66f7b49\",\"y\":2,\"x\":38,\"w\":10,\"h\":15}},{\"type\":\"visualization\",\"title\":\"Application PQC Dashboard Risk\",\"embeddableConfig\":{\"description\":\"\",\"hidePanelTitles\":true,\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9ee0be55-05bd-533b-b46b-ac541ed779ff\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Application PQC Dashboard Risk\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"totalApps\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"protoReady\\\", \\\"update\\\": \\\"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"protoPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"protoClr\\\", \\\"update\\\": \\\"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"barW\\\", \\\"update\\\": \\\"width * 0.62 - 18\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"proto_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"proto_pqc\\\", \\\"source\\\": \\\"proto_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"APPLICATION PQC DASHBOARD\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"signal\\\": \\\"'PQC COMPLIANCE PROGRESS \\u2014 ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"KEX COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY key exchange'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"PROTOCOL COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 TLS 1.3 capable'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * protoPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"protoPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 218},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 238},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 253},\\n \\\"text\\\": {\\\"signal\\\": \\\"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY signature'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * sigPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 282},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"6f785f49-4d43-42cb-92f3-c80b2c06f45d\",\"gridData\":{\"i\":\"6f785f49-4d43-42cb-92f3-c80b2c06f45d\",\"y\":17,\"x\":38,\"w\":10,\"h\":12}},{\"type\":\"visualization\",\"title\":\"Aggregate Risk Determination\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"6e39195a-0cb6-50af-9f4c-94de184a31c3\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"QuantumRiskRadial\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection risk dial aligned to inventory OMB readiness tiers.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"cx\\\", \\\"update\\\": \\\"width/2\\\" },\\n { \\\"name\\\": \\\"cy\\\", \\\"update\\\": \\\"height*0.56\\\" },\\n { \\\"name\\\": \\\"r\\\", \\\"update\\\": \\\"min(width, height) * 0.34\\\" }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"risk\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"apps_total\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } },\\n \\\"kex_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.kex_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"proto_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"sig_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.sig_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"isValid(datum.apps_total) && isValid(datum.apps_total.value) ? max(1, datum.apps_total.value) : 1\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"kex_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.kex_ready) && isValid(datum.kex_ready.u) && isValid(datum.kex_ready.u.value) ? datum.kex_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"proto_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.proto_ready) && isValid(datum.proto_ready.u) && isValid(datum.proto_ready.u.value) ? datum.proto_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sig_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.sig_ready) && isValid(datum.sig_ready.u) && isValid(datum.sig_ready.u.value) ? datum.sig_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_kex_ready\\\", \\\"expr\\\": \\\"100 * datum.kex_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_proto_ready\\\", \\\"expr\\\": \\\"100 * datum.proto_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_sig_ready\\\", \\\"expr\\\": \\\"100 * datum.sig_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"readiness\\\", \\\"expr\\\": \\\"clamp(round((datum.p_kex_ready + datum.p_proto_ready + datum.p_sig_ready) / 3), 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"score\\\", \\\"expr\\\": \\\"clamp(100 - datum.readiness, 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? 'LOW' : datum.readiness >= 60 ? 'MEDIUM' : 'HIGH'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"color\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? '#22c55e' : datum.readiness >= 60 ? '#f59e0b' : '#ef4444'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"angle\\\", \\\"expr\\\": \\\"-3.1415926 + (datum.score/100) * 3.1415926 * 2\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"value\\\": 3.1415926},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1f2937\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"field\\\": \\\"angle\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy - 6\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.score, 'd') + '/100'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 28}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + 24\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.tier + ' RISK'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cfe3f7\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"7bb23bb3-53f1-48c8-914c-4108cf26dc05\",\"gridData\":{\"i\":\"7bb23bb3-53f1-48c8-914c-4108cf26dc05\",\"y\":21,\"x\":0,\"w\":8,\"h\":11}}]", - "timeRestore": false, - "title": "[TYCHON Quantum Command] Application Connections Topology", - "version": 3 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", - "managed": false, - "originId": "67c35d70-7848-45c9-80e1-93a359eccf5b", - "references": [ - { - "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", - "name": "5de2ae04-5993-4e9b-9c32-674ec15c23cb:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:754afa08-289f-5a39-bc46-04d2b9e6e76a:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "6f785f49-4d43-42cb-92f3-c80b2c06f45d:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9ee0be55-05bd-533b-b46b-ac541ed779ff:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", - "name": "7bb23bb3-53f1-48c8-914c-4108cf26dc05:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:6e39195a-0cb6-50af-9f4c-94de184a31c3:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", - "name": "903af92d-f9ab-4b97-8f31-4f46b66f7b49:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:28bdb45d-bec5-5991-b0c4-e7c31df068c4:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", - "name": "tag-ref-2a2cc491-f59c-4504-b146-049aa17a25f2", - "type": "tag" - }, - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", - "type": "tag" - } - ], - "type": "dashboard", - "typeMigrationVersion": "10.2.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NzIsMzBd" -} + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", + "references": [ + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "5de2ae04-5993-4e9b-9c32-674ec15c23cb:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:754afa08-289f-5a39-bc46-04d2b9e6e76a:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "6f785f49-4d43-42cb-92f3-c80b2c06f45d:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9ee0be55-05bd-533b-b46b-ac541ed779ff:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "7bb23bb3-53f1-48c8-914c-4108cf26dc05:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:6e39195a-0cb6-50af-9f4c-94de184a31c3:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", + "name": "903af92d-f9ab-4b97-8f31-4f46b66f7b49:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:28bdb45d-bec5-5991-b0c4-e7c31df068c4:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.3.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json index e76c1b2f4e2..92534543c69 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json @@ -1,92 +1,653 @@ { - "attributes": { - "controlGroupInput": { - "chainingSystem": "HIERARCHICAL", - "controlStyle": "oneLine", - "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", - "panelsJSON": "{}", - "showApplySelections": false + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": {}, + "showApplySelections": false + }, + "description": "Operational view of all discovered certificates — quantum readiness, hygiene, key algorithms, and issuer coverage", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": true, + "syncColors": false, + "syncCursor": true, + "syncTooltips": true, + "useMargins": false + }, + "panelsJSON": [ + { + "embeddableConfig": { + "enhancements": {}, + "hidePanelTitles": true, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | Certificate Report | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 3, + "i": "tychon-quantum-command-nav", + "w": 48, + "x": 0, + "y": 0 + }, + "panelIndex": "tychon-quantum-command-nav", + "title": "", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"total\", \"update\": \"length(data('d_total'))\u003e0 ? data('d_total')[0].n : 0\"}, {\"name\": \"expired\", \"update\": \"length(data('d_expired'))\u003e0 ? data('d_expired')[0].n : 0\"}, {\"name\": \"exp30\", \"update\": \"length(data('d_exp30'))\u003e0 ? data('d_exp30')[0].n : 0\"}, {\"name\": \"self\", \"update\": \"length(data('d_self'))\u003e0 ? data('d_self')[0].n : 0\"}, {\"name\": \"legacy\", \"update\": \"length(data('d_legacy'))\u003e0 ? data('d_legacy')[0].n : 0\"}, {\"name\": \"pqcvuln\", \"update\": \"length(data('d_pqcvuln'))\u003e0 ? data('d_pqcvuln')[0].n : 0\"}, {\"name\": \"bw\", \"update\": \"floor((width - 10) / 6) - 4\"}, {\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"tile\"}, \"update\": \"datum.filt ? (datum.k === sel ? null : datum.k) : sel\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"tile\"}, \"update\": \"datum.filt ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"d_total\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"tychon.type\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"d_expired\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_exp30\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_self\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"certificate.is_self_signed\": true}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_legacy\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"LEGACY\"}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_pqcvuln\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"terms\": {\"omb.sig_tier\": [\"CLASSICAL\", \"MODERN\", \"LEGACY\"]}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"tiles\", \"values\": [{\"k\": \"TOTAL\", \"ord\": 0, \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"sig\": \"total\", \"filt\": null}, {\"k\": \"EXPIRED\", \"ord\": 1, \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"sig\": \"expired\", \"filt\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, {\"k\": \"EXP 30D\", \"ord\": 2, \"clr\": \"#ff7043\", \"bg\": \"#ff704318\", \"sig\": \"exp30\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, {\"k\": \"SELF-SIGNED\", \"ord\": 3, \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"sig\": \"self\", \"filt\": {\"term\": {\"certificate.is_self_signed\": true}}}, {\"k\": \"LEGACY\", \"ord\": 4, \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"sig\": \"legacy\", \"filt\": {\"term\": {\"omb.sig_tier\": \"LEGACY\"}}}, {\"k\": \"PQC VULN\", \"ord\": 5, \"clr\": \"#ab47bc\", \"bg\": \"#ab47bc18\", \"sig\": \"pqcvuln\", \"filt\": {\"terms\": {\"omb.sig_tier\": [\"CLASSICAL\", \"MODERN\", \"LEGACY\"]}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"x\", \"expr\": \"datum.ord * (bw + 4) + 8\"}, {\"type\": \"formula\", \"as\": \"val\", \"expr\": \"datum.sig === 'total' ? total : datum.sig === 'expired' ? expired : datum.sig === 'exp30' ? exp30 : datum.sig === 'self' ? self : datum.sig === 'legacy' ? legacy : pqcvuln\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE INVENTORY\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"OPERATIONAL OVERVIEW \\u2014 click a tile to filter the dashboard\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"tile\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"field\": \"x\"}, \"y\": {\"value\": 52}, \"width\": {\"signal\": \"bw\"}, \"height\": {\"value\": 72}, \"fill\": {\"signal\": \"datum.k === sel ? datum.bg : '#161616'\"}, \"cornerRadius\": {\"value\": 3}, \"stroke\": {\"signal\": \"datum.k === sel ? datum.clr : (datum.val \u003e 0 \u0026\u0026 datum.filt ? '#2a2a3a' : '#222222')\"}, \"strokeWidth\": {\"signal\": \"datum.k === sel ? 2 : 1\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x + bw/2\"}, \"y\": {\"value\": 88}, \"text\": {\"signal\": \"datum.val \u003e= 1000 ? format(datum.val,'.3~s') : format(datum.val,',')\"}, \"fill\": {\"signal\": \"datum.k === sel ? datum.clr : (datum.val \u003e 0 ? datum.clr : '#3a3a3a')\"}, \"fontSize\": {\"value\": 22}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x + bw/2\"}, \"y\": {\"value\": 108}, \"text\": {\"field\": \"k\"}, \"fill\": {\"signal\": \"datum.k === sel ? datum.clr : '#666666'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}]}" + }, + "title": "CERT OPS — Inventory Header", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 8, + "i": "74b385d6-da5a-438e-a0af-f1a77dab28db", + "w": 48, + "x": 0, + "y": 2 + }, + "panelIndex": "74b385d6-da5a-438e-a0af-f1a77dab28db", + "title": "CERT OPS — Inventory Header", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Inventory" + }, + "eventId": "f676853f-014e-5857-89ba-97b22fb271af", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 10}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"n\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature \\u2014 quantum-resistant, CNSA 2.0 approved\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve \\u2014 quantum-vulnerable via Shor's algorithm, must be replaced pre-2035\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA \\u2014 quantum-vulnerable via Shor's algorithm, harvest-now-decrypt-later risk today\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"SHA-1/MD5 hash \\u2014 classically broken and quantum-vulnerable, replace immediately\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#b71c1c\", \"bg\": \"#b71c1c22\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 55}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"field\": \"badge\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 106}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.5\"}, \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 106}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.56\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 38\"}, \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"}, \"fill\": {\"signal\": \"datum.t===sel ? datum.clr : datum.n\u003e0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 50\"}, \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\"}, \"height\": {\"value\": 6}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.clr + '55'\"}}}}]}" + }, + "title": "CERT OPS — Quantum Tier", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 29, + "i": "187d7c49-96d6-43fe-a3d7-ee51f605e0f5", + "w": 16, + "x": 0, + "y": 10 + }, + "panelIndex": "187d7c49-96d6-43fe-a3d7-ee51f605e0f5", + "title": "CERT OPS — Quantum Tier", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Cost Analysis" + }, + "eventId": "c9ef7c09-bbcf-57c7-bcbc-d3fae0140da2", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.n \u003e 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"expired\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, \"exp30\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, \"exp90\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now+30d\", \"lt\": \"now+90d\"}}}}, \"selfsign\": {\"filter\": {\"term\": {\"certificate.is_self_signed\": true}}}, \"weakkey\": {\"filter\": {\"terms\": {\"certificate.subject_public_key_info.bit_size\": [512, 1024]}}}, \"total\": {\"value_count\": {\"field\": \"certificate.not_after\"}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"expired\", \"expr\": \"datum.expired ? datum.expired.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"exp30\", \"expr\": \"datum.exp30 ? datum.exp30.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"exp90\", \"expr\": \"datum.exp90 ? datum.exp90.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"selfsign\", \"expr\": \"datum.selfsign ? datum.selfsign.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"weakkey\", \"expr\": \"datum.weakkey ? datum.weakkey.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"total\", \"expr\": \"datum.total ? datum.total.value : 0\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"EXPIRED\", \"lbl\": \"Expired\", \"desc\": \"certificate.not_after \u003c now \\u2014 no longer trusted by any client\", \"sev\": \"critical\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 0, \"field\": \"expired\", \"filt\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, {\"k\": \"EXP 30D\", \"lbl\": \"Expiring in 30 days\", \"desc\": \"certificate.not_after within 30 days \\u2014 immediate renewal required\", \"sev\": \"high\", \"clr\": \"#ff7043\", \"bg\": \"#ff704318\", \"ord\": 1, \"field\": \"exp30\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, {\"k\": \"EXP 90D\", \"lbl\": \"Expiring in 90 days\", \"desc\": \"certificate.not_after within 90 days \\u2014 plan renewal now\", \"sev\": \"medium\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2, \"field\": \"exp90\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now+30d\", \"lt\": \"now+90d\"}}}}, {\"k\": \"SELF-SIGNED\", \"lbl\": \"Self-Signed\", \"desc\": \"certificate.is_self_signed = true \\u2014 no CA trust chain, browser errors\", \"sev\": \"medium\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 3, \"field\": \"selfsign\", \"filt\": {\"term\": {\"certificate.is_self_signed\": true}}}, {\"k\": \"WEAK KEY\", \"lbl\": \"Weak Key \\u22641024-bit\", \"desc\": \"RSA/DSA key \\u22641024 bits \\u2014 computationally breakable, must be replaced\", \"sev\": \"critical\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 4, \"field\": \"weakkey\", \"filt\": {\"terms\": {\"certificate.subject_public_key_info.bit_size\": [512, 1024]}}}], \"transform\": [{\"type\": \"lookup\", \"from\": \"raw\", \"key\": \"total\", \"fields\": [\"ord\"], \"values\": [\"expired\", \"exp30\", \"exp90\", \"selfsign\", \"weakkey\", \"total\"], \"as\": [\"v_expired\", \"v_exp30\", \"v_exp90\", \"v_selfsign\", \"v_weakkey\", \"v_total\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.field==='expired' ? (length(data('raw'))\u003e0?data('raw')[0].expired:0) : datum.field==='exp30' ? (length(data('raw'))\u003e0?data('raw')[0].exp30:0) : datum.field==='exp90' ? (length(data('raw'))\u003e0?data('raw')[0].exp90:0) : datum.field==='selfsign' ? (length(data('raw'))\u003e0?data('raw')[0].selfsign:0) : (length(data('raw'))\u003e0?data('raw')[0].weakkey:0)\"}, {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('raw'))\u003e0 ? data('raw')[0].total : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 68 + 52\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE HYGIENE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"OPERATIONAL ISSUES \\u2014 expiry \\u00b7 trust \\u00b7 key strength\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 62}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n\u003e0 ? datum.bg : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 62}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 61\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 7\"}, \"width\": {\"value\": 72}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 36\"}, \"y\": {\"signal\": \"datum.y + 19\"}, \"text\": {\"field\": \"sev\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 29\"}, \"width\": {\"value\": 72}, \"height\": {\"value\": 14}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"signal\": \"datum.n \u003e 0 ? '#333333' : '#222222'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 36\"}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"signal\": \"datum.tot \u003e 0 ? format(datum.pct * 100, '.1f') + '%' : '\\u2014'\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n \u003e 0 ? (datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.n\u003e0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}]}" + }, + "title": "Certificate Hygiene", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 29, + "i": "48d7d98f-27df-4c04-a736-8e772da0b028", + "w": 16, + "x": 16, + "y": 10 + }, + "panelIndex": "48d7d98f-27df-4c04-a736-8e772da0b028", + "title": "Certificate Hygiene", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Inventory" + }, + "eventId": "5a19f6d5-01ea-5a0d-9469-870400433156", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.issuer_organization': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.issuer_organization': datum.k}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_issuer\": {\"terms\": {\"field\": \"certificate.issuer_organization\", \"size\": 10, \"order\": {\"_count\": \"desc\"}}}\n }}},\n \"format\": {\"property\": \"aggregations.by_issuer.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 52 + 52\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.rnk === 1 ? '#448aff' : datum.rnk === 2 ? '#4db6ac' : datum.rnk \u003c= 5 ? '#546e7a' : '#37474f'\"}\n ]\n },\n {\n \"name\": \"mx\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"TOP ISSUING CAs\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"CERTIFICATE AUTHORITY — who issued your certificates · click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 46},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 3}, \"height\": {\"value\": 46},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 30}, \"y\": {\"signal\": \"datum.y + 17\"},\n \"text\": {\"signal\": \"format(datum.rnk, 'd') + '.'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 10},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 36}, \"y\": {\"signal\": \"datum.y + 17\"},\n \"text\": {\"field\": \"k\"}, \"limit\": {\"signal\": \"width * 0.62\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 36}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * (width * 0.62) : 0\"},\n \"height\": {\"value\": 5}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.clr + '66'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 45\"},\n \"stroke\": {\"value\": \"#1e1e1e\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#888888'\"},\n \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "CERT OPS — Top Issuing CAs", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 29, + "i": "df2ef032-250b-40c9-93de-3f6211bddac5", + "w": 16, + "x": 32, + "y": 10 + }, + "panelIndex": "df2ef032-250b-40c9-93de-3f6211bddac5", + "title": "CERT OPS — Top Issuing CAs", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "195b2262-1d5d-50e1-86d2-f404cd493030", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_algo\": {\"terms\": {\"field\": \"certificate.subject_public_key_info.algorithm\", \"size\": 10}},\n \"total\": {\"value_count\": {\"field\": \"id\"}}\n }}},\n \"format\": {\"property\": \"aggregations.by_algo.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}\n ]\n },\n {\n \"name\": \"tot\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\n \"name\": \"palette\",\n \"values\": [\n {\"k\": \"RSA\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"lbl\": \"RSA\", \"desc\": \"Rivest–Shamir–Adleman — quantum-vulnerable via Shor's algorithm\"},\n {\"k\": \"ECDSA\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"lbl\": \"ECDSA\", \"desc\": \"Elliptic curve — quantum-vulnerable, efficient on classical hardware\"},\n {\"k\": \"DSA\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"lbl\": \"DSA\", \"desc\": \"Digital Signature Algorithm — deprecated, should not be in new certs\"},\n {\"k\": \"unknown_der\", \"clr\": \"#78909c\", \"bg\": \"#78909c18\", \"lbl\": \"Unknown DER\", \"desc\": \"DER-encoded cert with unrecognized key OID\"},\n {\"k\": \"unknown_pem\", \"clr\": \"#78909c\", \"bg\": \"#78909c18\", \"lbl\": \"Unknown PEM\", \"desc\": \"PEM-encoded cert with unrecognized key OID\"},\n {\"k\": \"ML-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"ML-DSA\", \"desc\": \"Lattice-based PQC signature — CNSA 2.0 quantum-resistant\"},\n {\"k\": \"SLH-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"SLH-DSA\", \"desc\": \"Hash-based PQC signature — CNSA 2.0 quantum-resistant\"},\n {\"k\": \"FN-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"FN-DSA\", \"desc\": \"Falcon lattice signature — CNSA 2.0 quantum-resistant\"}\n ]\n },\n {\n \"name\": \"rows\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"palette\", \"key\": \"k\", \"fields\": [\"k\"],\n \"values\": [\"clr\", \"bg\", \"lbl\", \"desc\"], \"as\": [\"clr\", \"bg\", \"lbl\", \"desc\"],\n \"default\": \"#78909c\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.clr || '#78909c'\"},\n {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.bg || '#78909c18'\"},\n {\"type\": \"formula\", \"as\": \"lbl\", \"expr\": \"datum.lbl || datum.k\"},\n {\"type\": \"formula\", \"as\": \"desc\", \"expr\": \"datum.desc || 'Unrecognized key algorithm'\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 70 + 52\"},\n {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"},\n {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"},\n {\"type\": \"formula\", \"as\": \"bw\", \"expr\": \"width * 0.58 - 110\"}\n ]\n },\n {\n \"name\": \"mx\",\n \"source\": \"rows\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"KEY ALGORITHM\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"PUBLIC KEY TYPE — click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 64},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n\u003e0 ? '#161622' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 64},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 63\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.4\"},\n \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 40\"},\n \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.56\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\"},\n \"height\": {\"value\": 10}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.clr + '88'\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 50\"},\n \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "CERT OPS — Key Algorithm", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 30, + "i": "65669cd8-396b-410c-bc9b-ee3389ef8017", + "w": 16, + "x": 0, + "y": 39 + }, + "panelIndex": "65669cd8-396b-410c-bc9b-ee3389ef8017", + "title": "CERT OPS — Key Algorithm", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "4cb43ecb-be8e-5b80-8c8e-32e171de9e03", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_size\": {\"terms\": {\"field\": \"certificate.subject_public_key_info.bit_size\", \"size\": 15, \"order\": {\"_count\": \"desc\"}}},\n \"total\": {\"value_count\": {\"field\": \"id\"}}\n }}},\n \"format\": {\"property\": \"aggregations.by_size.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"sz\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"toString(datum.key) + '-bit'\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.key \u003c= 1024 ? '#ef5350' : datum.key \u003c= 2048 ? '#ffa726' : datum.key \u003c= 3072 ? '#448aff' : '#00c853'\"},\n {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.key \u003c= 1024 ? '#ef535018' : datum.key \u003c= 2048 ? '#ffa72618' : datum.key \u003c= 3072 ? '#448aff18' : '#00c85318'\"},\n {\"type\": \"formula\", \"as\": \"tier\",\"expr\": \"datum.key \u003c= 512 ? 'CRITICAL' : datum.key \u003c= 1024 ? 'WEAK' : datum.key \u003c= 2048 ? 'CLASSICAL' : datum.key \u003c= 3072 ? 'STRONG' : 'CNSA 2.0'\"},\n {\"type\": \"formula\", \"as\": \"desc\",\"expr\": \"datum.key \u003c= 512 ? 'Trivially breakable — remove immediately' : datum.key \u003c= 1024 ? 'Below NIST minimum — must be replaced' : datum.key === 2048 ? 'RSA-2048 / ECDSA-P256 — classical standard, quantum-vulnerable' : datum.key === 3072 ? 'RSA-3072 — transitional strength, quantum-vulnerable' : datum.key === 4096 ? 'RSA-4096 — strong classical, quantum-vulnerable' : datum.key === 256 ? 'ECDSA-P256 — modern elliptic curve' : datum.key === 384 ? 'ECDSA-P384 — strong elliptic curve (CNSA 1.0)' : 'Key size ' + datum.key\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 70 + 52\"}\n ]\n },\n {\n \"name\": \"tot\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"},\n {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"KEY SIZE DISTRIBUTION\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"BIT STRENGTH — click to filter · CNSA 2.0 requires RSA ≥3072 or ECDSA P-384\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 64},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 64},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 63\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"text\": {\"field\": \"k\"},\n \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 40\"},\n \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 7\"},\n \"width\": {\"value\": 64}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"field\": \"bg\"},\n \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58 + 32\"}, \"y\": {\"signal\": \"datum.y + 19\"},\n \"text\": {\"field\": \"tier\"},\n \"fill\": {\"field\": \"clr\"},\n \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 27\"},\n \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * 64 : 0\"},\n \"height\": {\"value\": 12}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.clr + '55'\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 50\"},\n \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "CERT OPS — Key Size Distribution", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 30, + "i": "3a8c4d30-8553-4034-91da-f7010ef7b182", + "w": 16, + "x": 16, + "y": 39 + }, + "panelIndex": "3a8c4d30-8553-4034-91da-f7010ef7b182", + "title": "CERT OPS — Key Size Distribution", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Application Report" + }, + "eventId": "5e8c06e1-fcf5-5aab-b7bc-c3cdc891baee", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_sig\": {\"terms\": {\"field\": \"certificate.signature_algorithm\", \"size\": 15, \"order\": {\"_count\": \"desc\"}}},\n \"total\": {\"value_count\": {\"field\": \"id\"}}\n }}},\n \"format\": {\"property\": \"aggregations.by_sig.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.key === 'MD5-RSA' ? '#ef5350' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef5350' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa726' : datum.key === 'N/A' || datum.key === '0' ? '#555555' : '#00c853'\"},\n {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.key === 'MD5-RSA' ? '#ef535018' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef535018' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff18' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa72618' : '#55555518'\"},\n {\"type\": \"formula\", \"as\": \"tier\",\"expr\": \"datum.key === 'MD5-RSA' ? 'BROKEN' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? 'LEGACY' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? 'MODERN' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? 'CLASSICAL' : datum.key === 'N/A' || datum.key === '0' ? 'UNKNOWN' : 'PQC READY'\"},\n {\"type\": \"formula\", \"as\": \"desc\",\"expr\": \"datum.key === 'MD5-RSA' ? 'MD5 collision attacks are trivial — critically broken' : datum.key === 'SHA1-RSA' ? 'SHA-1 deprecated — browsers reject, fails compliance' : datum.key === 'DSA-SHA1' ? 'DSA with SHA-1 — both deprecated, remove immediately' : datum.key === 'SHA256-RSA' ? 'RSA with SHA-256 — dominant classical standard' : datum.key === 'SHA384-RSA' ? 'RSA with SHA-384 — stronger hash, still quantum-vulnerable' : datum.key === 'SHA512-RSA' ? 'RSA with SHA-512 — strongest classical RSA variant' : datum.key === 'ECDSA-SHA256' ? 'ECDSA with SHA-256 — modern, efficient, quantum-vulnerable' : datum.key === 'ECDSA-SHA384' ? 'ECDSA with SHA-384 — CNSA 1.0 approved, quantum-vulnerable' : 'Signature algorithm'\"},\n {\"type\": \"filter\", \"expr\": \"datum.k !== 'N/A' \u0026\u0026 datum.k !== '0'\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 66 + 52\"}\n ]\n },\n {\n \"name\": \"tot\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"},\n {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"SIGNATURE ALGORITHM\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"HOW CERTIFICATES ARE SIGNED — click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 60},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 60},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 59\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"field\": \"k\"}, \"limit\": {\"signal\": \"width * 0.42\"},\n \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 38\"},\n \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.60\"}, \"y\": {\"signal\": \"datum.y + 6\"},\n \"width\": {\"value\": 68}, \"height\": {\"value\": 15}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"field\": \"bg\"},\n \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.60 + 34\"}, \"y\": {\"signal\": \"datum.y + 18\"},\n \"text\": {\"field\": \"tier\"},\n \"fill\": {\"field\": \"clr\"},\n \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 32\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 47\"},\n \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + }, + "title": "CERT OPS — Signature Algorithm", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 30, + "i": "3fa6122b-517f-47d6-b194-2fcea3de3332", + "w": 16, + "x": 32, + "y": 39 + }, + "panelIndex": "3fa6122b-517f-47d6-b194-2fcea3de3332", + "title": "CERT OPS — Signature Algorithm", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "Certificate lifetime buckets: automated (≤90d) through legacy (\u003e5yr) with key management system insight", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Cost Analysis" + }, + "eventId": "8de715c9-8769-51a8-8672-32a3af72a8c7", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "Certificate lifetime buckets: automated (≤90d) through legacy (\u003e5yr) with key management system insight", + "id": "", + "params": { + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.n \u003e 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"le90d\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();if(na\u003c=System.currentTimeMillis())return false;long d=(na-nb)/86400000L;return d\u003e=0\u0026\u0026d\u003c=90;\"}}}}, \"le1yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e90\u0026\u0026d\u003c=365;\"}}}}, \"le825d\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e365\u0026\u0026d\u003c=825;\"}}}}, \"le5yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e825\u0026\u0026d\u003c=1825;\"}}}}, \"gt5yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e1825;\"}}}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"le90d\", \"expr\": \"datum.le90d ? datum.le90d.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le1yr\", \"expr\": \"datum.le1yr ? datum.le1yr.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le825d\", \"expr\": \"datum.le825d ? datum.le825d.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le5yr\", \"expr\": \"datum.le5yr ? datum.le5yr.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"gt5yr\", \"expr\": \"datum.gt5yr ? datum.gt5yr.doc_count : 0\"}]}, {\"name\": \"tot\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"certificate.not_after\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"le90d\", \"lbl\": \"Automated \\u226490 days\", \"mgmt\": \"KEY MGT SYSTEM\", \"desc\": \"Almost certainly managed by ACME / Let's Encrypt / cert-manager \\u2014 short lifetime is a signature of automated issuance\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0, \"field\": \"le90d\", \"filt\": {\"range\": {\"cert_total_days\": {\"gte\": 0, \"lte\": 90}}}}, {\"k\": \"le1yr\", \"lbl\": \"Short-lived \\u22641 year\", \"mgmt\": \"LIKELY MANAGED\", \"desc\": \"Annual lifetime pattern \\u2014 may be automated renewal or disciplined manual rotation by an ops team\", \"clr\": \"#4db6ac\", \"bg\": \"#4db6ac18\", \"ord\": 1, \"field\": \"le1yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 90, \"lte\": 365}}}}, {\"k\": \"le825d\", \"lbl\": \"Modern \\u2264825 days\", \"mgmt\": \"CA ISSUED\", \"desc\": \"Within Apple / browser maximum trust limit (825 days) \\u2014 actively issued by a real CA, rotation expected\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2, \"field\": \"le825d\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 365, \"lte\": 825}}}}, {\"k\": \"le5yr\", \"lbl\": \"Long-lived \\u22645 years\", \"mgmt\": \"MANUAL\", \"desc\": \"826\\u20131825 day lifetime \\u2014 manually managed, no automated rotation, quantum risk grows over the certificate's life\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 3, \"field\": \"le5yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 825, \"lte\": 1825}}}}, {\"k\": \"gt5yr\", \"lbl\": \"Legacy \u003e 5 years\", \"mgmt\": \"LEGACY / MANUAL\", \"desc\": \"5+ year validity \\u2014 definitely manually issued; each year of remaining life increases the window for harvest-now-decrypt-later attacks\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 4, \"field\": \"gt5yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 1825}}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"length(data('raw'))\u003e0 ? (datum.field==='le90d' ? data('raw')[0].le90d : datum.field==='le1yr' ? data('raw')[0].le1yr : datum.field==='le825d' ? data('raw')[0].le825d : datum.field==='le5yr' ? data('raw')[0].le5yr : data('raw')[0].gt5yr) : 0\"}, {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 52\"}]}, {\"name\": \"mx\", \"source\": \"rows\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE LONGEVITY\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"CERTIFICATE LIFETIME \\u2014 short = automated key management \\u00b7 long = manual / legacy\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n\u003e0 ? '#161616' : '#121212'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.52\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 42\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.74\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76 + 41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"field\": \"mgmt\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76\"}, \"y\": {\"signal\": \"datum.y + 28\"}, \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * 82 : 0\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.clr + '44'\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n \u003e 0 ? (datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.n\u003e0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 52\"}, \"text\": {\"signal\": \"datum.tot \u003e 0 \u0026\u0026 datum.n \u003e 0 ? format(datum.pct * 100, '.1f') + '%' : ''\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}]}" + }, + "title": "Certificate Longevity", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 22, + "i": "d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2", + "w": 24, + "x": 0, + "y": 69 + }, + "panelIndex": "d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2", + "title": "Certificate Longevity", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "File system disk scan vs live TLS port capture — how each certificate was discovered", + "enhancements": { + "dynamicActions": { + "events": [ + { + "action": { + "config": { + "openInNewTab": false, + "useCurrentDateRange": true, + "useCurrentFilters": true + }, + "factoryId": "DASHBOARD_TO_DASHBOARD_DRILLDOWN", + "name": "Open Inventory" + }, + "eventId": "d14a762a-33a5-545d-9c69-b36b1279da31", + "triggers": [ + "FILTER_TRIGGER" + ] + } + ] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "File system disk scan vs live TLS port capture — how each certificate was discovered", + "id": "", + "params": { + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"row_bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"row_bg\"}, \"update\": \"datum.n \u003e 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"d_fs\", \"url\": {\"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"query\": {\"term\": {\"tychon.type\": \"filesystem\"}}, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value || 0\"}]}, {\"name\": \"d_port\", \"url\": {\"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"query\": {\"bool\": {\"must\": [{\"exists\": {\"field\": \"x509.subject.common_name\"}}, {\"term\": {\"tychon.type\": \"cipher\"}}]}}, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"tychon.type\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value || 0\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"fs\", \"ord\": 0, \"lbl\": \"File System\", \"badge\": \"DISK\", \"sub\": \"Certificates read from disk \\u2014 PEM/DER files, keystores, application bundles\", \"desc\": \"Found by crawling the local filesystem. Source path is known. These certs may not be actively serving traffic \\u2014 they could be backups, bundled CA roots, or application trust stores.\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"icon\": \"\\u2399\", \"filt\": {\"match_phrase\": {\"tychon.type\": \"filesystem\"}}}, {\"k\": \"port\", \"ord\": 1, \"lbl\": \"Port / Network\", \"badge\": \"NETWORK\", \"sub\": \"Certificates captured live from TLS handshakes on open network ports\", \"desc\": \"Captured during an active TLS scan. These certs are definitely in use serving live traffic. Quantum readiness score and cipher suite are also available for these entries.\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"icon\": \"\\u26a1\", \"filt\": {\"match_phrase\": {\"tychon.type\": \"cipher\"}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.k === 'fs' ? (length(data('d_fs'))\u003e0 ? data('d_fs')[0].n : 0) : (length(data('d_port'))\u003e0 ? data('d_port')[0].n : 0)\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 134 + 52\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SOURCE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"HOW CERTIFICATES WERE DISCOVERED \\u2014 file scan vs live TLS capture\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"row_bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 128}, \"fill\": {\"signal\": \"datum.k === sel ? '#1c1c2e' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 128}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 127\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 10\"}, \"width\": {\"value\": 56}, \"height\": {\"value\": 18}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 42}, \"y\": {\"signal\": \"datum.y + 23\"}, \"text\": {\"field\": \"badge\"}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#333333'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 78}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"field\": \"lbl\"}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"field\": \"sub\"}, \"limit\": {\"signal\": \"width * 0.82\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 64\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.64\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 70\"}, \"text\": {\"signal\": \"datum.n \u003e 0 ? (datum.n \u003e= 1000 ? format(datum.n, '.3~s') : format(datum.n, ',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#333333'\"}, \"fontSize\": {\"value\": 32}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 88\"}, \"text\": {\"value\": \"certificates\"}, \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}]}" + }, + "title": "Certificate Source Type", + "type": "vega", + "uiState": {} + } + }, + "gridData": { + "h": 22, + "i": "ce89de35-28cf-4f8c-82a1-215539f77bad", + "w": 24, + "x": 24, + "y": 69 + }, + "panelIndex": "ce89de35-28cf-4f8c-82a1-215539f77bad", + "title": "Certificate Source Type", + "type": "visualization" + }, + { + "embeddableConfig": { + "description": "Per-cert records sorted by earliest expiry. FILE=disk scan, PORT=live TLS. Paginated server-side — scales to any size.", + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "grid": {} + }, + "gridData": { + "h": 38, + "i": "3a5ae8e6-acd0-40f9-a6fb-488f44a55e32", + "w": 48, + "x": 0, + "y": 91 + }, + "panelIndex": "3a5ae8e6-acd0-40f9-a6fb-488f44a55e32", + "panelRefName": "panel_3a5ae8e6-acd0-40f9-a6fb-488f44a55e32", + "title": "Certificate Inventory Detail", + "type": "search" + } + ], + "timeRestore": false, + "title": "[TYCHON Quantum Command] Certificate Operations Dashboard", + "version": 3 }, - "description": "Operational view of all discovered certificates — quantum readiness, hygiene, key algorithms, and issuer coverage", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"kuery\"}}" - }, - "optionsJSON": "{\"useMargins\":false,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":true,\"hidePanelTitles\":true}", - "panelsJSON": "[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":3,\"i\":\"tychon-quantum-command-nav\"},\"panelIndex\":\"tychon-quantum-command-nav\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"[Inventory](/app/dashboards#/view/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory) | [Application Report](/app/dashboards#/view/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report) | [Application Detail](/app/dashboards#/view/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail) | Certificate Report | [Application Connections Topology](/app/dashboards#/view/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology) | [Cost Analysis](/app/dashboards#/view/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis)\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"hidePanelTitles\":true,\"enhancements\":{}},\"title\":\"\"},{\"type\":\"visualization\",\"title\":\"CERT OPS — Inventory Header\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Inventory Header\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"total\\\", \\\"update\\\": \\\"length(data('d_total'))>0 ? data('d_total')[0].n : 0\\\"}, {\\\"name\\\": \\\"expired\\\", \\\"update\\\": \\\"length(data('d_expired'))>0 ? data('d_expired')[0].n : 0\\\"}, {\\\"name\\\": \\\"exp30\\\", \\\"update\\\": \\\"length(data('d_exp30'))>0 ? data('d_exp30')[0].n : 0\\\"}, {\\\"name\\\": \\\"self\\\", \\\"update\\\": \\\"length(data('d_self'))>0 ? data('d_self')[0].n : 0\\\"}, {\\\"name\\\": \\\"legacy\\\", \\\"update\\\": \\\"length(data('d_legacy'))>0 ? data('d_legacy')[0].n : 0\\\"}, {\\\"name\\\": \\\"pqcvuln\\\", \\\"update\\\": \\\"length(data('d_pqcvuln'))>0 ? data('d_pqcvuln')[0].n : 0\\\"}, {\\\"name\\\": \\\"bw\\\", \\\"update\\\": \\\"floor((width - 10) / 6) - 4\\\"}, {\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? null : datum.k) : sel\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_total\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"d_expired\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_exp30\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_self\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_legacy\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_pqcvuln\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tiles\\\", \\\"values\\\": [{\\\"k\\\": \\\"TOTAL\\\", \\\"ord\\\": 0, \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"sig\\\": \\\"total\\\", \\\"filt\\\": null}, {\\\"k\\\": \\\"EXPIRED\\\", \\\"ord\\\": 1, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"ord\\\": 2, \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"sig\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"ord\\\": 3, \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"sig\\\": \\\"self\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"LEGACY\\\", \\\"ord\\\": 4, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"legacy\\\", \\\"filt\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}, {\\\"k\\\": \\\"PQC VULN\\\", \\\"ord\\\": 5, \\\"clr\\\": \\\"#ab47bc\\\", \\\"bg\\\": \\\"#ab47bc18\\\", \\\"sig\\\": \\\"pqcvuln\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"x\\\", \\\"expr\\\": \\\"datum.ord * (bw + 4) + 8\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"val\\\", \\\"expr\\\": \\\"datum.sig === 'total' ? total : datum.sig === 'expired' ? expired : datum.sig === 'exp30' ? exp30 : datum.sig === 'self' ? self : datum.sig === 'legacy' ? legacy : pqcvuln\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE INVENTORY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL OVERVIEW \\\\u2014 click a tile to filter the dashboard\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"tile\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"field\\\": \\\"x\\\"}, \\\"y\\\": {\\\"value\\\": 52}, \\\"width\\\": {\\\"signal\\\": \\\"bw\\\"}, \\\"height\\\": {\\\"value\\\": 72}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.bg : '#161616'\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 && datum.filt ? '#2a2a3a' : '#222222')\\\"}, \\\"strokeWidth\\\": {\\\"signal\\\": \\\"datum.k === sel ? 2 : 1\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 88}, \\\"text\\\": {\\\"signal\\\": \\\"datum.val >= 1000 ? format(datum.val,'.3~s') : format(datum.val,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 ? datum.clr : '#3a3a3a')\\\"}, \\\"fontSize\\\": {\\\"value\\\": 22}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 108}, \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : '#666666'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"74b385d6-da5a-438e-a0af-f1a77dab28db\",\"gridData\":{\"i\":\"74b385d6-da5a-438e-a0af-f1a77dab28db\",\"y\":2,\"x\":0,\"w\":48,\"h\":8}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Quantum Tier\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"f676853f-014e-5857-89ba-97b22fb271af\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Quantum Tier\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 10}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tc\\\", \\\"source\\\": \\\"raw\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"]}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"tc\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature \\\\u2014 quantum-resistant, CNSA 2.0 approved\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0}, {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve \\\\u2014 quantum-vulnerable via Shor's algorithm, must be replaced pre-2035\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1}, {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA \\\\u2014 quantum-vulnerable via Shor's algorithm, harvest-now-decrypt-later risk today\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}, {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"SHA-1/MD5 hash \\\\u2014 classically broken and quantum-vulnerable, replace immediately\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#b71c1c\\\", \\\"bg\\\": \\\"#b71c1c22\\\", \\\"ord\\\": 3}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM \\\\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 55}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.5\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"}, \\\"height\\\": {\\\"value\\\": 6}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"187d7c49-96d6-43fe-a3d7-ee51f605e0f5\",\"gridData\":{\"i\":\"187d7c49-96d6-43fe-a3d7-ee51f605e0f5\",\"y\":10,\"x\":0,\"w\":16,\"h\":29}},{\"type\":\"visualization\",\"title\":\"Certificate Hygiene\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"c9ef7c09-bbcf-57c7-bcbc-d3fae0140da2\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Certificate Hygiene\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"expired\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, \\\"exp30\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, \\\"exp90\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, \\\"selfsign\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, \\\"weakkey\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}, \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"expired\\\", \\\"expr\\\": \\\"datum.expired ? datum.expired.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp30\\\", \\\"expr\\\": \\\"datum.exp30 ? datum.exp30.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp90\\\", \\\"expr\\\": \\\"datum.exp90 ? datum.exp90.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"selfsign\\\", \\\"expr\\\": \\\"datum.selfsign ? datum.selfsign.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"weakkey\\\", \\\"expr\\\": \\\"datum.weakkey ? datum.weakkey.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total\\\", \\\"expr\\\": \\\"datum.total ? datum.total.value : 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"EXPIRED\\\", \\\"lbl\\\": \\\"Expired\\\", \\\"desc\\\": \\\"certificate.not_after < now \\\\u2014 no longer trusted by any client\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"lbl\\\": \\\"Expiring in 30 days\\\", \\\"desc\\\": \\\"certificate.not_after within 30 days \\\\u2014 immediate renewal required\\\", \\\"sev\\\": \\\"high\\\", \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"EXP 90D\\\", \\\"lbl\\\": \\\"Expiring in 90 days\\\", \\\"desc\\\": \\\"certificate.not_after within 90 days \\\\u2014 plan renewal now\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"exp90\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"lbl\\\": \\\"Self-Signed\\\", \\\"desc\\\": \\\"certificate.is_self_signed = true \\\\u2014 no CA trust chain, browser errors\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"selfsign\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"WEAK KEY\\\", \\\"lbl\\\": \\\"Weak Key \\\\u22641024-bit\\\", \\\"desc\\\": \\\"RSA/DSA key \\\\u22641024 bits \\\\u2014 computationally breakable, must be replaced\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"weakkey\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"raw\\\", \\\"key\\\": \\\"total\\\", \\\"fields\\\": [\\\"ord\\\"], \\\"values\\\": [\\\"expired\\\", \\\"exp30\\\", \\\"exp90\\\", \\\"selfsign\\\", \\\"weakkey\\\", \\\"total\\\"], \\\"as\\\": [\\\"v_expired\\\", \\\"v_exp30\\\", \\\"v_exp90\\\", \\\"v_selfsign\\\", \\\"v_weakkey\\\", \\\"v_total\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.field==='expired' ? (length(data('raw'))>0?data('raw')[0].expired:0) : datum.field==='exp30' ? (length(data('raw'))>0?data('raw')[0].exp30:0) : datum.field==='exp90' ? (length(data('raw'))>0?data('raw')[0].exp90:0) : datum.field==='selfsign' ? (length(data('raw'))>0?data('raw')[0].selfsign:0) : (length(data('raw'))>0?data('raw')[0].weakkey:0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? data('raw')[0].total : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 68 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE HYGIENE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL ISSUES \\\\u2014 expiry \\\\u00b7 trust \\\\u00b7 key strength\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? datum.bg : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 61\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sev\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 29\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 14}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#333333' : '#222222'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 ? format(datum.pct * 100, '.1f') + '%' : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"48d7d98f-27df-4c04-a736-8e772da0b028\",\"gridData\":{\"i\":\"48d7d98f-27df-4c04-a736-8e772da0b028\",\"y\":10,\"x\":16,\"w\":16,\"h\":29}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Top Issuing CAs\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"5a19f6d5-01ea-5a0d-9469-870400433156\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Top Issuing CAs\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.issuer_organization': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.issuer_organization': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_issuer\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.issuer_organization\\\", \\\"size\\\": 10, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_issuer.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 52 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.rnk === 1 ? '#448aff' : datum.rnk === 2 ? '#4db6ac' : datum.rnk <= 5 ? '#546e7a' : '#37474f'\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"TOP ISSUING CAs\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE AUTHORITY — who issued your certificates · click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 30}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.rnk, 'd') + '.'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.62\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.62) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 5}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '66'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 45\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#888888'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"df2ef032-250b-40c9-93de-3f6211bddac5\",\"gridData\":{\"i\":\"df2ef032-250b-40c9-93de-3f6211bddac5\",\"y\":10,\"x\":32,\"w\":16,\"h\":29}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Key Algorithm\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"195b2262-1d5d-50e1-86d2-f404cd493030\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Key Algorithm\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_algo\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.algorithm\\\", \\\"size\\\": 10}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_algo.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"palette\\\",\\n \\\"values\\\": [\\n {\\\"k\\\": \\\"RSA\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"lbl\\\": \\\"RSA\\\", \\\"desc\\\": \\\"Rivest–Shamir–Adleman — quantum-vulnerable via Shor's algorithm\\\"},\\n {\\\"k\\\": \\\"ECDSA\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"lbl\\\": \\\"ECDSA\\\", \\\"desc\\\": \\\"Elliptic curve — quantum-vulnerable, efficient on classical hardware\\\"},\\n {\\\"k\\\": \\\"DSA\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"lbl\\\": \\\"DSA\\\", \\\"desc\\\": \\\"Digital Signature Algorithm — deprecated, should not be in new certs\\\"},\\n {\\\"k\\\": \\\"unknown_der\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown DER\\\", \\\"desc\\\": \\\"DER-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"unknown_pem\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown PEM\\\", \\\"desc\\\": \\\"PEM-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"ML-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"ML-DSA\\\", \\\"desc\\\": \\\"Lattice-based PQC signature — CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"SLH-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"SLH-DSA\\\", \\\"desc\\\": \\\"Hash-based PQC signature — CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"FN-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"FN-DSA\\\", \\\"desc\\\": \\\"Falcon lattice signature — CNSA 2.0 quantum-resistant\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"palette\\\", \\\"key\\\": \\\"k\\\", \\\"fields\\\": [\\\"k\\\"],\\n \\\"values\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"], \\\"as\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"],\\n \\\"default\\\": \\\"#78909c\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.clr || '#78909c'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.bg || '#78909c18'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"lbl\\\", \\\"expr\\\": \\\"datum.lbl || datum.k\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\", \\\"expr\\\": \\\"datum.desc || 'Unrecognized key algorithm'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bw\\\", \\\"expr\\\": \\\"width * 0.58 - 110\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"rows\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"PUBLIC KEY TYPE — click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161622' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.4\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 10}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '88'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"65669cd8-396b-410c-bc9b-ee3389ef8017\",\"gridData\":{\"i\":\"65669cd8-396b-410c-bc9b-ee3389ef8017\",\"y\":39,\"x\":0,\"w\":16,\"h\":30}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Key Size Distribution\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"4cb43ecb-be8e-5b80-8c8e-32e171de9e03\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Key Size Distribution\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_size\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.bit_size\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_size.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sz\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"toString(datum.key) + '-bit'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef5350' : datum.key <= 2048 ? '#ffa726' : datum.key <= 3072 ? '#448aff' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef535018' : datum.key <= 2048 ? '#ffa72618' : datum.key <= 3072 ? '#448aff18' : '#00c85318'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'CRITICAL' : datum.key <= 1024 ? 'WEAK' : datum.key <= 2048 ? 'CLASSICAL' : datum.key <= 3072 ? 'STRONG' : 'CNSA 2.0'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'Trivially breakable — remove immediately' : datum.key <= 1024 ? 'Below NIST minimum — must be replaced' : datum.key === 2048 ? 'RSA-2048 / ECDSA-P256 — classical standard, quantum-vulnerable' : datum.key === 3072 ? 'RSA-3072 — transitional strength, quantum-vulnerable' : datum.key === 4096 ? 'RSA-4096 — strong classical, quantum-vulnerable' : datum.key === 256 ? 'ECDSA-P256 — modern elliptic curve' : datum.key === 384 ? 'ECDSA-P384 — strong elliptic curve (CNSA 1.0)' : 'Key size ' + datum.key\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY SIZE DISTRIBUTION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"BIT STRENGTH — click to filter · CNSA 2.0 requires RSA ≥3072 or ECDSA P-384\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"},\\n \\\"width\\\": {\\\"value\\\": 64}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58 + 32\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 27\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 64 : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 12}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3a8c4d30-8553-4034-91da-f7010ef7b182\",\"gridData\":{\"i\":\"3a8c4d30-8553-4034-91da-f7010ef7b182\",\"y\":39,\"x\":16,\"w\":16,\"h\":30}},{\"type\":\"visualization\",\"title\":\"CERT OPS — Signature Algorithm\",\"embeddableConfig\":{\"description\":\"\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"5e8c06e1-fcf5-5aab-b7bc-c3cdc891baee\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Application Report\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"CERT OPS — Signature Algorithm\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_sig\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.signature_algorithm\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_sig.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef5350' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef5350' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa726' : datum.key === 'N/A' || datum.key === '0' ? '#555555' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef535018' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef535018' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff18' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa72618' : '#55555518'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'BROKEN' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? 'LEGACY' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? 'MODERN' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? 'CLASSICAL' : datum.key === 'N/A' || datum.key === '0' ? 'UNKNOWN' : 'PQC READY'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'MD5 collision attacks are trivial — critically broken' : datum.key === 'SHA1-RSA' ? 'SHA-1 deprecated — browsers reject, fails compliance' : datum.key === 'DSA-SHA1' ? 'DSA with SHA-1 — both deprecated, remove immediately' : datum.key === 'SHA256-RSA' ? 'RSA with SHA-256 — dominant classical standard' : datum.key === 'SHA384-RSA' ? 'RSA with SHA-384 — stronger hash, still quantum-vulnerable' : datum.key === 'SHA512-RSA' ? 'RSA with SHA-512 — strongest classical RSA variant' : datum.key === 'ECDSA-SHA256' ? 'ECDSA with SHA-256 — modern, efficient, quantum-vulnerable' : datum.key === 'ECDSA-SHA384' ? 'ECDSA with SHA-384 — CNSA 1.0 approved, quantum-vulnerable' : 'Signature algorithm'\\\"},\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.k !== 'N/A' && datum.k !== '0'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 66 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES ARE SIGNED — click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 59\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.42\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 6\\\"},\\n \\\"width\\\": {\\\"value\\\": 68}, \\\"height\\\": {\\\"value\\\": 15}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60 + 34\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 18\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 32\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 47\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}}},\"panelIndex\":\"3fa6122b-517f-47d6-b194-2fcea3de3332\",\"gridData\":{\"i\":\"3fa6122b-517f-47d6-b194-2fcea3de3332\",\"y\":39,\"x\":32,\"w\":16,\"h\":30}},{\"type\":\"visualization\",\"title\":\"Certificate Longevity\",\"embeddableConfig\":{\"description\":\"Certificate lifetime buckets: automated (≤90d) through legacy (>5yr) with key management system insight\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"8de715c9-8769-51a8-8672-32a3af72a8c7\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Cost Analysis\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Certificate Longevity\",\"description\":\"Certificate lifetime buckets: automated (≤90d) through legacy (>5yr) with key management system insight\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"le90d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();if(na<=System.currentTimeMillis())return false;long d=(na-nb)/86400000L;return d>=0&&d<=90;\\\"}}}}, \\\"le1yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>90&&d<=365;\\\"}}}}, \\\"le825d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>365&&d<=825;\\\"}}}}, \\\"le5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>825&&d<=1825;\\\"}}}}, \\\"gt5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>1825;\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le90d\\\", \\\"expr\\\": \\\"datum.le90d ? datum.le90d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le1yr\\\", \\\"expr\\\": \\\"datum.le1yr ? datum.le1yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le825d\\\", \\\"expr\\\": \\\"datum.le825d ? datum.le825d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le5yr\\\", \\\"expr\\\": \\\"datum.le5yr ? datum.le5yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"gt5yr\\\", \\\"expr\\\": \\\"datum.gt5yr ? datum.gt5yr.doc_count : 0\\\"}]}, {\\\"name\\\": \\\"tot\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"le90d\\\", \\\"lbl\\\": \\\"Automated \\\\u226490 days\\\", \\\"mgmt\\\": \\\"KEY MGT SYSTEM\\\", \\\"desc\\\": \\\"Almost certainly managed by ACME / Let's Encrypt / cert-manager \\\\u2014 short lifetime is a signature of automated issuance\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"le90d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gte\\\": 0, \\\"lte\\\": 90}}}}, {\\\"k\\\": \\\"le1yr\\\", \\\"lbl\\\": \\\"Short-lived \\\\u22641 year\\\", \\\"mgmt\\\": \\\"LIKELY MANAGED\\\", \\\"desc\\\": \\\"Annual lifetime pattern \\\\u2014 may be automated renewal or disciplined manual rotation by an ops team\\\", \\\"clr\\\": \\\"#4db6ac\\\", \\\"bg\\\": \\\"#4db6ac18\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"le1yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 90, \\\"lte\\\": 365}}}}, {\\\"k\\\": \\\"le825d\\\", \\\"lbl\\\": \\\"Modern \\\\u2264825 days\\\", \\\"mgmt\\\": \\\"CA ISSUED\\\", \\\"desc\\\": \\\"Within Apple / browser maximum trust limit (825 days) \\\\u2014 actively issued by a real CA, rotation expected\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"le825d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 365, \\\"lte\\\": 825}}}}, {\\\"k\\\": \\\"le5yr\\\", \\\"lbl\\\": \\\"Long-lived \\\\u22645 years\\\", \\\"mgmt\\\": \\\"MANUAL\\\", \\\"desc\\\": \\\"826\\\\u20131825 day lifetime \\\\u2014 manually managed, no automated rotation, quantum risk grows over the certificate's life\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"le5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 825, \\\"lte\\\": 1825}}}}, {\\\"k\\\": \\\"gt5yr\\\", \\\"lbl\\\": \\\"Legacy > 5 years\\\", \\\"mgmt\\\": \\\"LEGACY / MANUAL\\\", \\\"desc\\\": \\\"5+ year validity \\\\u2014 definitely manually issued; each year of remaining life increases the window for harvest-now-decrypt-later attacks\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"gt5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 1825}}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? (datum.field==='le90d' ? data('raw')[0].le90d : datum.field==='le1yr' ? data('raw')[0].le1yr : datum.field==='le825d' ? data('raw')[0].le825d : datum.field==='le5yr' ? data('raw')[0].le5yr : data('raw')[0].gt5yr) : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 52\\\"}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"rows\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LONGEVITY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LIFETIME \\\\u2014 short = automated key management \\\\u00b7 long = manual / legacy\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161616' : '#121212'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.52\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 42\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.74\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76 + 41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"mgmt\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 28\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 82 : 0\\\"}, \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '44'\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 52\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 && datum.n > 0 ? format(datum.pct * 100, '.1f') + '%' : ''\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2\",\"gridData\":{\"i\":\"d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2\",\"y\":69,\"x\":0,\"w\":24,\"h\":22}},{\"type\":\"visualization\",\"title\":\"Certificate Source Type\",\"embeddableConfig\":{\"description\":\"File system disk scan vs live TLS port capture — how each certificate was discovered\",\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"d14a762a-33a5-545d-9c69-b36b1279da31\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Open Inventory\",\"config\":{\"openInNewTab\":false,\"useCurrentDateRange\":true,\"useCurrentFilters\":true}}}]}},\"savedVis\":{\"id\":\"\",\"title\":\"Certificate Source Type\",\"description\":\"File system disk scan vs live TLS port capture — how each certificate was discovered\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_fs\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"term\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"d_port\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-inventory*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"bool\\\": {\\\"must\\\": [{\\\"exists\\\": {\\\"field\\\": \\\"x509.subject.common_name\\\"}}, {\\\"term\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}]}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"fs\\\", \\\"ord\\\": 0, \\\"lbl\\\": \\\"File System\\\", \\\"badge\\\": \\\"DISK\\\", \\\"sub\\\": \\\"Certificates read from disk \\\\u2014 PEM/DER files, keystores, application bundles\\\", \\\"desc\\\": \\\"Found by crawling the local filesystem. Source path is known. These certs may not be actively serving traffic \\\\u2014 they could be backups, bundled CA roots, or application trust stores.\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"icon\\\": \\\"\\\\u2399\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}}, {\\\"k\\\": \\\"port\\\", \\\"ord\\\": 1, \\\"lbl\\\": \\\"Port / Network\\\", \\\"badge\\\": \\\"NETWORK\\\", \\\"sub\\\": \\\"Certificates captured live from TLS handshakes on open network ports\\\", \\\"desc\\\": \\\"Captured during an active TLS scan. These certs are definitely in use serving live traffic. Quantum readiness score and cipher suite are also available for these entries.\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"icon\\\": \\\"\\\\u26a1\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.k === 'fs' ? (length(data('d_fs'))>0 ? data('d_fs')[0].n : 0) : (length(data('d_port'))>0 ? data('d_port')[0].n : 0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 134 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SOURCE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES WERE DISCOVERED \\\\u2014 file scan vs live TLS capture\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"row_bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? '#1c1c2e' : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 127\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 10\\\"}, \\\"width\\\": {\\\"value\\\": 56}, \\\"height\\\": {\\\"value\\\": 18}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 42}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 23\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 78}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sub\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.82\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 64\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.64\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 70\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n, '.3~s') : format(datum.n, ',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 32}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 88\\\"}, \\\"text\\\": {\\\"value\\\": \\\"certificates\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}}}},\"panelIndex\":\"ce89de35-28cf-4f8c-82a1-215539f77bad\",\"gridData\":{\"i\":\"ce89de35-28cf-4f8c-82a1-215539f77bad\",\"y\":69,\"x\":24,\"w\":24,\"h\":22}},{\"type\":\"search\",\"title\":\"Certificate Inventory Detail\",\"panelIndex\":\"3a5ae8e6-acd0-40f9-a6fb-488f44a55e32\",\"gridData\":{\"i\":\"3a5ae8e6-acd0-40f9-a6fb-488f44a55e32\",\"y\":91,\"x\":0,\"w\":48,\"h\":38},\"embeddableConfig\":{\"description\":\"Per-cert records sorted by earliest expiry. FILE=disk scan, PORT=live TLS. Paginated server-side — scales to any size.\",\"enhancements\":{\"dynamicActions\":{\"events\":[]}},\"grid\":{}},\"panelRefName\":\"panel_3a5ae8e6-acd0-40f9-a6fb-488f44a55e32\"}]", - "timeRestore": false, - "title": "[TYCHON Quantum Command] Certificate Operations Dashboard", - "version": 3 - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T17:19:39.902Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", - "managed": false, - "references": [ - { - "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", - "name": "187d7c49-96d6-43fe-a3d7-ee51f605e0f5:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:f676853f-014e-5857-89ba-97b22fb271af:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "3a8c4d30-8553-4034-91da-f7010ef7b182:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:4cb43ecb-be8e-5b80-8c8e-32e171de9e03:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "3fa6122b-517f-47d6-b194-2fcea3de3332:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:5e8c06e1-fcf5-5aab-b7bc-c3cdc891baee:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", - "name": "48d7d98f-27df-4c04-a736-8e772da0b028:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:c9ef7c09-bbcf-57c7-bcbc-d3fae0140da2:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", - "name": "65669cd8-396b-410c-bc9b-ee3389ef8017:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:195b2262-1d5d-50e1-86d2-f404cd493030:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", - "name": "ce89de35-28cf-4f8c-82a1-215539f77bad:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d14a762a-33a5-545d-9c69-b36b1279da31:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", - "name": "d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:8de715c9-8769-51a8-8672-32a3af72a8c7:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", - "name": "df2ef032-250b-40c9-93de-3f6211bddac5:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:5a19f6d5-01ea-5a0d-9469-870400433156:dashboardId", - "type": "dashboard" - }, - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-dacb217e-57b4-4296-8545-cbf6b5739344", - "type": "tag" - }, - { - "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", - "name": "tag-ref-e9b715ba-5f19-4f99-b837-2c1a24143212", - "type": "tag" - }, - { - "id": "tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail", - "name": "3a5ae8e6-acd0-40f9-a6fb-488f44a55e32:panel_3a5ae8e6-acd0-40f9-a6fb-488f44a55e32", - "type": "search" - } - ], - "type": "dashboard", - "typeMigrationVersion": "10.2.0", - "updated_at": "2026-06-11T17:19:39.902Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY2MTcsMzBd" -} + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", + "references": [ + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "187d7c49-96d6-43fe-a3d7-ee51f605e0f5:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:f676853f-014e-5857-89ba-97b22fb271af:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "3a8c4d30-8553-4034-91da-f7010ef7b182:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:4cb43ecb-be8e-5b80-8c8e-32e171de9e03:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "3fa6122b-517f-47d6-b194-2fcea3de3332:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:5e8c06e1-fcf5-5aab-b7bc-c3cdc891baee:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "48d7d98f-27df-4c04-a736-8e772da0b028:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:c9ef7c09-bbcf-57c7-bcbc-d3fae0140da2:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", + "name": "65669cd8-396b-410c-bc9b-ee3389ef8017:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:195b2262-1d5d-50e1-86d2-f404cd493030:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "ce89de35-28cf-4f8c-82a1-215539f77bad:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:d14a762a-33a5-545d-9c69-b36b1279da31:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", + "name": "d2ae0bd5-2c42-4bb1-a4e7-a80b31524be2:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:8de715c9-8769-51a8-8672-32a3af72a8c7:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", + "name": "df2ef032-250b-40c9-93de-3f6211bddac5:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:5a19f6d5-01ea-5a0d-9469-870400433156:dashboardId", + "type": "dashboard" + }, + { + "id": "tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail", + "name": "3a5ae8e6-acd0-40f9-a6fb-488f44a55e32:panel_3a5ae8e6-acd0-40f9-a6fb-488f44a55e32", + "type": "search" + }, + { + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "name": "tag-ref-tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "type": "tag" + }, + { + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "name": "tag-ref-tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "type": "tag" + }, + { + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "name": "tag-ref-tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "type": "tag" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.3.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json index 066caa03961..d74a6daba59 100644 --- a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json +++ b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json @@ -1,81 +1,172 @@ { - "attributes": { - "columns": [ - "observer.hostname", - "omb.vulnerability_status", - "omb.module_name", - "omb.crqc_vulnerable_algos", - "omb.pqc_algos", - "omb.symmetric_algos", - "omb.software_package_name", - "omb.software_package_version", - "omb.vendor", - "omb.operating_system", - "omb.additional_notes", - "omb.kex_protocols", - "tls.supported_ciphers", - "tls.preferred_key_exchange", - "omb.kex_secondary", - "omb.kem_algorithms", - "omb.kem_parameters", - "omb.dsa_algorithms", - "omb.dsa_parameters", - "omb.block_cipher_key_lengths", - "omb.block_cipher_modes", - "crypto.hash_algorithms", - "omb.hash_algorithm_parameters", - "crypto.mac_algorithms", - "omb.mac_algorithm_parameters", - "omb.other_crypto_details", - "omb.certifications", - "@timestamp" - ], - "description": "OMB Report for the Department of Defense", - "grid": { - "columns": { - "omb.additional_notes": { - "width": 241 - } - } - }, - "hideChart": false, - "isTextBasedQuery": false, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"exists\",\"key\":\"omb.vulnerability_status\",\"value\":\"exists\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"exists\":{\"field\":\"omb.vulnerability_status\"}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" - }, - "refreshInterval": { - "pause": true, - "value": 60000 + "attributes": { + "columns": [ + "observer.hostname", + "omb.vulnerability_status", + "omb.module_name", + "omb.crqc_vulnerable_algos", + "omb.pqc_algos", + "omb.symmetric_algos", + "omb.software_package_name", + "omb.software_package_version", + "omb.vendor", + "omb.operating_system", + "omb.additional_notes", + "omb.kex_protocols", + "tls.supported_ciphers", + "tls.preferred_key_exchange", + "omb.kex_secondary", + "omb.kem_algorithms", + "omb.kem_parameters", + "omb.dsa_algorithms", + "omb.dsa_parameters", + "omb.block_cipher_key_lengths", + "omb.block_cipher_modes", + "crypto.hash_algorithms", + "omb.hash_algorithm_parameters", + "crypto.mac_algorithms", + "omb.mac_algorithm_parameters", + "omb.other_crypto_details", + "omb.certifications", + "@timestamp" + ], + "description": "OMB Report for the Department of Defense", + "grid": { + "columns": { + "omb.additional_notes": { + "width": 241 + } + } + }, + "hideChart": false, + "isTextBasedQuery": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "key": "omb.vulnerability_status", + "negate": false, + "type": "exists", + "value": "exists" + }, + "query": { + "exists": { + "field": "omb.vulnerability_status" + } + } + } + ], + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.index", + "query": { + "language": "kuery", + "query": "" + } + } + }, + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "tabs": [ + { + "attributes": { + "columns": [ + "observer.hostname", + "omb.vulnerability_status", + "omb.module_name", + "omb.crqc_vulnerable_algos", + "omb.pqc_algos", + "omb.symmetric_algos", + "omb.software_package_name", + "omb.software_package_version", + "omb.vendor", + "omb.operating_system", + "omb.additional_notes", + "omb.kex_protocols", + "tls.supported_ciphers", + "tls.preferred_key_exchange", + "omb.kex_secondary", + "omb.kem_algorithms", + "omb.kem_parameters", + "omb.dsa_algorithms", + "omb.dsa_parameters", + "omb.block_cipher_key_lengths", + "omb.block_cipher_modes", + "crypto.hash_algorithms", + "omb.hash_algorithm_parameters", + "crypto.mac_algorithms", + "omb.mac_algorithm_parameters", + "omb.other_crypto_details", + "omb.certifications", + "@timestamp" + ], + "grid": { + "columns": { + "omb.additional_notes": { + "width": 241 + } + } + }, + "hideChart": false, + "isTextBasedQuery": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"exists\",\"key\":\"omb.vulnerability_status\",\"value\":\"exists\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"exists\":{\"field\":\"omb.vulnerability_status\"}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "timeRange": { + "from": "now-24h/h", + "to": "now" + }, + "timeRestore": true + }, + "id": "cc77a3a6-6b3b-4ffc-b6fa-0db060e1091b", + "label": "Untitled" + } + ], + "timeRange": { + "from": "now-24h/h", + "to": "now" + }, + "timeRestore": true, + "title": "DoD OMB Report" }, - "sort": [ - [ - "@timestamp", - "desc" - ] + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report", + "references": [ + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + }, + { + "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + } ], - "timeRange": { - "from": "now-24h/h", - "to": "now" - }, - "timeRestore": true, - "title": "DoD OMB Report" - }, - "coreMigrationVersion": "8.8.0", - "id": "tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report", - "managed": false, - "originId": "662602a4-f820-4e80-9fe2-115c951fe43c", - "references": [ - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "kibanaSavedObjectMeta.searchSourceJSON.index", - "type": "index-pattern" - }, - { - "id": "05179988-8b3d-4f26-9832-d83a1e769b2d", - "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", - "type": "index-pattern" - } - ], - "type": "search", - "typeMigrationVersion": "10.5.0" -} + "type": "search", + "typeMigrationVersion": "10.12.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json index 66a8dbaa739..5f3d08283a0 100644 --- a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json +++ b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json @@ -1,46 +1,89 @@ { - "attributes": { - "columns": [ - "observer.hostname", - "tychon.type", - "x509.subject.common_name", - "certificate.issuer_common_name", - "x509.issuer.common_name", - "omb.sig_tier", - "tychon.crypto.grade", - "cert_days_remaining", - "cert_total_days", - "certificate.not_after", - "x509.not_after", - "certificate.is_self_signed", - "file.path", - "server.ip", - "server.port" - ], - "description": "All certs — FILE (disk scan) and PORT (live TLS). Sorted by earliest expiry. Scales via server-side pagination.", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"highlightAll\": true, \"version\": true, \"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": [], \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + "attributes": { + "columns": [ + "observer.hostname", + "tychon.type", + "x509.subject.common_name", + "certificate.issuer_common_name", + "x509.issuer.common_name", + "omb.sig_tier", + "tychon.crypto.grade", + "cert_days_remaining", + "cert_total_days", + "certificate.not_after", + "x509.not_after", + "certificate.is_self_signed", + "file.path", + "server.ip", + "server.port" + ], + "description": "All certs — FILE (disk scan) and PORT (live TLS). Sorted by earliest expiry. Scales via server-side pagination.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "highlightAll": true, + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.index", + "query": { + "language": "kuery", + "query": "" + }, + "version": true + } + }, + "sort": [ + [ + "cert_days_remaining", + "asc" + ] + ], + "tabs": [ + { + "attributes": { + "columns": [ + "observer.hostname", + "tychon.type", + "x509.subject.common_name", + "certificate.issuer_common_name", + "x509.issuer.common_name", + "omb.sig_tier", + "tychon.crypto.grade", + "cert_days_remaining", + "cert_total_days", + "certificate.not_after", + "x509.not_after", + "certificate.is_self_signed", + "file.path", + "server.ip", + "server.port" + ], + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\": true, \"version\": true, \"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": [], \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "cert_days_remaining", + "asc" + ] + ], + "version": 1 + }, + "id": "b1f91752-530a-4ed7-b9c2-79ff3c3a6653", + "label": "Untitled" + } + ], + "title": "Certificate Inventory Detail", + "version": 1 }, - "sort": [ - [ - "cert_days_remaining", - "asc" - ] + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail", + "references": [ + { + "id": "1dc9d581-4b38-4108-84e1-59a9fbcfbca5", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } ], - "title": "Certificate Inventory Detail", - "version": 1 - }, - "coreMigrationVersion": "8.8.0", - "id": "tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail", - "managed": false, - "originId": "d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001", - "references": [ - { - "id": "1dc9d581-4b38-4108-84e1-59a9fbcfbca5", - "name": "kibanaSavedObjectMeta.searchSourceJSON.index", - "type": "index-pattern" - } - ], - "type": "search", - "typeMigrationVersion": "10.5.0" -} + "type": "search", + "typeMigrationVersion": "10.12.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json index b14849564a5..6ecac686d80 100644 --- a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json @@ -1,19 +1,13 @@ { - "attributes": { - "color": "#E7664C", - "description": "PQC Scan Results", - "name": "ACDI" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "managed": false, - "originId": "6a127011-8fb1-4f28-afae-70d465f3f246", - "references": [], - "type": "tag", - "typeMigrationVersion": "8.0.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY4NzMzOSwzMF0=" -} + "attributes": { + "color": "#E7664C", + "description": "PQC Scan Results", + "name": "ACDI" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", + "references": [], + "type": "tag", + "typeMigrationVersion": "8.0.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json index 7abe599f47f..6eff37bfc7c 100644 --- a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json @@ -1,19 +1,13 @@ { - "attributes": { - "color": "#B9A888", - "description": "Updated for the Quantum 2.0.3 schema", - "name": "2.0.3" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "managed": false, - "originId": "fbb71a48-1a00-4182-8614-cacc09fd24f4", - "references": [], - "type": "tag", - "typeMigrationVersion": "8.0.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY4NzMzOCwzMF0=" -} + "attributes": { + "color": "#B9A888", + "description": "Updated for the Quantum 2.0.3 schema", + "name": "2.0.3" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", + "references": [], + "type": "tag", + "typeMigrationVersion": "8.0.0" +} \ No newline at end of file diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json index 0d9780245ba..c0549441990 100644 --- a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json @@ -1,19 +1,13 @@ { - "attributes": { - "color": "#1140c2", - "description": "", - "name": "Quantum Resilient" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", - "managed": false, - "originId": "2a2cc491-f59c-4504-b146-049aa17a25f2", - "references": [], - "type": "tag", - "typeMigrationVersion": "8.0.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY4NzM0MCwzMF0=" -} + "attributes": { + "color": "#1140c2", + "description": "", + "name": "Quantum Resilient" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-20T16:55:14.701Z", + "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", + "references": [], + "type": "tag", + "typeMigrationVersion": "8.0.0" +} \ No newline at end of file From c504bb35d3686b5c4e499cbf6aec1ac1954472d5 Mon Sep 17 00:00:00 2001 From: Thomas Hatcher Date: Tue, 21 Jul 2026 16:51:31 +0000 Subject: [PATCH 5/6] Remove unused Kibana visualization saved objects Deleted 14 standalone visualization saved objects that are no longer referenced by the package dashboards after converting visualization panels to by-value embeds. Confirmed all remaining data views are still referenced: - 05179988-8b3d-4f26-9832-d83a1e769b2d: used by application-report, application-detail, and DoD OMB report search - 1dc9d581-4b38-4108-84e1-59a9fbcfbca5: used by Certificate Inventory Detail search for runtime fields and duration formatting - 852a2806-9a09-4c17-bcea-b54e7b69f3bc: used by application-detail dashboard --- ...-4ea4-8458-7c8a8b58987e-cost-analysis.json | 2 +- ...0d80-4a28-9de7-55b2046f7c45-inventory.json | 2 +- ...-b0b9-c675dd057e2f-application-report.json | 2 +- ...-9410-7d8c01ff0d9a-application-detail.json | 2 +- ...ea1b-application-connections-topology.json | 2 +- ...3982-certificate-operations-dashboard.json | 2 +- ...4e80-9fe2-115c951fe43c-dod-omb-report.json | 6 ++-- ...d3e40001-certificate-inventory-detail.json | 6 ++-- ...-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json | 2 +- ...-dacb217e-57b4-4296-8545-cbf6b5739344.json | 2 +- ...-e9b715ba-5f19-4f99-b837-2c1a24143212.json | 2 +- ...-01375d36-099a-405d-a513-b1a782190a1d.json | 24 ------------- ...-1309bf24-a8af-43cb-8aae-cf88da1db46e.json | 35 ------------------- ...-1751052b-7016-4e89-b376-fd6a7064885f.json | 23 ------------ ...-2022b217-3551-4a32-b5e9-b77c85a38492.json | 23 ------------ ...-433bc733-a80c-4ca5-90a3-a667926206a1.json | 23 ------------ ...-461557f7-e0d3-45bd-88d2-06962ca8c975.json | 35 ------------------- ...-8f02e394-d19d-419f-bd75-8a1984c41984.json | 23 ------------ ...-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json | 35 ------------------- ...-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json | 22 ------------ ...-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json | 23 ------------ ...-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json | 22 ------------ ...-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json | 24 ------------- ...-ebdbafa8-2778-4098-b5df-fb2c23665551.json | 23 ------------ ...-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json | 23 ------------ 25 files changed, 15 insertions(+), 373 deletions(-) delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json delete mode 100644 packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json index b4d8f4696e2..5e796d85e7e 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json @@ -350,7 +350,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", "references": [ { diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json index 2b8625376a8..d5af6d21c6f 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json @@ -540,7 +540,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", "references": [ { diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json index 35fc7f30977..31c979f6f1d 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json @@ -2429,7 +2429,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", "references": [ { diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json index e96c00b11a2..cf5c2ccb2d3 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json @@ -2146,7 +2146,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", "references": [ { diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json index 9554c9c02e3..1f769e63c22 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json @@ -342,7 +342,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", "references": [ { diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json index 92534543c69..80511537c96 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json @@ -584,7 +584,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", "references": [ { diff --git a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json index d74a6daba59..ca8a6083619 100644 --- a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json +++ b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report.json @@ -153,7 +153,7 @@ "title": "DoD OMB Report" }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-662602a4-f820-4e80-9fe2-115c951fe43c-dod-omb-report", "references": [ { @@ -168,5 +168,5 @@ } ], "type": "search", - "typeMigrationVersion": "10.12.0" -} \ No newline at end of file + "typeMigrationVersion": "10.9.0" +} diff --git a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json index 5f3d08283a0..3446b89f85e 100644 --- a/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json +++ b/packages/tychon_quantum_command/kibana/search/tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail.json @@ -75,7 +75,7 @@ "version": 1 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-d7e8f9a0-2b3c-4d5e-9f0a-b1c2d3e40001-certificate-inventory-detail", "references": [ { @@ -85,5 +85,5 @@ } ], "type": "search", - "typeMigrationVersion": "10.12.0" -} \ No newline at end of file + "typeMigrationVersion": "10.9.0" +} diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json index 6ecac686d80..cbbdf6d97d0 100644 --- a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba.json @@ -5,7 +5,7 @@ "name": "ACDI" }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", "references": [], "type": "tag", diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json index 6eff37bfc7c..fd163f93249 100644 --- a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344.json @@ -5,7 +5,7 @@ "name": "2.0.3" }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", "references": [], "type": "tag", diff --git a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json index c0549441990..a09eaeb4186 100644 --- a/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json +++ b/packages/tychon_quantum_command/kibana/tag/tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212.json @@ -5,7 +5,7 @@ "name": "Quantum Resilient" }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-20T16:55:14.701Z", + "created_at": "2026-07-21T14:29:29.805Z", "id": "tychon_quantum_command-e9b715ba-5f19-4f99-b837-2c1a24143212", "references": [], "type": "tag", diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json deleted file mode 100644 index 5b180964592..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "Application PQC Dashboard Risk", - "uiStateJSON": "{}", - "version": "1", - "visState": "{\"title\":\"Application PQC Dashboard Risk\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\\"name\\\": \\\"totalApps\\\", \\\"update\\\": \\\"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexReady\\\", \\\"update\\\": \\\"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"kexPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"kexClr\\\", \\\"update\\\": \\\"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"protoReady\\\", \\\"update\\\": \\\"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"protoPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"protoClr\\\", \\\"update\\\": \\\"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"sigReady\\\", \\\"update\\\": \\\"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\\\"},\\n {\\\"name\\\": \\\"sigPct\\\", \\\"update\\\": \\\"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\\\"},\\n {\\\"name\\\": \\\"sigClr\\\", \\\"update\\\": \\\"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\\\"},\\n {\\\"name\\\": \\\"barW\\\", \\\"update\\\": \\\"width * 0.62 - 18\\\"}\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"apps_total\\\", \\\"source\\\": \\\"apps_raw\\\"},\\n {\\n \\\"name\\\": \\\"kex_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.kex_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"kex_pqc\\\", \\\"source\\\": \\\"kex_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"proto_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"proto_pqc\\\", \\\"source\\\": \\\"proto_pqc_raw\\\"},\\n {\\n \\\"name\\\": \\\"sig_pqc_raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"PQC READY\\\"}}, \\\"aggs\\\": {\\\"u\\\": {\\\"cardinality\\\": {\\\"field\\\": \\\"process.executable\\\"}}}}}}\\n },\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.f.u\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\\"name\\\": \\\"sig_pqc\\\", \\\"source\\\": \\\"sig_pqc_raw\\\"}\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 22},\\n \\\"text\\\": {\\\"value\\\": \\\"APPLICATION PQC DASHBOARD\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 11}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 40},\\n \\\"text\\\": {\\\"signal\\\": \\\"'PQC COMPLIANCE PROGRESS \u2014 ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 60}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 78},\\n \\\"text\\\": {\\\"value\\\": \\\"KEX COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 93},\\n \\\"text\\\": {\\\"signal\\\": \\\"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \u2014 PQC READY key exchange'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 106},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * kexPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 122},\\n \\\"text\\\": {\\\"signal\\\": \\\"kexPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"kexClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 138},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 140}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 158},\\n \\\"text\\\": {\\\"value\\\": \\\"PROTOCOL COMPLIANCE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 173},\\n \\\"text\\\": {\\\"signal\\\": \\\"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \u2014 TLS 1.3 capable'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 186},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * protoPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 202},\\n \\\"text\\\": {\\\"signal\\\": \\\"protoPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"protoClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 218},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"value\\\": \\\"#161616\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"value\\\": 220}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 78},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 238},\\n \\\"text\\\": {\\\"value\\\": \\\"CERT SIGNATURE\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#888888\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 253},\\n \\\"text\\\": {\\\"signal\\\": \\\"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \u2014 PQC READY signature'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266}, \\\"width\\\": {\\\"signal\\\": \\\"barW\\\"}, \\\"height\\\": {\\\"value\\\": 8},\\n \\\"cornerRadius\\\": {\\\"value\\\": 4}, \\\"fill\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#2a2a2a\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 18}, \\\"y\\\": {\\\"value\\\": 266},\\n \\\"width\\\": {\\\"signal\\\": \\\"max(0, barW * sigPct / 100)\\\"},\\n \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 4},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"value\\\": 282},\\n \\\"text\\\": {\\\"signal\\\": \\\"sigPct + '%'\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"sigClr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 24}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-01375d36-099a-405d-a513-b1a782190a1d", - "managed": false, - "originId": "a80b900a-ad14-4973-ba14-6135a7657b22", - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NzEsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json deleted file mode 100644 index d138939bfae..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "QuantumApplicationList", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"QuantumApplicationList\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Application filter list panel (multi-select) with dashboard filter integration.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"selectedApps\\\",\\n \\\"value\\\": \\\"|\\\",\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@appRowBg:click\\\",\\n \\\"update\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? replace(selectedApps, '|' + datum.app + '|', '|') : selectedApps + datum.app + '|'\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedAppsArray\\\",\\n \\\"update\\\": \\\"selectedApps == '|' ? [] : split(slice(selectedApps, 1, length(selectedApps)-1), '|')\\\"\\n },\\n {\\n \\\"name\\\": \\\"activeFilter\\\",\\n \\\"update\\\": \\\"length(selectedAppsArray) > 0 ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'terms': {'tychon.application.name': selectedAppsArray}}]}} : {'term': {'event.dataset': 'tychon.application'}}\\\"\\n },\\n {\\n \\\"name\\\": \\\"_applyAppFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@applyBtn:click\\\",\\n \\\"update\\\": \\\"kibanaAddFilter(activeFilter)\\\",\\n \\\"force\\\": true\\n }\\n ]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"apps\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"app_only\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } },\\n \\\"aggs\\\": {\\n \\\"app_names\\\": {\\n \\\"terms\\\": {\\n \\\"field\\\": \\\"tychon.application.name\\\",\\n \\\"size\\\": 200,\\n \\\"order\\\": { \\\"_count\\\": \\\"desc\\\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.app_only.app_names.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"app\\\", \\\"expr\\\": \\\"datum.key\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"datum.doc_count\\\" },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"72 + (datum.rn - 1) * 26\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.rn <= 15\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLICATION FILTER\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"name\\\": \\\"applyBtn\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 92\\\" },\\n \\\"y\\\": { \\\"value\\\": 16 },\\n \\\"width\\\": { \\\"value\\\": 76 },\\n \\\"height\\\": { \\\"value\\\": 20 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#9fd7ff\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 54\\\" },\\n \\\"y\\\": { \\\"value\\\": 26 },\\n \\\"text\\\": { \\\"value\\\": \\\"APPLY\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#dff0ff\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"name\\\": \\\"appRowBg\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 18 },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y - 10\\\" },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 18\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"datum.y + 10\\\" },\\n \\\"cornerRadius\\\": { \\\"value\\\": 6 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#1f4d74' : '#0f1115'\\\" },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#9fd7ff' : '#253241'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 30 },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"app\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#e8f3ff' : '#c9d7e5'\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - 110\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"apps\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"width - 30\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"format(datum.count, ',')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#d9eeff' : '#8ea3b8'\\\" },\\n \\\"align\\\": { \\\"value\\\": \\\"right\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n }\\n ]\\n}\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-1309bf24-a8af-43cb-8aae-cf88da1db46e", - "managed": false, - "originId": "4caff337-23d1-4e48-b924-e2fe546c1b8c", - "references": [ - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", - "type": "tag" - } - ], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NjksMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json deleted file mode 100644 index a544b64d5b1..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "CERT OPS \u2014 Key Algorithm", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\": \"CERT OPS \\u2014 Key Algorithm\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_algo\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.algorithm\\\", \\\"size\\\": 10}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_algo.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"palette\\\",\\n \\\"values\\\": [\\n {\\\"k\\\": \\\"RSA\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"lbl\\\": \\\"RSA\\\", \\\"desc\\\": \\\"Rivest\\u2013Shamir\\u2013Adleman \\u2014 quantum-vulnerable via Shor's algorithm\\\"},\\n {\\\"k\\\": \\\"ECDSA\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"lbl\\\": \\\"ECDSA\\\", \\\"desc\\\": \\\"Elliptic curve \\u2014 quantum-vulnerable, efficient on classical hardware\\\"},\\n {\\\"k\\\": \\\"DSA\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"lbl\\\": \\\"DSA\\\", \\\"desc\\\": \\\"Digital Signature Algorithm \\u2014 deprecated, should not be in new certs\\\"},\\n {\\\"k\\\": \\\"unknown_der\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown DER\\\", \\\"desc\\\": \\\"DER-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"unknown_pem\\\", \\\"clr\\\": \\\"#78909c\\\", \\\"bg\\\": \\\"#78909c18\\\", \\\"lbl\\\": \\\"Unknown PEM\\\", \\\"desc\\\": \\\"PEM-encoded cert with unrecognized key OID\\\"},\\n {\\\"k\\\": \\\"ML-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"ML-DSA\\\", \\\"desc\\\": \\\"Lattice-based PQC signature \\u2014 CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"SLH-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"SLH-DSA\\\", \\\"desc\\\": \\\"Hash-based PQC signature \\u2014 CNSA 2.0 quantum-resistant\\\"},\\n {\\\"k\\\": \\\"FN-DSA\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"lbl\\\": \\\"FN-DSA\\\", \\\"desc\\\": \\\"Falcon lattice signature \\u2014 CNSA 2.0 quantum-resistant\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"palette\\\", \\\"key\\\": \\\"k\\\", \\\"fields\\\": [\\\"k\\\"],\\n \\\"values\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"], \\\"as\\\": [\\\"clr\\\", \\\"bg\\\", \\\"lbl\\\", \\\"desc\\\"],\\n \\\"default\\\": \\\"#78909c\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.clr || '#78909c'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.bg || '#78909c18'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"lbl\\\", \\\"expr\\\": \\\"datum.lbl || datum.k\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\", \\\"expr\\\": \\\"datum.desc || 'Unrecognized key algorithm'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bw\\\", \\\"expr\\\": \\\"width * 0.58 - 110\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"rows\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"PUBLIC KEY TYPE \\u2014 click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161622' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.4\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 10}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '88'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-1751052b-7016-4e89-b376-fd6a7064885f", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTMsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json deleted file mode 100644 index b04bd3bbd95..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "CERT OPS \u2014 Inventory Header", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\": \"CERT OPS \\u2014 Inventory Header\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"total\\\", \\\"update\\\": \\\"length(data('d_total'))>0 ? data('d_total')[0].n : 0\\\"}, {\\\"name\\\": \\\"expired\\\", \\\"update\\\": \\\"length(data('d_expired'))>0 ? data('d_expired')[0].n : 0\\\"}, {\\\"name\\\": \\\"exp30\\\", \\\"update\\\": \\\"length(data('d_exp30'))>0 ? data('d_exp30')[0].n : 0\\\"}, {\\\"name\\\": \\\"self\\\", \\\"update\\\": \\\"length(data('d_self'))>0 ? data('d_self')[0].n : 0\\\"}, {\\\"name\\\": \\\"legacy\\\", \\\"update\\\": \\\"length(data('d_legacy'))>0 ? data('d_legacy')[0].n : 0\\\"}, {\\\"name\\\": \\\"pqcvuln\\\", \\\"update\\\": \\\"length(data('d_pqcvuln'))>0 ? data('d_pqcvuln')[0].n : 0\\\"}, {\\\"name\\\": \\\"bw\\\", \\\"update\\\": \\\"floor((width - 10) / 6) - 4\\\"}, {\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? null : datum.k) : sel\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"tile\\\"}, \\\"update\\\": \\\"datum.filt ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_total\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"d_expired\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_exp30\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_self\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_legacy\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"d_pqcvuln\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"f\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.f\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tiles\\\", \\\"values\\\": [{\\\"k\\\": \\\"TOTAL\\\", \\\"ord\\\": 0, \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"sig\\\": \\\"total\\\", \\\"filt\\\": null}, {\\\"k\\\": \\\"EXPIRED\\\", \\\"ord\\\": 1, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"ord\\\": 2, \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"sig\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"ord\\\": 3, \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"sig\\\": \\\"self\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"LEGACY\\\", \\\"ord\\\": 4, \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"sig\\\": \\\"legacy\\\", \\\"filt\\\": {\\\"term\\\": {\\\"omb.sig_tier\\\": \\\"LEGACY\\\"}}}, {\\\"k\\\": \\\"PQC VULN\\\", \\\"ord\\\": 5, \\\"clr\\\": \\\"#ab47bc\\\", \\\"bg\\\": \\\"#ab47bc18\\\", \\\"sig\\\": \\\"pqcvuln\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"omb.sig_tier\\\": [\\\"CLASSICAL\\\", \\\"MODERN\\\", \\\"LEGACY\\\"]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"x\\\", \\\"expr\\\": \\\"datum.ord * (bw + 4) + 8\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"val\\\", \\\"expr\\\": \\\"datum.sig === 'total' ? total : datum.sig === 'expired' ? expired : datum.sig === 'exp30' ? exp30 : datum.sig === 'self' ? self : datum.sig === 'legacy' ? legacy : pqcvuln\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE INVENTORY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL OVERVIEW \\\\u2014 click a tile to filter the dashboard\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"tile\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"field\\\": \\\"x\\\"}, \\\"y\\\": {\\\"value\\\": 52}, \\\"width\\\": {\\\"signal\\\": \\\"bw\\\"}, \\\"height\\\": {\\\"value\\\": 72}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.bg : '#161616'\\\"}, \\\"cornerRadius\\\": {\\\"value\\\": 3}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 && datum.filt ? '#2a2a3a' : '#222222')\\\"}, \\\"strokeWidth\\\": {\\\"signal\\\": \\\"datum.k === sel ? 2 : 1\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 88}, \\\"text\\\": {\\\"signal\\\": \\\"datum.val >= 1000 ? format(datum.val,'.3~s') : format(datum.val,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : (datum.val > 0 ? datum.clr : '#3a3a3a')\\\"}, \\\"fontSize\\\": {\\\"value\\\": 22}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"tiles\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"datum.x + bw/2\\\"}, \\\"y\\\": {\\\"value\\\": 108}, \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? datum.clr : '#666666'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}]}\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-2022b217-3551-4a32-b5e9-b77c85a38492", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NDksMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json deleted file mode 100644 index 611fa6084a9..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "CERT OPS \u2014 Top Issuing CAs", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\": \"CERT OPS \\u2014 Top Issuing CAs\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.issuer_organization': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.issuer_organization': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_issuer\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.issuer_organization\\\", \\\"size\\\": 10, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_issuer.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 52 + 52\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.rnk === 1 ? '#448aff' : datum.rnk === 2 ? '#4db6ac' : datum.rnk <= 5 ? '#546e7a' : '#37474f'\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"TOP ISSUING CAs\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE AUTHORITY \\u2014 who issued your certificates \\u00b7 click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 3}, \\\"height\\\": {\\\"value\\\": 46},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 30}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.rnk, 'd') + '.'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 17\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.62\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 36}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.62) : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 5}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.clr + '66'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 45\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"raw\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#888888'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-433bc733-a80c-4ca5-90a3-a667926206a1", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTIsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json deleted file mode 100644 index 3c19412ac59..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "Connections Selection Details", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Connections Selection Details\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection details panel for host/application context using dashboard filters.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"panelW\\\", \\\"update\\\": \\\"width - 20\\\" },\\n { \\\"name\\\": \\\"labelX\\\", \\\"value\\\": 26 },\\n { \\\"name\\\": \\\"valueX\\\", \\\"update\\\": \\\"width * 0.42\\\" },\\n { \\\"name\\\": \\\"row0\\\", \\\"value\\\": 74 },\\n { \\\"name\\\": \\\"rowH\\\", \\\"value\\\": 24 }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"context\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"host\\\": { \\\"terms\\\": { \\\"field\\\": \\\"observer.hostname\\\", \\\"size\\\": 1 } },\\n \\\"app\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name.keyword\\\", \\\"size\\\": 1 } },\\n \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"server.address\\\", \\\"size\\\": 1 } },\\n \\\"proto\\\": { \\\"terms\\\": { \\\"field\\\": \\\"network.protocol\\\", \\\"size\\\": 1 } },\\n \\\"tls_ver\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_protocol\\\", \\\"size\\\": 1 } },\\n \\\"cipher\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tls.preferred_cipher\\\", \\\"size\\\": 1 } },\\n \\\"events\\\": { \\\"value_count\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"first_seen\\\": { \\\"min\\\": { \\\"field\\\": \\\"@timestamp\\\" } },\\n \\\"last_seen\\\": { \\\"max\\\": { \\\"field\\\": \\\"@timestamp\\\" } }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"host\\\",\\n \\\"expr\\\": \\\"datum.host && datum.host.buckets && length(datum.host.buckets)>0 ? datum.host.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"app\\\",\\n \\\"expr\\\": \\\"datum.app && datum.app.buckets && length(datum.app.buckets)>0 ? datum.app.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"dst\\\",\\n \\\"expr\\\": \\\"datum.dst && datum.dst.buckets && length(datum.dst.buckets)>0 ? datum.dst.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"proto\\\",\\n \\\"expr\\\": \\\"datum.proto && datum.proto.buckets && length(datum.proto.buckets)>0 ? datum.proto.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"tlsVer\\\",\\n \\\"expr\\\": \\\"datum.tls_ver && datum.tls_ver.buckets && length(datum.tls_ver.buckets)>0 ? datum.tls_ver.buckets[0].key : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"cipher\\\",\\n \\\"expr\\\": \\\"datum.cipher && datum.cipher.buckets && length(datum.cipher.buckets)>0 ? datum.cipher.buckets[0].key : ''\\\"\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"events\\\", \\\"expr\\\": \\\"datum.events ? datum.events.value : 0\\\" },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"firstSeen\\\",\\n \\\"expr\\\": \\\"datum.first_seen && isValid(datum.first_seen.value_as_string) ? datum.first_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"lastSeen\\\",\\n \\\"expr\\\": \\\"datum.last_seen && isValid(datum.last_seen.value_as_string) ? datum.last_seen.value_as_string : ''\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionType\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? 'APPLICATION CONTEXT' : (datum.host != '' ? 'HOST CONTEXT' : 'NO SELECTION')\\\"\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"selectionId\\\",\\n \\\"expr\\\": \\\"datum.app != '' ? datum.app : (datum.host != '' ? datum.host : 'Select a host/app in the graph')\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"context\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"project\\\",\\n \\\"fields\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ],\\n \\\"as\\\": [\\n \\\"selectionType\\\",\\n \\\"selectionId\\\",\\n \\\"host\\\",\\n \\\"app\\\",\\n \\\"dst\\\",\\n \\\"proto\\\",\\n \\\"tlsVer\\\",\\n \\\"cipher\\\",\\n \\\"events\\\",\\n \\\"firstSeen\\\",\\n \\\"lastSeen\\\"\\n ]\\n },\\n {\\n \\\"type\\\": \\\"formula\\\",\\n \\\"as\\\": \\\"kv\\\",\\n \\\"expr\\\": \\\"[{k:'Context',v:datum.selectionType},{k:'Selection',v:datum.selectionId},{k:'Source Host',v:datum.host},{k:'Application',v:datum.app},{k:'Destination',v:datum.dst},{k:'Protocol',v:datum.proto},{k:'TLS Version',v:datum.tlsVer},{k:'Cipher',v:datum.cipher},{k:'Event Count',v:format(datum.events, ',')},{k:'First Seen',v:datum.firstSeen},{k:'Last Seen',v:datum.lastSeen}]\\\"\\n },\\n { \\\"type\\\": \\\"flatten\\\", \\\"fields\\\": [\\\"kv\\\"], \\\"as\\\": [\\\"row\\\"] },\\n { \\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"row_number\\\"], \\\"as\\\": [\\\"rn\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"row0 + (datum.rn - 1) * rowH\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 10\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#0f1115\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.96 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#2b3440\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"cornerRadius\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 10 },\\n \\\"y\\\": { \\\"value\\\": 10 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width - 10\\\" },\\n \\\"y2\\\": { \\\"value\\\": 42 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#17324a\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.92 },\\n \\\"cornerRadiusTopLeft\\\": { \\\"value\\\": 8 },\\n \\\"cornerRadiusTopRight\\\": { \\\"value\\\": 8 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"value\\\": 24 },\\n \\\"y\\\": { \\\"value\\\": 30 },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 12 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8f3ff\\\" },\\n \\\"text\\\": { \\\"value\\\": \\\"SELECTION DETAILS\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX - 10\\\" },\\n \\\"y\\\": { \\\"value\\\": 54 },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height - 20\\\" },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#1f2a36\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"labelX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.k\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fontWeight\\\": { \\\"value\\\": \\\"bold\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#9fc4e0\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"rows\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"valueX\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"y\\\" },\\n \\\"text\\\": { \\\"signal\\\": \\\"datum.row.v == '' ? '\u2014' : datum.row.v\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 10 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#e8eef5\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"middle\\\" },\\n \\\"limit\\\": { \\\"signal\\\": \\\"width - valueX - 18\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-461557f7-e0d3-45bd-88d2-06962ca8c975", - "managed": false, - "originId": "d5510112-05fd-47b6-8930-fe26306b50ce", - "references": [ - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", - "type": "tag" - } - ], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NjcsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json deleted file mode 100644 index b3c8e88a724..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "CERT OPS \u2014 Quantum Tier", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\": \"CERT OPS \\u2014 Quantum Tier\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? null : datum.t\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"k\\\": {\\\"terms\\\": {\\\"field\\\": \\\"omb.sig_tier\\\", \\\"size\\\": 10}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.k.buckets\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"t\\\", \\\"expr\\\": \\\"datum.key\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"}]}, {\\\"name\\\": \\\"tc\\\", \\\"source\\\": \\\"raw\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"t\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"]}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"tc\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"t\\\": \\\"PQC READY\\\", \\\"lbl\\\": \\\"ML-DSA / Dilithium\\\", \\\"desc\\\": \\\"Post-quantum lattice signature \\\\u2014 quantum-resistant, CNSA 2.0 approved\\\", \\\"badge\\\": \\\"PQC READY\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0}, {\\\"t\\\": \\\"MODERN\\\", \\\"lbl\\\": \\\"ECDSA (P-256 / P-384)\\\", \\\"desc\\\": \\\"Elliptic curve \\\\u2014 quantum-vulnerable via Shor's algorithm, must be replaced pre-2035\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 1}, {\\\"t\\\": \\\"CLASSICAL\\\", \\\"lbl\\\": \\\"RSA / SHA-256 RSA\\\", \\\"desc\\\": \\\"RSA \\\\u2014 quantum-vulnerable via Shor's algorithm, harvest-now-decrypt-later risk today\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 2}, {\\\"t\\\": \\\"LEGACY\\\", \\\"lbl\\\": \\\"MD5 / SHA-1 RSA\\\", \\\"desc\\\": \\\"SHA-1/MD5 hash \\\\u2014 classically broken and quantum-vulnerable, replace immediately\\\", \\\"badge\\\": \\\"QUANTUM VULN\\\", \\\"clr\\\": \\\"#b71c1c\\\", \\\"bg\\\": \\\"#b71c1c22\\\", \\\"ord\\\": 3}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"tc\\\", \\\"key\\\": \\\"t\\\", \\\"fields\\\": [\\\"t\\\"], \\\"values\\\": [\\\"n\\\"], \\\"as\\\": [\\\"n\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 60\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SIGNATURE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"value\\\": 38}, \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM \\\\u2014 click a tier to filter\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 48}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?datum.clr:'#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 55}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.5\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0?'#e8e8e8':'#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 106}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.56\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.t===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\\\"}, \\\"height\\\": {\\\"value\\\": 6}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}}}}]}\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-8f02e394-d19d-419f-bd75-8a1984c41984", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTAsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json deleted file mode 100644 index 8a07af7eecd..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "QuantumRiskRadial", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"QuantumRiskRadial\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"description\\\": \\\"Selection risk dial aligned to inventory OMB readiness tiers.\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 10,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n { \\\"name\\\": \\\"cx\\\", \\\"update\\\": \\\"width/2\\\" },\\n { \\\"name\\\": \\\"cy\\\", \\\"update\\\": \\\"height*0.56\\\" },\\n { \\\"name\\\": \\\"r\\\", \\\"update\\\": \\\"min(width, height) * 0.34\\\" }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"risk\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-inventory*\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"apps_total\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } },\\n \\\"kex_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.kex_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"proto_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.protocol_tier\\\": \\\"TLS 1.3\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n },\\n \\\"sig_ready\\\": {\\n \\\"filter\\\": { \\\"term\\\": { \\\"omb.sig_tier\\\": \\\"PQC READY\\\" } },\\n \\\"aggs\\\": { \\\"u\\\": { \\\"cardinality\\\": { \\\"field\\\": \\\"process.executable\\\" } } }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"isValid(datum.apps_total) && isValid(datum.apps_total.value) ? max(1, datum.apps_total.value) : 1\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"kex_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.kex_ready) && isValid(datum.kex_ready.u) && isValid(datum.kex_ready.u.value) ? datum.kex_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"proto_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.proto_ready) && isValid(datum.proto_ready.u) && isValid(datum.proto_ready.u.value) ? datum.proto_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sig_ready_n\\\", \\\"expr\\\": \\\"isValid(datum.sig_ready) && isValid(datum.sig_ready.u) && isValid(datum.sig_ready.u.value) ? datum.sig_ready.u.value : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_kex_ready\\\", \\\"expr\\\": \\\"100 * datum.kex_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_proto_ready\\\", \\\"expr\\\": \\\"100 * datum.proto_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"p_sig_ready\\\", \\\"expr\\\": \\\"100 * datum.sig_ready_n / datum.n\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"readiness\\\", \\\"expr\\\": \\\"clamp(round((datum.p_kex_ready + datum.p_proto_ready + datum.p_sig_ready) / 3), 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"score\\\", \\\"expr\\\": \\\"clamp(100 - datum.readiness, 0, 100)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? 'LOW' : datum.readiness >= 60 ? 'MEDIUM' : 'HIGH'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"color\\\", \\\"expr\\\": \\\"datum.readiness >= 90 ? '#22c55e' : datum.readiness >= 60 ? '#f59e0b' : '#ef4444'\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"angle\\\", \\\"expr\\\": \\\"-3.1415926 + (datum.score/100) * 3.1415926 * 2\\\" }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"value\\\": 3.1415926},\\n \\\"fill\\\": {\\\"value\\\": \\\"#1f2937\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"arc\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy\\\"},\\n \\\"innerRadius\\\": {\\\"signal\\\": \\\"r-18\\\"}, \\\"outerRadius\\\": {\\\"signal\\\": \\\"r\\\"},\\n \\\"startAngle\\\": {\\\"value\\\": -3.1415926}, \\\"endAngle\\\": {\\\"field\\\": \\\"angle\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy - 6\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.score, 'd') + '/100'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 28}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"field\\\": \\\"color\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"risk\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"cx\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"cy + 24\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.tier + ' RISK'\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cfe3f7\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-9b1cd080-9823-4903-bc8c-120d4ccdb2c4", - "managed": false, - "originId": "dfb8a02d-f29b-48d9-8ed9-c997d0f0bfe2", - "references": [ - { - "id": "tychon_quantum_command-07b6a21f-5bba-413b-8d49-e8c246dde2ba", - "name": "tag-ref-6a127011-8fb1-4f28-afae-70d465f3f246", - "type": "tag" - }, - { - "id": "tychon_quantum_command-dacb217e-57b4-4296-8545-cbf6b5739344", - "name": "tag-ref-fbb71a48-1a00-4182-8614-cacc09fd24f4", - "type": "tag" - } - ], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NzAsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json deleted file mode 100644 index ca67b0a5386..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "attributes": { - "description": "Certificate lifetime buckets: automated (\u226490d) through legacy (>5yr) with key management system insight", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": []}" - }, - "title": "Certificate Longevity", - "uiStateJSON": "{}", - "visState": "{\"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"le90d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();if(na<=System.currentTimeMillis())return false;long d=(na-nb)/86400000L;return d>=0&&d<=90;\\\"}}}}, \\\"le1yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>90&&d<=365;\\\"}}}}, \\\"le825d\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>365&&d<=825;\\\"}}}}, \\\"le5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>825&&d<=1825;\\\"}}}}, \\\"gt5yr\\\": {\\\"filter\\\": {\\\"script\\\": {\\\"script\\\": {\\\"lang\\\": \\\"painless\\\", \\\"source\\\": \\\"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>1825;\\\"}}}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le90d\\\", \\\"expr\\\": \\\"datum.le90d ? datum.le90d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le1yr\\\", \\\"expr\\\": \\\"datum.le1yr ? datum.le1yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le825d\\\", \\\"expr\\\": \\\"datum.le825d ? datum.le825d.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"le5yr\\\", \\\"expr\\\": \\\"datum.le5yr ? datum.le5yr.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"gt5yr\\\", \\\"expr\\\": \\\"datum.gt5yr ? datum.gt5yr.doc_count : 0\\\"}]}, {\\\"name\\\": \\\"tot\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"le90d\\\", \\\"lbl\\\": \\\"Automated \\\\u226490 days\\\", \\\"mgmt\\\": \\\"KEY MGT SYSTEM\\\", \\\"desc\\\": \\\"Almost certainly managed by ACME / Let's Encrypt / cert-manager \\\\u2014 short lifetime is a signature of automated issuance\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"le90d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gte\\\": 0, \\\"lte\\\": 90}}}}, {\\\"k\\\": \\\"le1yr\\\", \\\"lbl\\\": \\\"Short-lived \\\\u22641 year\\\", \\\"mgmt\\\": \\\"LIKELY MANAGED\\\", \\\"desc\\\": \\\"Annual lifetime pattern \\\\u2014 may be automated renewal or disciplined manual rotation by an ops team\\\", \\\"clr\\\": \\\"#4db6ac\\\", \\\"bg\\\": \\\"#4db6ac18\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"le1yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 90, \\\"lte\\\": 365}}}}, {\\\"k\\\": \\\"le825d\\\", \\\"lbl\\\": \\\"Modern \\\\u2264825 days\\\", \\\"mgmt\\\": \\\"CA ISSUED\\\", \\\"desc\\\": \\\"Within Apple / browser maximum trust limit (825 days) \\\\u2014 actively issued by a real CA, rotation expected\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"le825d\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 365, \\\"lte\\\": 825}}}}, {\\\"k\\\": \\\"le5yr\\\", \\\"lbl\\\": \\\"Long-lived \\\\u22645 years\\\", \\\"mgmt\\\": \\\"MANUAL\\\", \\\"desc\\\": \\\"826\\\\u20131825 day lifetime \\\\u2014 manually managed, no automated rotation, quantum risk grows over the certificate's life\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"le5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 825, \\\"lte\\\": 1825}}}}, {\\\"k\\\": \\\"gt5yr\\\", \\\"lbl\\\": \\\"Legacy > 5 years\\\", \\\"mgmt\\\": \\\"LEGACY / MANUAL\\\", \\\"desc\\\": \\\"5+ year validity \\\\u2014 definitely manually issued; each year of remaining life increases the window for harvest-now-decrypt-later attacks\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"gt5yr\\\", \\\"filt\\\": {\\\"range\\\": {\\\"cert_total_days\\\": {\\\"gt\\\": 1825}}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? (datum.field==='le90d' ? data('raw')[0].le90d : datum.field==='le1yr' ? data('raw')[0].le1yr : datum.field==='le825d' ? data('raw')[0].le825d : datum.field==='le5yr' ? data('raw')[0].le5yr : data('raw')[0].gt5yr) : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 72 + 52\\\"}]}, {\\\"name\\\": \\\"mx\\\", \\\"source\\\": \\\"rows\\\", \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LONGEVITY\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE LIFETIME \\\\u2014 short = automated key management \\\\u00b7 long = manual / legacy\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161616' : '#121212'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 66}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 65\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.52\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 12}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 42\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.74\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 8\\\"}, \\\"width\\\": {\\\"value\\\": 82}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76 + 41\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"}, \\\"text\\\": {\\\"field\\\": \\\"mgmt\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.76\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 28\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 82 : 0\\\"}, \\\"height\\\": {\\\"value\\\": 8}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '44'\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 52\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 && datum.n > 0 ? format(datum.pct * 100, '.1f') + '%' : ''\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-a4f28c31-9e2d-4b0a-b5e7-d1c8f9e01234", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTYsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json deleted file mode 100644 index d325a41f23f..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": []}" - }, - "title": "Certificate Hygiene", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"raw\\\", \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"expired\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, \\\"exp30\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, \\\"exp90\\\": {\\\"filter\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, \\\"selfsign\\\": {\\\"filter\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, \\\"weakkey\\\": {\\\"filter\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}, \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"certificate.not_after\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"expired\\\", \\\"expr\\\": \\\"datum.expired ? datum.expired.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp30\\\", \\\"expr\\\": \\\"datum.exp30 ? datum.exp30.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"exp90\\\", \\\"expr\\\": \\\"datum.exp90 ? datum.exp90.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"selfsign\\\", \\\"expr\\\": \\\"datum.selfsign ? datum.selfsign.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"weakkey\\\", \\\"expr\\\": \\\"datum.weakkey ? datum.weakkey.doc_count : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"total\\\", \\\"expr\\\": \\\"datum.total ? datum.total.value : 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"EXPIRED\\\", \\\"lbl\\\": \\\"Expired\\\", \\\"desc\\\": \\\"certificate.not_after < now \\\\u2014 no longer trusted by any client\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 0, \\\"field\\\": \\\"expired\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"lt\\\": \\\"now\\\"}}}}, {\\\"k\\\": \\\"EXP 30D\\\", \\\"lbl\\\": \\\"Expiring in 30 days\\\", \\\"desc\\\": \\\"certificate.not_after within 30 days \\\\u2014 immediate renewal required\\\", \\\"sev\\\": \\\"high\\\", \\\"clr\\\": \\\"#ff7043\\\", \\\"bg\\\": \\\"#ff704318\\\", \\\"ord\\\": 1, \\\"field\\\": \\\"exp30\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now\\\", \\\"lt\\\": \\\"now+30d\\\"}}}}, {\\\"k\\\": \\\"EXP 90D\\\", \\\"lbl\\\": \\\"Expiring in 90 days\\\", \\\"desc\\\": \\\"certificate.not_after within 90 days \\\\u2014 plan renewal now\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 2, \\\"field\\\": \\\"exp90\\\", \\\"filt\\\": {\\\"range\\\": {\\\"certificate.not_after\\\": {\\\"gte\\\": \\\"now+30d\\\", \\\"lt\\\": \\\"now+90d\\\"}}}}, {\\\"k\\\": \\\"SELF-SIGNED\\\", \\\"lbl\\\": \\\"Self-Signed\\\", \\\"desc\\\": \\\"certificate.is_self_signed = true \\\\u2014 no CA trust chain, browser errors\\\", \\\"sev\\\": \\\"medium\\\", \\\"clr\\\": \\\"#ffa726\\\", \\\"bg\\\": \\\"#ffa72618\\\", \\\"ord\\\": 3, \\\"field\\\": \\\"selfsign\\\", \\\"filt\\\": {\\\"term\\\": {\\\"certificate.is_self_signed\\\": true}}}, {\\\"k\\\": \\\"WEAK KEY\\\", \\\"lbl\\\": \\\"Weak Key \\\\u22641024-bit\\\", \\\"desc\\\": \\\"RSA/DSA key \\\\u22641024 bits \\\\u2014 computationally breakable, must be replaced\\\", \\\"sev\\\": \\\"critical\\\", \\\"clr\\\": \\\"#ef5350\\\", \\\"bg\\\": \\\"#ef535018\\\", \\\"ord\\\": 4, \\\"field\\\": \\\"weakkey\\\", \\\"filt\\\": {\\\"terms\\\": {\\\"certificate.subject_public_key_info.bit_size\\\": [512, 1024]}}}], \\\"transform\\\": [{\\\"type\\\": \\\"lookup\\\", \\\"from\\\": \\\"raw\\\", \\\"key\\\": \\\"total\\\", \\\"fields\\\": [\\\"ord\\\"], \\\"values\\\": [\\\"expired\\\", \\\"exp30\\\", \\\"exp90\\\", \\\"selfsign\\\", \\\"weakkey\\\", \\\"total\\\"], \\\"as\\\": [\\\"v_expired\\\", \\\"v_exp30\\\", \\\"v_exp90\\\", \\\"v_selfsign\\\", \\\"v_weakkey\\\", \\\"v_total\\\"], \\\"default\\\": 0}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.field==='expired' ? (length(data('raw'))>0?data('raw')[0].expired:0) : datum.field==='exp30' ? (length(data('raw'))>0?data('raw')[0].exp30:0) : datum.field==='exp90' ? (length(data('raw'))>0?data('raw')[0].exp90:0) : datum.field==='selfsign' ? (length(data('raw'))>0?data('raw')[0].selfsign:0) : (length(data('raw'))>0?data('raw')[0].weakkey:0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('raw'))>0 ? data('raw')[0].total : 1\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 68 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE HYGIENE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"OPERATIONAL ISSUES \\\\u2014 expiry \\\\u00b7 trust \\\\u00b7 key strength\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : datum.n>0 ? datum.bg : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 62}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 61\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 16}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sev\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n>0 ? datum.clr : '#383838'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 29\\\"}, \\\"width\\\": {\\\"value\\\": 72}, \\\"height\\\": {\\\"value\\\": 14}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"value\\\": \\\"#1a1a1a\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#333333' : '#222222'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width * 0.62 + 36\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.tot > 0 ? format(datum.pct * 100, '.1f') + '%' : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 20}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-b1063363-e1e3-4291-ba8a-9e5c49bba3d7", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTEsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json deleted file mode 100644 index 420b10fe0d0..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "attributes": { - "description": "File system disk scan vs live TLS port capture \u2014 how each certificate was discovered", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\": {\"language\": \"kuery\", \"query\": \"\"}, \"filter\": []}" - }, - "title": "Certificate Source Type", - "uiStateJSON": "{}", - "visState": "{\"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\", \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0}, \\\"background\\\": \\\"#111111\\\", \\\"signals\\\": [{\\\"name\\\": \\\"sel\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]}, {\\\"name\\\": \\\"_kf\\\", \\\"value\\\": null, \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"row_bg\\\"}, \\\"update\\\": \\\"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\\\", \\\"force\\\": true}]}], \\\"data\\\": [{\\\"name\\\": \\\"d_fs\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-certificates*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"term\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"d_port\\\", \\\"url\\\": {\\\"index\\\": \\\"tychon-pqc-inventory*\\\", \\\"body\\\": {\\\"size\\\": 0, \\\"query\\\": {\\\"bool\\\": {\\\"must\\\": [{\\\"exists\\\": {\\\"field\\\": \\\"x509.subject.common_name\\\"}}, {\\\"term\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}]}}, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"tychon.type\\\"}}}}}, \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"}, \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value || 0\\\"}]}, {\\\"name\\\": \\\"rows\\\", \\\"values\\\": [{\\\"k\\\": \\\"fs\\\", \\\"ord\\\": 0, \\\"lbl\\\": \\\"File System\\\", \\\"badge\\\": \\\"DISK\\\", \\\"sub\\\": \\\"Certificates read from disk \\\\u2014 PEM/DER files, keystores, application bundles\\\", \\\"desc\\\": \\\"Found by crawling the local filesystem. Source path is known. These certs may not be actively serving traffic \\\\u2014 they could be backups, bundled CA roots, or application trust stores.\\\", \\\"clr\\\": \\\"#448aff\\\", \\\"bg\\\": \\\"#448aff18\\\", \\\"icon\\\": \\\"\\\\u2399\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"filesystem\\\"}}}, {\\\"k\\\": \\\"port\\\", \\\"ord\\\": 1, \\\"lbl\\\": \\\"Port / Network\\\", \\\"badge\\\": \\\"NETWORK\\\", \\\"sub\\\": \\\"Certificates captured live from TLS handshakes on open network ports\\\", \\\"desc\\\": \\\"Captured during an active TLS scan. These certs are definitely in use serving live traffic. Quantum readiness score and cipher suite are also available for these entries.\\\", \\\"clr\\\": \\\"#00c853\\\", \\\"bg\\\": \\\"#00c85318\\\", \\\"icon\\\": \\\"\\\\u26a1\\\", \\\"filt\\\": {\\\"match_phrase\\\": {\\\"tychon.type\\\": \\\"cipher\\\"}}}], \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.k === 'fs' ? (length(data('d_fs'))>0 ? data('d_fs')[0].n : 0) : (length(data('d_port'))>0 ? data('d_port')[0].n : 0)\\\"}, {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"datum.ord * 134 + 52\\\"}]}], \\\"marks\\\": [{\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18}, \\\"text\\\": {\\\"value\\\": \\\"CERTIFICATE SOURCE\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}}}}, {\\\"type\\\": \\\"text\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34}, \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES WERE DISCOVERED \\\\u2014 file scan vs live TLS capture\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rule\\\", \\\"encode\\\": {\\\"enter\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42}, \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"row_bg\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.k === sel ? '#1c1c2e' : '#161616'\\\"}, \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 128}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}}}}, {\\\"type\\\": \\\"rule\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 127\\\"}, \\\"stroke\\\": {\\\"value\\\": \\\"#1e1e1e\\\"}}}}, {\\\"type\\\": \\\"rect\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 10\\\"}, \\\"width\\\": {\\\"value\\\": 56}, \\\"height\\\": {\\\"value\\\": 18}, \\\"cornerRadius\\\": {\\\"value\\\": 2}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.bg : '#1a1a1a'\\\"}, \\\"stroke\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#2a2a2a'\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 42}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 23\\\"}, \\\"text\\\": {\\\"field\\\": \\\"badge\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 78}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 24\\\"}, \\\"text\\\": {\\\"field\\\": \\\"lbl\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? '#e8e8e8' : '#444444'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 14}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 44\\\"}, \\\"text\\\": {\\\"field\\\": \\\"sub\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.82\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#666666\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 64\\\"}, \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.64\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#444444\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 70\\\"}, \\\"text\\\": {\\\"signal\\\": \\\"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n, '.3~s') : format(datum.n, ',')) : '\\\\u2014'\\\"}, \\\"fill\\\": {\\\"signal\\\": \\\"datum.n > 0 ? datum.clr : '#333333'\\\"}, \\\"fontSize\\\": {\\\"value\\\": 32}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}, {\\\"type\\\": \\\"text\\\", \\\"from\\\": {\\\"data\\\": \\\"rows\\\"}, \\\"encode\\\": {\\\"update\\\": {\\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 88\\\"}, \\\"text\\\": {\\\"value\\\": \\\"certificates\\\"}, \\\"fill\\\": {\\\"value\\\": \\\"#3a3a3a\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}}}}]}\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-b5e39d42-af3e-4c1b-c6f8-e2d9a0f12345", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTcsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json deleted file mode 100644 index 699c263f9c2..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" - }, - "title": "PQC Connections Topology", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"PQC Connections Topology\",\"type\":\"vega\",\"aggs\":[],\"params\":{\"spec\":\"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"autosize\\\": \\\"fit\\\",\\n \\\"padding\\\": 8,\\n \\\"background\\\": \\\"#000000\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"zoom\\\",\\n \\\"value\\\": 0.55,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6)\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panX\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panX - (width/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (width/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panX + event.movementX\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"panY\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": { \\\"type\\\": \\\"wheel\\\" },\\n \\\"update\\\": \\\"((panY - (height/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (height/2)\\\"\\n },\\n {\\n \\\"events\\\": {\\n \\\"source\\\": \\\"window\\\",\\n \\\"type\\\": \\\"mousemove\\\",\\n \\\"between\\\": [\\n { \\\"source\\\": \\\"view\\\", \\\"type\\\": \\\"mousedown\\\" },\\n { \\\"source\\\": \\\"window\\\", \\\"type\\\": \\\"mouseup\\\" }\\n ]\\n },\\n \\\"update\\\": \\\"panY + event.movementY\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"selectedNode\\\",\\n \\\"value\\\": null,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:click\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? (selectedNode && selectedNode.id===datum.id ? null : datum) : selectedNode\\\"\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"_applyNodeFilter\\\",\\n \\\"value\\\": 0,\\n \\\"on\\\": [\\n {\\n \\\"events\\\": \\\"@nodeMark:dblclick\\\",\\n \\\"update\\\": \\\"datum && isValid(datum.id) ? kibanaAddFilter((datum.nodeType === 'application' ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'tychon.application.name': toString(datum.id)}}]}} : {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'host.hostname': toString(datum.id)}}]}})) : 0\\\",\\n \\\"force\\\": true\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjPeerIds\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency')) ? pluck(data('adjacency'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"adjPeer2Ids\\\",\\n \\\"update\\\": \\\"isArray(data('adjacency2')) ? pluck(data('adjacency2'), 'peer') : []\\\"\\n },\\n {\\n \\\"name\\\": \\\"highlightNodeIdsCsv\\\",\\n \\\"update\\\": \\\"selectedNode ? (',' + toString(selectedNode.id) + ',' + join(adjPeerIds, ',') + ',' + join(adjPeer2Ids, ',') + ',') : ''\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanX\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cx) ? (width * 0.5) - (data('layout_center')[0].cx * zoom) : (width * (1 - zoom) * 0.5)\\\"\\n },\\n {\\n \\\"name\\\": \\\"autoPanY\\\",\\n \\\"update\\\": \\\"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cy) ? (height * 0.52) - (data('layout_center')[0].cy * zoom) : (height * (1 - zoom) * 0.5)\\\"\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\n \\\"%context%\\\": true,\\n \\\"%timefield%\\\": \\\"@timestamp\\\",\\n \\\"index\\\": \\\"tychon-pqc-applications\\\",\\n \\\"body\\\": {\\n \\\"size\\\": 0,\\n \\\"aggs\\\": {\\n \\\"pairs\\\": {\\n \\\"filter\\\": {\\n \\\"bool\\\": {\\n \\\"must\\\": [\\n { \\\"exists\\\": { \\\"field\\\": \\\"host.hostname\\\" } },\\n { \\\"exists\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } },\\n { \\\"term\\\": { \\\"event.dataset\\\": \\\"tychon.application\\\" } }\\n ]\\n }\\n },\\n \\\"aggs\\\": {\\n \\\"links\\\": {\\n \\\"composite\\\": {\\n \\\"size\\\": 500,\\n \\\"sources\\\": [\\n { \\\"src\\\": { \\\"terms\\\": { \\\"field\\\": \\\"host.hostname\\\" } } },\\n { \\\"dst\\\": { \\\"terms\\\": { \\\"field\\\": \\\"tychon.application.name\\\" } } }\\n ]\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"format\\\": { \\\"property\\\": \\\"aggregations.pairs.links.buckets\\\" },\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"datum.key.src\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"datum.key.dst\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.doc_count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.target) && datum.source!='' && datum.target!=''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"nodes\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"source\\\", \\\"target\\\"], \\\"as\\\": [\\\"side\\\", \\\"id\\\"] },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"id\\\", \\\"side\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"nodeType\\\", \\\"expr\\\": \\\"datum.side==='source' ? 'host' : 'application'\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"source\\\", \\\"expr\\\": \\\"toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"target\\\", \\\"expr\\\": \\\"toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"count\\\", \\\"expr\\\": \\\"toNumber(datum.count)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.source != '' && datum.target != ''\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout\\\",\\n \\\"source\\\": \\\"nodes\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"force\\\",\\n \\\"iterations\\\": 300,\\n \\\"static\\\": true,\\n \\\"forces\\\": [\\n { \\\"force\\\": \\\"center\\\", \\\"x\\\": { \\\"signal\\\": \\\"width * 0.5\\\" }, \\\"y\\\": { \\\"signal\\\": \\\"height * 0.52\\\" } },\\n { \\\"force\\\": \\\"collide\\\", \\\"radius\\\": 20 },\\n { \\\"force\\\": \\\"nbody\\\", \\\"strength\\\": -180 },\\n { \\\"force\\\": \\\"link\\\", \\\"links\\\": \\\"edges\\\", \\\"id\\\": \\\"id\\\", \\\"distance\\\": 130 }\\n ]\\n }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"layout_center\\\",\\n \\\"source\\\": \\\"layout\\\",\\n \\\"transform\\\": [\\n {\\n \\\"type\\\": \\\"aggregate\\\",\\n \\\"ops\\\": [\\\"median\\\", \\\"median\\\"],\\n \\\"fields\\\": [\\\"x\\\", \\\"y\\\"],\\n \\\"as\\\": [\\\"cx\\\", \\\"cy\\\"]\\n },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cx\\\", \\\"expr\\\": \\\"isFinite(datum.cx) ? datum.cx : 0\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"cy\\\", \\\"expr\\\": \\\"isFinite(datum.cy) ? datum.cy : 0\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"edges_draw\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sx\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.x) ? datum.source.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sy\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.y) ? datum.source.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tx\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.x) ? datum.target.x * zoom + autoPanX + panX : null\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"ty\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.y) ? datum.target.y * zoom + autoPanY + panY : null\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"isValid(datum.sx) && isValid(datum.sy) && isValid(datum.tx) && isValid(datum.ty)\\\" }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (datum.srcId===toString(selectedNode.id) || datum.dstId===toString(selectedNode.id))\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id)\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n },\\n {\\n \\\"name\\\": \\\"adjacency2\\\",\\n \\\"source\\\": \\\"edges\\\",\\n \\\"transform\\\": [\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"srcId\\\", \\\"expr\\\": \\\"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\\\" },\\n { \\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"dstId\\\", \\\"expr\\\": \\\"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\\\" },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"selectedNode && (indexof(adjPeerIds, datum.srcId) >= 0 || indexof(adjPeerIds, datum.dstId) >= 0)\\\" },\\n { \\\"type\\\": \\\"fold\\\", \\\"fields\\\": [\\\"srcId\\\", \\\"dstId\\\"], \\\"as\\\": [\\\"side\\\", \\\"peer\\\"] },\\n { \\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.peer !== toString(selectedNode.id) && indexof(adjPeerIds, datum.peer) < 0\\\" },\\n { \\\"type\\\": \\\"aggregate\\\", \\\"groupby\\\": [\\\"peer\\\"], \\\"fields\\\": [\\\"count\\\"], \\\"ops\\\": [\\\"sum\\\"], \\\"as\\\": [\\\"traffic\\\"] }\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"x\\\": { \\\"value\\\": 0 },\\n \\\"y\\\": { \\\"value\\\": 0 },\\n \\\"x2\\\": { \\\"signal\\\": \\\"width\\\" },\\n \\\"y2\\\": { \\\"signal\\\": \\\"height\\\" },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"edges_draw\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"field\\\": \\\"sx\\\" },\\n \\\"y\\\": { \\\"field\\\": \\\"sy\\\" },\\n \\\"x2\\\": { \\\"field\\\": \\\"tx\\\" },\\n \\\"y2\\\": { \\\"field\\\": \\\"ty\\\" },\\n \\\"stroke\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? '#4fc3f7' : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? '#7fe8ff' : '#213240')\\\"\\n },\\n \\\"strokeOpacity\\\": {\\n \\\"signal\\\": \\\"!selectedNode ? 0.42 : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? 0.75 : 0.08)\\\"\\n },\\n \\\"strokeWidth\\\": { \\\"value\\\": 0.9 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#3b2b1a' : '#1a2c3b'\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.9 },\\n \\\"stroke\\\": { \\\"signal\\\": \\\"datum.nodeType==='application' ? '#ffd7a2' : '#a9dbff'\\\" },\\n \\\"strokeWidth\\\": { \\\"value\\\": 1.2 },\\n \\\"opacity\\\": { \\\"signal\\\": \\\"!selectedNode ? 1 : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? 1 : 0.2)\\\" }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"symbol\\\",\\n \\\"name\\\": \\\"nodeMark\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"enter\\\": {\\n \\\"size\\\": { \\\"value\\\": 980 },\\n \\\"fill\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"fillOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"stroke\\\": { \\\"value\\\": \\\"#000000\\\" },\\n \\\"strokeOpacity\\\": { \\\"value\\\": 0.001 },\\n \\\"cursor\\\": { \\\"value\\\": \\\"pointer\\\" }\\n },\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY\\\" },\\n \\\"size\\\": { \\\"value\\\": 980 }\\n }\\n }\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": { \\\"data\\\": \\\"layout\\\" },\\n \\\"encode\\\": {\\n \\\"update\\\": {\\n \\\"x\\\": { \\\"signal\\\": \\\"datum.x * zoom + autoPanX + panX\\\" },\\n \\\"y\\\": { \\\"signal\\\": \\\"datum.y * zoom + autoPanY + panY - 14\\\" },\\n \\\"text\\\": { \\\"field\\\": \\\"id\\\" },\\n \\\"fill\\\": { \\\"signal\\\": \\\"!selectedNode ? '#e0e0e0' : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? '#f2f7ff' : '#4f5f6f')\\\" },\\n \\\"font\\\": { \\\"value\\\": \\\"monospace\\\" },\\n \\\"fontSize\\\": { \\\"value\\\": 9 },\\n \\\"align\\\": { \\\"value\\\": \\\"center\\\" },\\n \\\"baseline\\\": { \\\"value\\\": \\\"bottom\\\" }\\n }\\n }\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-bac83eaf-eacf-4a4b-9fb3-aa102b21a34c", - "managed": false, - "originId": "d12466b5-c1c4-4c03-bd17-295d26285885", - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NjgsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json deleted file mode 100644 index 183fb0f6364..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "CERT OPS \u2014 Signature Algorithm", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\": \"CERT OPS \\u2014 Signature Algorithm\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_sig\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.signature_algorithm\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_sig.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef5350' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef5350' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa726' : datum.key === 'N/A' || datum.key === '0' ? '#555555' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? '#ef535018' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef535018' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff18' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa72618' : '#55555518'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'BROKEN' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? 'LEGACY' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? 'MODERN' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? 'CLASSICAL' : datum.key === 'N/A' || datum.key === '0' ? 'UNKNOWN' : 'PQC READY'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key === 'MD5-RSA' ? 'MD5 collision attacks are trivial \\u2014 critically broken' : datum.key === 'SHA1-RSA' ? 'SHA-1 deprecated \\u2014 browsers reject, fails compliance' : datum.key === 'DSA-SHA1' ? 'DSA with SHA-1 \\u2014 both deprecated, remove immediately' : datum.key === 'SHA256-RSA' ? 'RSA with SHA-256 \\u2014 dominant classical standard' : datum.key === 'SHA384-RSA' ? 'RSA with SHA-384 \\u2014 stronger hash, still quantum-vulnerable' : datum.key === 'SHA512-RSA' ? 'RSA with SHA-512 \\u2014 strongest classical RSA variant' : datum.key === 'ECDSA-SHA256' ? 'ECDSA with SHA-256 \\u2014 modern, efficient, quantum-vulnerable' : datum.key === 'ECDSA-SHA384' ? 'ECDSA with SHA-384 \\u2014 CNSA 1.0 approved, quantum-vulnerable' : 'Signature algorithm'\\\"},\\n {\\\"type\\\": \\\"filter\\\", \\\"expr\\\": \\\"datum.k !== 'N/A' && datum.k !== '0'\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 66 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"SIGNATURE ALGORITHM\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"HOW CERTIFICATES ARE SIGNED \\u2014 click to filter\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 60},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 59\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 20\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.42\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 38\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 6\\\"},\\n \\\"width\\\": {\\\"value\\\": 68}, \\\"height\\\": {\\\"value\\\": 15}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.60 + 34\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 18\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 32\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 47\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-ebdbafa8-2778-4098-b5df-fb2c23665551", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTUsMzBd" -} diff --git a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json b/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json deleted file mode 100644 index 5cc4134b682..00000000000 --- a/packages/tychon_quantum_command/kibana/visualization/tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" - }, - "title": "CERT OPS \u2014 Key Size Distribution", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\": \"CERT OPS \\u2014 Key Size Distribution\", \"type\": \"vega\", \"aggs\": [], \"params\": {\"spec\": \"{\\n \\\"$schema\\\": \\\"https://vega.github.io/schema/vega/v5.json\\\",\\n \\\"padding\\\": {\\\"top\\\": 0, \\\"bottom\\\": 0, \\\"left\\\": 0, \\\"right\\\": 0},\\n \\\"background\\\": \\\"#111111\\\",\\n \\\"signals\\\": [\\n {\\n \\\"name\\\": \\\"sel\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? null : datum.k\\\", \\\"force\\\": true}]\\n },\\n {\\n \\\"name\\\": \\\"_kf\\\", \\\"value\\\": null,\\n \\\"on\\\": [{\\\"events\\\": {\\\"type\\\": \\\"click\\\", \\\"markname\\\": \\\"bg\\\"}, \\\"update\\\": \\\"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}})\\\", \\\"force\\\": true}]\\n }\\n ],\\n \\\"data\\\": [\\n {\\n \\\"name\\\": \\\"raw\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\n \\\"by_size\\\": {\\\"terms\\\": {\\\"field\\\": \\\"certificate.subject_public_key_info.bit_size\\\", \\\"size\\\": 15, \\\"order\\\": {\\\"_count\\\": \\\"desc\\\"}}},\\n \\\"total\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}\\n }}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.by_size.buckets\\\"},\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"sz\\\", \\\"expr\\\": \\\"datum.key\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"k\\\", \\\"expr\\\": \\\"toString(datum.key) + '-bit'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.doc_count\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"clr\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef5350' : datum.key <= 2048 ? '#ffa726' : datum.key <= 3072 ? '#448aff' : '#00c853'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"bg\\\", \\\"expr\\\": \\\"datum.key <= 1024 ? '#ef535018' : datum.key <= 2048 ? '#ffa72618' : datum.key <= 3072 ? '#448aff18' : '#00c85318'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tier\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'CRITICAL' : datum.key <= 1024 ? 'WEAK' : datum.key <= 2048 ? 'CLASSICAL' : datum.key <= 3072 ? 'STRONG' : 'CNSA 2.0'\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"desc\\\",\\\"expr\\\": \\\"datum.key <= 512 ? 'Trivially breakable \\u2014 remove immediately' : datum.key <= 1024 ? 'Below NIST minimum \\u2014 must be replaced' : datum.key === 2048 ? 'RSA-2048 / ECDSA-P256 \\u2014 classical standard, quantum-vulnerable' : datum.key === 3072 ? 'RSA-3072 \\u2014 transitional strength, quantum-vulnerable' : datum.key === 4096 ? 'RSA-4096 \\u2014 strong classical, quantum-vulnerable' : datum.key === 256 ? 'ECDSA-P256 \\u2014 modern elliptic curve' : datum.key === 384 ? 'ECDSA-P384 \\u2014 strong elliptic curve (CNSA 1.0)' : 'Key size ' + datum.key\\\"},\\n {\\\"type\\\": \\\"collect\\\", \\\"sort\\\": {\\\"field\\\": \\\"n\\\", \\\"order\\\": \\\"descending\\\"}},\\n {\\\"type\\\": \\\"window\\\", \\\"ops\\\": [\\\"rank\\\"], \\\"as\\\": [\\\"rnk\\\"]},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"y\\\", \\\"expr\\\": \\\"(datum.rnk - 1) * 70 + 52\\\"}\\n ]\\n },\\n {\\n \\\"name\\\": \\\"tot\\\",\\n \\\"url\\\": {\\\"%context%\\\": true, \\\"%timefield%\\\": \\\"@timestamp\\\", \\\"index\\\": \\\"tychon-pqc-certificates*\\\",\\n \\\"body\\\": {\\\"size\\\": 0, \\\"aggs\\\": {\\\"v\\\": {\\\"value_count\\\": {\\\"field\\\": \\\"id\\\"}}}}},\\n \\\"format\\\": {\\\"property\\\": \\\"aggregations.v\\\"},\\n \\\"transform\\\": [{\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"n\\\", \\\"expr\\\": \\\"datum.value\\\"}]\\n },\\n {\\n \\\"name\\\": \\\"mx\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [{\\\"type\\\": \\\"aggregate\\\", \\\"ops\\\": [\\\"max\\\"], \\\"fields\\\": [\\\"n\\\"], \\\"as\\\": [\\\"v\\\"]}]\\n },\\n {\\n \\\"name\\\": \\\"rows\\\",\\n \\\"source\\\": \\\"raw\\\",\\n \\\"transform\\\": [\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"tot\\\", \\\"expr\\\": \\\"length(data('tot'))>0 ? data('tot')[0].n : 1\\\"},\\n {\\\"type\\\": \\\"formula\\\", \\\"as\\\": \\\"pct\\\", \\\"expr\\\": \\\"datum.tot > 0 ? datum.n / datum.tot : 0\\\"}\\n ]\\n }\\n ],\\n \\\"marks\\\": [\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 18},\\n \\\"text\\\": {\\\"value\\\": \\\"KEY SIZE DISTRIBUTION\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#cccccc\\\"}, \\\"fontSize\\\": {\\\"value\\\": 10}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1.5}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"value\\\": 34},\\n \\\"text\\\": {\\\"value\\\": \\\"BIT STRENGTH \\u2014 click to filter \\u00b7 CNSA 2.0 requires RSA \\u22653072 or ECDSA P-384\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"encode\\\": {\\\"enter\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"value\\\": 42},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#252525\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\", \\\"name\\\": \\\"bg\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? '#1c1c2e' : '#161616'\\\"},\\n \\\"cursor\\\": {\\\"value\\\": \\\"pointer\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"y\\\": {\\\"field\\\": \\\"y\\\"}, \\\"width\\\": {\\\"value\\\": 4}, \\\"height\\\": {\\\"value\\\": 64},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rule\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 0}, \\\"x2\\\": {\\\"signal\\\": \\\"width\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 63\\\"},\\n \\\"stroke\\\": {\\\"value\\\": \\\"#222222\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 22\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"k\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#e8e8e8\\\"}, \\\"fontSize\\\": {\\\"value\\\": 13}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"value\\\": 14}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 40\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"desc\\\"}, \\\"limit\\\": {\\\"signal\\\": \\\"width * 0.55\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9}, \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 7\\\"},\\n \\\"width\\\": {\\\"value\\\": 64}, \\\"height\\\": {\\\"value\\\": 16}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"field\\\": \\\"bg\\\"},\\n \\\"stroke\\\": {\\\"field\\\": \\\"clr\\\"}, \\\"strokeWidth\\\": {\\\"value\\\": 1}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58 + 32\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 19\\\"},\\n \\\"text\\\": {\\\"field\\\": \\\"tier\\\"},\\n \\\"fill\\\": {\\\"field\\\": \\\"clr\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 8}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"center\\\"}, \\\"letterSpacing\\\": {\\\"value\\\": 0.8}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"rect\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width * 0.58\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 27\\\"},\\n \\\"width\\\": {\\\"signal\\\": \\\"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 64 : 0\\\"},\\n \\\"height\\\": {\\\"value\\\": 12}, \\\"cornerRadius\\\": {\\\"value\\\": 2},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.clr + '55'\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 36\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\\\"},\\n \\\"fill\\\": {\\\"signal\\\": \\\"datum.k===sel ? datum.clr : '#dddddd'\\\"},\\n \\\"fontSize\\\": {\\\"value\\\": 18}, \\\"fontWeight\\\": {\\\"value\\\": \\\"bold\\\"},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n },\\n {\\n \\\"type\\\": \\\"text\\\",\\n \\\"from\\\": {\\\"data\\\": \\\"rows\\\"},\\n \\\"encode\\\": {\\\"update\\\": {\\n \\\"x\\\": {\\\"signal\\\": \\\"width - 10\\\"}, \\\"y\\\": {\\\"signal\\\": \\\"datum.y + 50\\\"},\\n \\\"text\\\": {\\\"signal\\\": \\\"format(datum.pct * 100, '.1f') + '%'\\\"},\\n \\\"fill\\\": {\\\"value\\\": \\\"#555555\\\"}, \\\"fontSize\\\": {\\\"value\\\": 9},\\n \\\"font\\\": {\\\"value\\\": \\\"monospace\\\"}, \\\"align\\\": {\\\"value\\\": \\\"right\\\"}\\n }}\\n }\\n ]\\n}\\n\"}}" - }, - "coreMigrationVersion": "8.8.0", - "created_at": "2026-06-11T16:06:12.868Z", - "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "id": "tychon_quantum_command-f3ff9cb1-3edd-41fd-904d-0b24808fe130", - "managed": false, - "references": [], - "type": "visualization", - "typeMigrationVersion": "8.5.0", - "updated_at": "2026-06-11T16:06:12.868Z", - "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", - "version": "WzY1NTQsMzBd" -} From 0af5250e33435f98c1ca544825e076a49d030459 Mon Sep 17 00:00:00 2001 From: Thomas Hatcher Date: Thu, 23 Jul 2026 18:06:12 +0000 Subject: [PATCH 6/6] Fix Vega dashboard filter logic, empty states, and certificate source query handling Expanded summary: - Correct inverted Vega filter-toggle ternaries so selected rows remove filters and unselected rows add them. - Add consistent empty-state indicators to Vega query panels. - Add missing time bindings to certificate dashboard Vega queries, using Kibana-compatible dashboard context where explicit queries are required. - Fix Certificate Source Type panel by replacing invalid %context% + body.query usage with dashboard context placeholders and %timefilter%. - Add a topology truncation warning for the 500-relationship composite bucket limit. - Add regression tests covering Vega toggle behavior, time binding presence, empty-state indicators, and topology truncation disclosure. - Updated .github/CODEOWNERS and manifest.yml with correct owners. - Removed LICENSE.txt and sample_event.json. --- .github/CODEOWNERS | 1 + packages/tychon_quantum_command/LICENSE.txt | 93 ------------------- ...-4ea4-8458-7c8a8b58987e-cost-analysis.json | 14 +-- ...0d80-4a28-9de7-55b2046f7c45-inventory.json | 26 +++--- ...-b0b9-c675dd057e2f-application-report.json | 12 +-- ...-9410-7d8c01ff0d9a-application-detail.json | 8 +- ...ea1b-application-connections-topology.json | 14 +-- ...3982-certificate-operations-dashboard.json | 28 +++--- packages/tychon_quantum_command/manifest.yml | 2 +- .../tychon_quantum_command/sample_event.json | 37 -------- 10 files changed, 53 insertions(+), 182 deletions(-) delete mode 100644 packages/tychon_quantum_command/LICENSE.txt delete mode 100644 packages/tychon_quantum_command/sample_event.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5784ed08f27..a780f536e55 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -591,6 +591,7 @@ /packages/trend_micro_vision_one @elastic/security-service-integrations @elastic/sit-crest-contractors /packages/trendmicro @elastic/security-service-integrations @elastic/sit-crest-contractors /packages/tychon @elastic/security-service-integrations @elastic/sit-crest-contractors +/packages/tychon_quantum_command @elastic/security-service-integrations @elastic/sit-crest-contractors /packages/udp @elastic/integration-experience /packages/unifiedlogs @elastic/sec-windows-platform /packages/universal_profiling_agent @elastic/ingest-otel-data diff --git a/packages/tychon_quantum_command/LICENSE.txt b/packages/tychon_quantum_command/LICENSE.txt deleted file mode 100644 index 809108b857f..00000000000 --- a/packages/tychon_quantum_command/LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Elastic License 2.0 - -URL: https://www.elastic.co/licensing/elastic-license - -## Acceptance - -By using the software, you agree to all of the terms and conditions below. - -## Copyright License - -The licensor grants you a non-exclusive, royalty-free, worldwide, -non-sublicensable, non-transferable license to use, copy, distribute, make -available, and prepare derivative works of the software, in each case subject to -the limitations and conditions below. - -## Limitations - -You may not provide the software to third parties as a hosted or managed -service, where the service provides users with access to any substantial set of -the features or functionality of the software. - -You may not move, change, disable, or circumvent the license key functionality -in the software, and you may not remove or obscure any functionality in the -software that is protected by the license key. - -You may not alter, remove, or obscure any licensing, copyright, or other notices -of the licensor in the software. Any use of the licensor’s trademarks is subject -to applicable law. - -## Patents - -The licensor grants you a license, under any patent claims the licensor can -license, or becomes able to license, to make, have made, use, sell, offer for -sale, import and have imported the software, in each case subject to the -limitations and conditions in this license. This license does not cover any -patent claims that you cause to be infringed by modifications or additions to -the software. If you or your company make any written claim that the software -infringes or contributes to infringement of any patent, your patent license for -the software granted under these terms ends immediately. If your company makes -such a claim, your patent license ends immediately for work on behalf of your -company. - -## Notices - -You must ensure that anyone who gets a copy of any part of the software from you -also gets a copy of these terms. - -If you modify the software, you must include in any modified copies of the -software prominent notices stating that you have modified the software. - -## No Other Rights - -These terms do not imply any licenses other than those expressly granted in -these terms. - -## Termination - -If you use the software in violation of these terms, such use is not licensed, -and your licenses will automatically terminate. If the licensor provides you -with a notice of your violation, and you cease all violation of this license no -later than 30 days after you receive that notice, your licenses will be -reinstated retroactively. However, if you violate these terms after such -reinstatement, any additional violation of these terms will cause your licenses -to terminate automatically and permanently. - -## No Liability - -*As far as the law allows, the software comes as is, without any warranty or -condition, and the licensor will not be liable to you for any damages arising -out of these terms or the use or nature of the software, under any kind of -legal claim.* - -## Definitions - -The **licensor** is the entity offering these terms, and the **software** is the -software the licensor makes available under these terms, including any portion -of it. - -**you** refers to the individual or entity agreeing to these terms. - -**your company** is any legal entity, sole proprietorship, or other kind of -organization that you work for, plus all organizations that have control over, -are under the control of, or are under common control with that -organization. **control** means ownership of substantially all the assets of an -entity, or the power to direct its management and policies by vote, contract, or -otherwise. Control can be direct or indirect. - -**your licenses** are all the licenses granted to you for the software under -these terms. - -**use** means anything you do with the software requiring one of your licenses. - -**trademark** means trademarks, service marks, and similar rights. diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json index 5e796d85e7e..8cae8b4290a 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis.json @@ -105,7 +105,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Upgrade Cost Analysis — Responsive KPI header: unified top card with accent stripe, three cost-breakdown tiles, and proportional composition bar. Reads pre-computed fields from tychon-pqc-system-readiness*. No cost arithmetic in Vega.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 16, \"right\": 16, \"top\": 16, \"bottom\": 16 },\n \"data\": [\n {\n \"name\": \"cost_totals\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"agg_labor_hours\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_labor_hours\" } },\n \"agg_total_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } },\n \"agg_labor_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_labor_cost_usd\" } },\n \"agg_hw_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_hardware_cost_usd\" } },\n \"agg_lic_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_license_cost_usd\" } },\n \"agg_asset_count\": { \"value_count\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"labor_hours\", \"expr\": \"isValid(datum.agg_labor_hours) ? datum.agg_labor_hours.value : 0\" },\n { \"type\": \"formula\", \"as\": \"total_cost\", \"expr\": \"isValid(datum.agg_total_cost) ? datum.agg_total_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"labor_cost\", \"expr\": \"isValid(datum.agg_labor_cost) ? datum.agg_labor_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"hw_cost\", \"expr\": \"isValid(datum.agg_hw_cost) ? datum.agg_hw_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"lic_cost\", \"expr\": \"isValid(datum.agg_lic_cost) ? datum.agg_lic_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"asset_count\", \"expr\": \"isValid(datum.agg_asset_count) ? datum.agg_asset_count.value : 0\" }\n ]\n }\n ],\n \"signals\": [\n { \"name\": \"gap\", \"value\": 12 },\n { \"name\": \"topH\", \"value\": 124 },\n { \"name\": \"midH\", \"value\": 88 },\n { \"name\": \"midY\", \"update\": \"topH + gap\" },\n { \"name\": \"cw\", \"update\": \"(width - gap * 2) / 3\" },\n { \"name\": \"c2x\", \"update\": \"cw + gap\" },\n { \"name\": \"c3x\", \"update\": \"(cw + gap) * 2\" },\n { \"name\": \"div1x\", \"update\": \"width / 3\" },\n { \"name\": \"div2x\", \"update\": \"width * 2 / 3\" },\n {\n \"name\": \"r\",\n \"update\": \"length(data('cost_totals')) \u003e 0 ? data('cost_totals')[0] : {total_cost:0,labor_hours:0,labor_cost:0,hw_cost:0,lic_cost:0,asset_count:0}\"\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"value\": 0 },\n \"width\": { \"signal\": \"width\" }, \"height\": { \"signal\": \"topH\" },\n \"fill\": { \"value\": \"#f8faff\" },\n \"stroke\": { \"value\": \"#dbeafe\" }, \"strokeWidth\": { \"value\": 1.5 },\n \"cornerRadius\": { \"value\": 10 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"value\": 0 },\n \"width\": { \"signal\": \"width\" }, \"height\": { \"value\": 4 },\n \"fill\": { \"value\": \"#3b82f6\" },\n \"cornerRadiusTopLeft\": { \"value\": 10 }, \"cornerRadiusTopRight\": { \"value\": 10 }\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x\" }, \"y\": { \"value\": 18 },\n \"x2\": { \"signal\": \"div1x\" }, \"y2\": { \"signal\": \"topH - 18\" },\n \"stroke\": { \"value\": \"#e2e8f0\" }, \"strokeWidth\": { \"value\": 1 }\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div2x\" }, \"y\": { \"value\": 18 },\n \"x2\": { \"signal\": \"div2x\" }, \"y2\": { \"signal\": \"topH - 18\" },\n \"stroke\": { \"value\": \"#e2e8f0\" }, \"strokeWidth\": { \"value\": 1 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x / 2\" }, \"y\": { \"signal\": \"topH * 0.40\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 38 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#1d4ed8\" },\n \"text\": { \"signal\": \"'$' + format(r.total_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x / 2\" }, \"y\": { \"signal\": \"topH * 0.65\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 12 }, \"fill\": { \"value\": \"#64748b\" },\n \"text\": { \"value\": \"Total Upgrade Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x / 2\" }, \"y\": { \"signal\": \"topH * 0.85\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#94a3b8\" },\n \"text\": { \"signal\": \"r.asset_count \u003e 0 ? '$' + format(r.total_cost / r.asset_count, ',.0f') + ' per asset' : ''\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x + (div2x - div1x) / 2\" }, \"y\": { \"signal\": \"topH * 0.40\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 34 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#047857\" },\n \"text\": { \"signal\": \"format(r.labor_hours, ',.1f') + ' h'\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x + (div2x - div1x) / 2\" }, \"y\": { \"signal\": \"topH * 0.65\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 12 }, \"fill\": { \"value\": \"#64748b\" },\n \"text\": { \"value\": \"Total Labor Hours\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div1x + (div2x - div1x) / 2\" }, \"y\": { \"signal\": \"topH * 0.85\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#94a3b8\" },\n \"text\": { \"signal\": \"r.asset_count \u003e 0 ? format(r.labor_hours / r.asset_count, '.1f') + ' h per asset' : ''\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div2x + (width - div2x) / 2\" }, \"y\": { \"signal\": \"topH * 0.40\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 34 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#7e22ce\" },\n \"text\": { \"signal\": \"format(r.asset_count, ',')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"div2x + (width - div2x) / 2\" }, \"y\": { \"signal\": \"topH * 0.65\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 12 }, \"fill\": { \"value\": \"#64748b\" },\n \"text\": { \"value\": \"Assets Requiring Upgrade\" }\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"signal\": \"cw\" }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#eff6ff\" }, \"stroke\": { \"value\": \"#bfdbfe\" },\n \"strokeWidth\": { \"value\": 1 }, \"cornerRadius\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"value\": 0 }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"value\": 5 }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#3b82f6\" },\n \"cornerRadiusTopLeft\": { \"value\": 8 }, \"cornerRadiusBottomLeft\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.34\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 26 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#1d4ed8\" },\n \"text\": { \"signal\": \"'$' + format(r.labor_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.58\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 11 }, \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"value\": \"Labor Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.78\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#9ca3af\" },\n \"text\": { \"signal\": \"r.total_cost \u003e 0 ? format(r.labor_cost / r.total_cost * 100, '.0f') + '% of total' : ''\" }\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"signal\": \"cw\" }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#fff1f2\" }, \"stroke\": { \"value\": \"#fca5a5\" },\n \"strokeWidth\": { \"value\": 1 }, \"cornerRadius\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"value\": 5 }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#ef4444\" },\n \"cornerRadiusTopLeft\": { \"value\": 8 }, \"cornerRadiusBottomLeft\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.34\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 26 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#b91c1c\" },\n \"text\": { \"signal\": \"'$' + format(r.hw_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.58\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 11 }, \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"value\": \"Hardware Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c2x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.78\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#9ca3af\" },\n \"text\": { \"signal\": \"r.total_cost \u003e 0 ? format(r.hw_cost / r.total_cost * 100, '.0f') + '% of total' : ''\" }\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"signal\": \"cw\" }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#fffbeb\" }, \"stroke\": { \"value\": \"#fcd34d\" },\n \"strokeWidth\": { \"value\": 1 }, \"cornerRadius\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x\" }, \"y\": { \"signal\": \"midY\" },\n \"width\": { \"value\": 5 }, \"height\": { \"signal\": \"midH\" },\n \"fill\": { \"value\": \"#f59e0b\" },\n \"cornerRadiusTopLeft\": { \"value\": 8 }, \"cornerRadiusBottomLeft\": { \"value\": 8 }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.34\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 26 }, \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#b45309\" },\n \"text\": { \"signal\": \"'$' + format(r.lic_cost, ',.0f')\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.58\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 11 }, \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"value\": \"License / Software Cost\" }\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": { \"enter\": {\n \"x\": { \"signal\": \"c3x + cw / 2\" }, \"y\": { \"signal\": \"midY + midH * 0.78\" },\n \"align\": { \"value\": \"center\" }, \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 10 }, \"fill\": { \"value\": \"#9ca3af\" },\n \"text\": { \"signal\": \"r.total_cost \u003e 0 ? format(r.lic_cost / r.total_cost * 100, '.0f') + '% of total' : ''\" }\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"PQC Upgrade Cost Analysis \\u2014 Responsive KPI header: unified top card with accent stripe, three cost-breakdown tiles, and proportional composition bar. Reads pre-computed fields from tychon-pqc-system-readiness*. No cost arithmetic in Vega.\", \"autosize\": {\"type\": \"fit\", \"contains\": \"padding\"}, \"padding\": {\"left\": 16, \"right\": 16, \"top\": 16, \"bottom\": 16}, \"data\": [{\"name\": \"cost_totals\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-system-readiness*\", \"body\": {\"size\": 0, \"aggs\": {\"agg_labor_hours\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_labor_hours\"}}, \"agg_total_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_cost_usd\"}}, \"agg_labor_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_labor_cost_usd\"}}, \"agg_hw_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_hardware_cost_usd\"}}, \"agg_lic_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_license_cost_usd\"}}, \"agg_asset_count\": {\"value_count\": {\"field\": \"quantum_readiness.cost_analysis.total_cost_usd\"}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"labor_hours\", \"expr\": \"isValid(datum.agg_labor_hours) ? datum.agg_labor_hours.value : 0\"}, {\"type\": \"formula\", \"as\": \"total_cost\", \"expr\": \"isValid(datum.agg_total_cost) ? datum.agg_total_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"labor_cost\", \"expr\": \"isValid(datum.agg_labor_cost) ? datum.agg_labor_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"hw_cost\", \"expr\": \"isValid(datum.agg_hw_cost) ? datum.agg_hw_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"lic_cost\", \"expr\": \"isValid(datum.agg_lic_cost) ? datum.agg_lic_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"asset_count\", \"expr\": \"isValid(datum.agg_asset_count) ? datum.agg_asset_count.value : 0\"}]}], \"signals\": [{\"name\": \"gap\", \"value\": 12}, {\"name\": \"topH\", \"value\": 124}, {\"name\": \"midH\", \"value\": 88}, {\"name\": \"midY\", \"update\": \"topH + gap\"}, {\"name\": \"cw\", \"update\": \"(width - gap * 2) / 3\"}, {\"name\": \"c2x\", \"update\": \"cw + gap\"}, {\"name\": \"c3x\", \"update\": \"(cw + gap) * 2\"}, {\"name\": \"div1x\", \"update\": \"width / 3\"}, {\"name\": \"div2x\", \"update\": \"width * 2 / 3\"}, {\"name\": \"r\", \"update\": \"length(data('cost_totals')) > 0 ? data('cost_totals')[0] : {total_cost:0,labor_hours:0,labor_cost:0,hw_cost:0,lic_cost:0,asset_count:0}\"}], \"marks\": [{\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 0}, \"width\": {\"signal\": \"width\"}, \"height\": {\"signal\": \"topH\"}, \"fill\": {\"value\": \"#f8faff\"}, \"stroke\": {\"value\": \"#dbeafe\"}, \"strokeWidth\": {\"value\": 1.5}, \"cornerRadius\": {\"value\": 10}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 0}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 4}, \"fill\": {\"value\": \"#3b82f6\"}, \"cornerRadiusTopLeft\": {\"value\": 10}, \"cornerRadiusTopRight\": {\"value\": 10}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div1x\"}, \"y\": {\"value\": 18}, \"x2\": {\"signal\": \"div1x\"}, \"y2\": {\"signal\": \"topH - 18\"}, \"stroke\": {\"value\": \"#e2e8f0\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div2x\"}, \"y\": {\"value\": 18}, \"x2\": {\"signal\": \"div2x\"}, \"y2\": {\"signal\": \"topH - 18\"}, \"stroke\": {\"value\": \"#e2e8f0\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div1x / 2\"}, \"y\": {\"signal\": \"topH * 0.40\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 38}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#1d4ed8\"}, \"text\": {\"signal\": \"'$' + format(r.total_cost, ',.0f')\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div1x / 2\"}, \"y\": {\"signal\": \"topH * 0.65\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 12}, \"fill\": {\"value\": \"#64748b\"}, \"text\": {\"value\": \"Total Upgrade Cost\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div1x / 2\"}, \"y\": {\"signal\": \"topH * 0.85\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"value\": \"#94a3b8\"}, \"text\": {\"signal\": \"r.asset_count > 0 ? '$' + format(r.total_cost / r.asset_count, ',.0f') + ' per asset' : ''\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div1x + (div2x - div1x) / 2\"}, \"y\": {\"signal\": \"topH * 0.40\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 34}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#047857\"}, \"text\": {\"signal\": \"format(r.labor_hours, ',.1f') + ' h'\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div1x + (div2x - div1x) / 2\"}, \"y\": {\"signal\": \"topH * 0.65\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 12}, \"fill\": {\"value\": \"#64748b\"}, \"text\": {\"value\": \"Total Labor Hours\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div1x + (div2x - div1x) / 2\"}, \"y\": {\"signal\": \"topH * 0.85\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"value\": \"#94a3b8\"}, \"text\": {\"signal\": \"r.asset_count > 0 ? format(r.labor_hours / r.asset_count, '.1f') + ' h per asset' : ''\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div2x + (width - div2x) / 2\"}, \"y\": {\"signal\": \"topH * 0.40\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 34}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#7e22ce\"}, \"text\": {\"signal\": \"format(r.asset_count, ',')\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"div2x + (width - div2x) / 2\"}, \"y\": {\"signal\": \"topH * 0.65\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 12}, \"fill\": {\"value\": \"#64748b\"}, \"text\": {\"value\": \"Assets Requiring Upgrade\"}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"y\": {\"signal\": \"midY\"}, \"width\": {\"signal\": \"cw\"}, \"height\": {\"signal\": \"midH\"}, \"fill\": {\"value\": \"#eff6ff\"}, \"stroke\": {\"value\": \"#bfdbfe\"}, \"strokeWidth\": {\"value\": 1}, \"cornerRadius\": {\"value\": 8}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"y\": {\"signal\": \"midY\"}, \"width\": {\"value\": 5}, \"height\": {\"signal\": \"midH\"}, \"fill\": {\"value\": \"#3b82f6\"}, \"cornerRadiusTopLeft\": {\"value\": 8}, \"cornerRadiusBottomLeft\": {\"value\": 8}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.34\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 26}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#1d4ed8\"}, \"text\": {\"signal\": \"'$' + format(r.labor_cost, ',.0f')\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.58\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 11}, \"fill\": {\"value\": \"#374151\"}, \"text\": {\"value\": \"Labor Cost\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.78\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"value\": \"#9ca3af\"}, \"text\": {\"signal\": \"r.total_cost > 0 ? format(r.labor_cost / r.total_cost * 100, '.0f') + '% of total' : ''\"}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c2x\"}, \"y\": {\"signal\": \"midY\"}, \"width\": {\"signal\": \"cw\"}, \"height\": {\"signal\": \"midH\"}, \"fill\": {\"value\": \"#fff1f2\"}, \"stroke\": {\"value\": \"#fca5a5\"}, \"strokeWidth\": {\"value\": 1}, \"cornerRadius\": {\"value\": 8}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c2x\"}, \"y\": {\"signal\": \"midY\"}, \"width\": {\"value\": 5}, \"height\": {\"signal\": \"midH\"}, \"fill\": {\"value\": \"#ef4444\"}, \"cornerRadiusTopLeft\": {\"value\": 8}, \"cornerRadiusBottomLeft\": {\"value\": 8}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c2x + cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.34\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 26}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#b91c1c\"}, \"text\": {\"signal\": \"'$' + format(r.hw_cost, ',.0f')\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c2x + cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.58\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 11}, \"fill\": {\"value\": \"#374151\"}, \"text\": {\"value\": \"Hardware Cost\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c2x + cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.78\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"value\": \"#9ca3af\"}, \"text\": {\"signal\": \"r.total_cost > 0 ? format(r.hw_cost / r.total_cost * 100, '.0f') + '% of total' : ''\"}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c3x\"}, \"y\": {\"signal\": \"midY\"}, \"width\": {\"signal\": \"cw\"}, \"height\": {\"signal\": \"midH\"}, \"fill\": {\"value\": \"#fffbeb\"}, \"stroke\": {\"value\": \"#fcd34d\"}, \"strokeWidth\": {\"value\": 1}, \"cornerRadius\": {\"value\": 8}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c3x\"}, \"y\": {\"signal\": \"midY\"}, \"width\": {\"value\": 5}, \"height\": {\"signal\": \"midH\"}, \"fill\": {\"value\": \"#f59e0b\"}, \"cornerRadiusTopLeft\": {\"value\": 8}, \"cornerRadiusBottomLeft\": {\"value\": 8}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c3x + cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.34\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 26}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#b45309\"}, \"text\": {\"signal\": \"'$' + format(r.lic_cost, ',.0f')\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c3x + cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.58\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 11}, \"fill\": {\"value\": \"#374151\"}, \"text\": {\"value\": \"License / Software Cost\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"c3x + cw / 2\"}, \"y\": {\"signal\": \"midY + midH * 0.78\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"value\": \"#9ca3af\"}, \"text\": {\"signal\": \"r.total_cost > 0 ? format(r.lic_cost / r.total_cost * 100, '.0f') + '% of total' : ''\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('cost_totals')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('cost_totals')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -159,7 +159,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Upgrade Cost — OS Category cost estimates ranked list. Reads pre-computed total_cost_usd per OS category from tychon-pqc-system-readiness*. Styled to match the main OS breakdown panel. No cost arithmetic in Vega.\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.os_category === sel ? null : datum.os_category\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.os_category === sel ? kibanaRemoveFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}}) : kibanaAddFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"os_costs\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"qa_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment\" } },\n \"aggs\": {\n \"categories\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.os_category\",\n \"size\": 30,\n \"order\": { \"cost_sum\": \"desc\" }\n },\n \"aggs\": {\n \"cost_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_total_cost_usd\" } },\n \"hours_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_labor_hours\" } },\n \"license_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_license_cost_usd\" } },\n \"hw_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_hardware_cost_usd\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.os_tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\", \"as\": \"buckets\",\n \"expr\": \"isValid(datum.qa_only) \u0026\u0026 isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\"\n },\n { \"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"] },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.item) \u0026\u0026 isValid(datum.item.key)\" },\n { \"type\": \"formula\", \"as\": \"os_category\", \"expr\": \"datum.item.key\" },\n { \"type\": \"formula\", \"as\": \"total_cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"labor_hours\", \"expr\": \"isValid(datum.item.hours_sum) ? datum.item.hours_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"license_cost\", \"expr\": \"isValid(datum.item.license_sum) ? datum.item.license_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"hw_cost\", \"expr\": \"isValid(datum.item.hw_sum) ? datum.item.hw_sum.value : 0\" },\n {\n \"type\": \"formula\", \"as\": \"tier\",\n \"expr\": \"isValid(datum.item.tier_terms) \u0026\u0026 datum.item.tier_terms.buckets.length \u003e 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n {\n \"type\": \"formula\", \"as\": \"clr\",\n \"expr\": \"datum.total_cost === 0 ? '#66bb6a' : datum.tier === 'LEGACY' ? '#ef5350' : datum.tier === 'CLASSICAL' ? '#ffa726' : '#448aff'\"\n },\n {\n \"type\": \"formula\", \"as\": \"bgclr\",\n \"expr\": \"datum.total_cost === 0 ? '#66bb6a18' : datum.tier === 'LEGACY' ? '#ef535018' : datum.tier === 'CLASSICAL' ? '#ffa72618' : '#448aff18'\"\n }\n ]\n },\n {\n \"name\": \"mx\",\n \"source\": \"os_costs\",\n \"transform\": [\n { \"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"total_cost\"], \"as\": [\"v\"] }\n ]\n }\n ],\n \"scales\": [\n {\n \"name\": \"yscale\",\n \"type\": \"band\",\n \"domain\": { \"data\": \"os_costs\", \"field\": \"os_category\", \"sort\": false },\n \"range\": { \"step\": 72 },\n \"paddingInner\": 0,\n \"paddingOuter\": 0\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"OS UPGRADE COST ESTIMATE\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 38},\n \"text\": {\"value\": \"TOTAL COST BY OS CATEGORY — sorted by cost desc\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 48},\n \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.os_category === sel ? '#1c1c2e' : datum.total_cost === 0 ? '#121a12' : '#161622'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 48},\n \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 4}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 110},\n \"width\": {\"signal\": \"length(data('mx')) \u003e 0 \u0026\u0026 data('mx')[0].v \u003e 0 ? max((datum.total_cost / data('mx')[0].v) * (width - 4), 0) : 0\"},\n \"height\": {\"value\": 4},\n \"fill\": {\"field\": \"clr\"},\n \"opacity\": {\"value\": 0.35}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"},\n \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 113},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 72},\n \"text\": {\"field\": \"os_category\"},\n \"limit\": {\"signal\": \"width * 0.58 - 18\"},\n \"fill\": {\"value\": \"#e8e8e8\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 92},\n \"text\": {\"signal\": \"format(datum.labor_hours, ',.1f') + ' labor hrs | $' + format(datum.license_cost, ',.0f') + ' license | $' + format(datum.hw_cost, ',.0f') + ' hardware'\"},\n \"limit\": {\"signal\": \"width * 0.58 - 18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 56},\n \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"field\": \"bgclr\"},\n \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62 + 41\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 68},\n \"text\": {\"field\": \"tier\"},\n \"fill\": {\"field\": \"clr\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 79},\n \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#333333\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.62 + 41\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 91},\n \"text\": {\"signal\": \"datum.os_category === sel ? 'SELECTED' : ''\"},\n \"fill\": {\"signal\": \"datum.os_category === sel ? datum.clr : '#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"os_costs\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 84},\n \"text\": {\"signal\": \"datum.total_cost \u003e= 1e6 ? '$' + format(datum.total_cost / 1e6, ',.2~f') + 'M' : datum.total_cost \u003e= 1e3 ? '$' + format(datum.total_cost / 1e3, ',.1~f') + 'k' : '$' + format(datum.total_cost, ',')\"},\n \"fill\": {\"signal\": \"datum.os_category === sel ? datum.clr : datum.total_cost \u003e 0 ? '#dddddd' : '#66bb6a'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height - 8\"},\n \"text\": {\"value\": \"↑ highest cost at top\"},\n \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 100},\n \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'NO OS UPGRADE COSTS IN SELECTED TIME RANGE' : ''\"},\n \"fill\": {\"value\": \"#333333\"}, \"fontSize\": {\"value\": 11},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"},\n \"fontWeight\": {\"value\": \"bold\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'OS costs appear when scanned hosts run RHEL 7/8/9, CentOS, Windows 10/Server, Ubuntu, Debian,' : ''\"},\n \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 136},\n \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'or any macOS below version 26 (Tahoe). Windows 11 and macOS 26 Tahoe are PQC targets.' : ''\"},\n \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}\n }}\n }\n ]\n}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"PQC Upgrade Cost \\u2014 OS Category cost estimates ranked list. Reads pre-computed total_cost_usd per OS category from tychon-pqc-system-readiness*. Styled to match the main OS breakdown panel. No cost arithmetic in Vega.\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.os_category === sel ? null : datum.os_category\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.os_category === sel ? kibanaRemoveFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}}) : kibanaAddFilter({'match_phrase': {'quantum_readiness.cost_analysis.os_category': datum.os_category}})\", \"force\": true}]}], \"data\": [{\"name\": \"os_costs\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-system-readiness*\", \"body\": {\"size\": 0, \"aggs\": {\"qa_only\": {\"filter\": {\"term\": {\"event.dataset\": \"quantum_assessment\"}}, \"aggs\": {\"categories\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.os_category\", \"size\": 30, \"order\": {\"cost_sum\": \"desc\"}}, \"aggs\": {\"cost_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.os_total_cost_usd\"}}, \"hours_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.os_labor_hours\"}}, \"license_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.os_license_cost_usd\"}}, \"hw_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.os_hardware_cost_usd\"}}, \"tier_terms\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.os_tier\", \"size\": 1}}}}}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"buckets\", \"expr\": \"isValid(datum.qa_only) && isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\"}, {\"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"]}, {\"type\": \"filter\", \"expr\": \"isValid(datum.item) && isValid(datum.item.key)\"}, {\"type\": \"formula\", \"as\": \"os_category\", \"expr\": \"datum.item.key\"}, {\"type\": \"formula\", \"as\": \"total_cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\"}, {\"type\": \"formula\", \"as\": \"labor_hours\", \"expr\": \"isValid(datum.item.hours_sum) ? datum.item.hours_sum.value : 0\"}, {\"type\": \"formula\", \"as\": \"license_cost\", \"expr\": \"isValid(datum.item.license_sum) ? datum.item.license_sum.value : 0\"}, {\"type\": \"formula\", \"as\": \"hw_cost\", \"expr\": \"isValid(datum.item.hw_sum) ? datum.item.hw_sum.value : 0\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"}, {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.total_cost === 0 ? '#66bb6a' : datum.tier === 'LEGACY' ? '#ef5350' : datum.tier === 'CLASSICAL' ? '#ffa726' : '#448aff'\"}, {\"type\": \"formula\", \"as\": \"bgclr\", \"expr\": \"datum.total_cost === 0 ? '#66bb6a18' : datum.tier === 'LEGACY' ? '#ef535018' : datum.tier === 'CLASSICAL' ? '#ffa72618' : '#448aff18'\"}]}, {\"name\": \"mx\", \"source\": \"os_costs\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"total_cost\"], \"as\": [\"v\"]}]}], \"scales\": [{\"name\": \"yscale\", \"type\": \"band\", \"domain\": {\"data\": \"os_costs\", \"field\": \"os_category\", \"sort\": false}, \"range\": {\"step\": 72}, \"paddingInner\": 0, \"paddingOuter\": 0}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"OS UPGRADE COST ESTIMATE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"TOTAL COST BY OS CATEGORY \\u2014 sorted by cost desc\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 48}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.os_category === sel ? '#1c1c2e' : datum.total_cost === 0 ? '#121a12' : '#161622'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 48}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"field\": \"clr\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"value\": 4}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 110}, \"width\": {\"signal\": \"length(data('mx')) > 0 && data('mx')[0].v > 0 ? max((datum.total_cost / data('mx')[0].v) * (width - 4), 0) : 0\"}, \"height\": {\"value\": 4}, \"fill\": {\"field\": \"clr\"}, \"opacity\": {\"value\": 0.35}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 113}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 72}, \"text\": {\"field\": \"os_category\"}, \"limit\": {\"signal\": \"width * 0.58 - 18\"}, \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 92}, \"text\": {\"signal\": \"format(datum.labor_hours, ',.1f') + ' labor hrs | $' + format(datum.license_cost, ',.0f') + ' license | $' + format(datum.hw_cost, ',.0f') + ' hardware'\"}, \"limit\": {\"signal\": \"width * 0.58 - 18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 56}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"field\": \"bgclr\"}, \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 41\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 68}, \"text\": {\"field\": \"tier\"}, \"fill\": {\"field\": \"clr\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 79}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#333333\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 41\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 91}, \"text\": {\"signal\": \"datum.os_category === sel ? 'SELECTED' : ''\"}, \"fill\": {\"signal\": \"datum.os_category === sel ? datum.clr : '#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"os_costs\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"os_category\", \"offset\": 84}, \"text\": {\"signal\": \"datum.total_cost >= 1e6 ? '$' + format(datum.total_cost / 1e6, ',.2~f') + 'M' : datum.total_cost >= 1e3 ? '$' + format(datum.total_cost / 1e3, ',.1~f') + 'k' : '$' + format(datum.total_cost, ',')\"}, \"fill\": {\"signal\": \"datum.os_category === sel ? datum.clr : datum.total_cost > 0 ? '#dddddd' : '#66bb6a'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height - 8\"}, \"text\": {\"value\": \"\\u2191 highest cost at top\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 100}, \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'NO OS UPGRADE COSTS IN SELECTED TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#333333\"}, \"fontSize\": {\"value\": 11}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"fontWeight\": {\"value\": \"bold\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 122}, \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'OS costs appear when scanned hosts run RHEL 7/8/9, CentOS, Windows 10/Server, Ubuntu, Debian,' : ''\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"value\": 136}, \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'or any macOS below version 26 (Tahoe). Windows 11 and macOS 26 Tahoe are PQC targets.' : ''\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('os_costs')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -213,7 +213,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Upgrade Cost — Effort vs. Risk Bubble Chart. X=total_cost_usd, Y=tier, bubble size=count. Reads pre-computed values from tychon-pqc-system-readiness* using new row schema.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 90, \"right\": 40, \"top\": 40, \"bottom\": 60 },\n \"data\": [\n {\n \"name\": \"os_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"qa_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment\" } },\n \"aggs\": {\n \"categories\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.os_category\",\n \"size\": 30\n },\n \"aggs\": {\n \"cost_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.os_total_cost_usd\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.os_tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"buckets\",\n \"expr\": \"isValid(datum.qa_only) \u0026\u0026 isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\"\n },\n { \"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"] },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.item) \u0026\u0026 isValid(datum.item.key)\" },\n { \"type\": \"formula\", \"as\": \"label\", \"expr\": \"datum.item.key\" },\n { \"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"datum.item.doc_count \u003e 0 ? datum.item.doc_count : 1\" },\n {\n \"type\": \"formula\",\n \"as\": \"tier\",\n \"expr\": \"isValid(datum.item.tier_terms) \u0026\u0026 datum.item.tier_terms.buckets.length \u003e 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"'OS Upgrade'\" }\n ]\n },\n {\n \"name\": \"app_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment.app_group\" } },\n \"aggs\": {\n \"families\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.app_family\",\n \"size\": 20\n },\n \"aggs\": {\n \"cost_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } },\n \"instances_sum\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.instance_count\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"buckets\",\n \"expr\": \"isValid(datum.app_only) \u0026\u0026 isValid(datum.app_only.families) ? datum.app_only.families.buckets : []\"\n },\n { \"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"] },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.item) \u0026\u0026 isValid(datum.item.key)\" },\n { \"type\": \"formula\", \"as\": \"label\", \"expr\": \"datum.item.key\" },\n { \"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"isValid(datum.item.instances_sum) \u0026\u0026 datum.item.instances_sum.value \u003e 0 ? datum.item.instances_sum.value : 1\" },\n {\n \"type\": \"formula\",\n \"as\": \"tier\",\n \"expr\": \"isValid(datum.item.tier_terms) \u0026\u0026 datum.item.tier_terms.buckets.length \u003e 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"'App Upgrade'\" }\n ]\n },\n {\n \"name\": \"all_items\",\n \"source\": [\"os_raw\", \"app_raw\"],\n \"transform\": [\n { \"type\": \"filter\", \"expr\": \"isFinite(datum.cost) \u0026\u0026 datum.cost \u003e 0\" }\n ]\n }\n ],\n \"scales\": [\n {\n \"name\": \"xscale\",\n \"type\": \"linear\",\n \"domain\": { \"data\": \"all_items\", \"field\": \"cost\" },\n \"range\": \"width\",\n \"nice\": true,\n \"zero\": true\n },\n {\n \"name\": \"yscale\",\n \"type\": \"point\",\n \"domain\": [\"LEGACY\", \"CLASSICAL\"],\n \"range\": [80, 260],\n \"padding\": 0.5\n },\n {\n \"name\": \"sizescale\",\n \"type\": \"sqrt\",\n \"domain\": { \"data\": \"all_items\", \"field\": \"count\" },\n \"range\": [200, 3000],\n \"zero\": true\n },\n {\n \"name\": \"colorscale\",\n \"type\": \"ordinal\",\n \"domain\": [\"OS Upgrade\", \"App Upgrade\"],\n \"range\": [\"#ef5350\", \"#3b82f6\"]\n }\n ],\n \"axes\": [\n {\n \"orient\": \"bottom\",\n \"scale\": \"xscale\",\n \"format\": \"$,.0f\",\n \"title\": \"Total Upgrade Cost (USD)\",\n \"titleFontSize\": 12,\n \"labelAngle\": -30\n },\n {\n \"orient\": \"left\",\n \"scale\": \"yscale\",\n \"title\": \"Risk Tier\",\n \"titleFontSize\": 12\n }\n ],\n \"legends\": [\n {\n \"fill\": \"colorscale\",\n \"title\": \"Category\",\n \"symbolType\": \"circle\",\n \"orient\": \"top-right\"\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 60 },\n \"y\": { \"scale\": \"yscale\", \"value\": \"CLASSICAL\", \"offset\": 40 },\n \"text\": { \"value\": \"Quick Wins\" },\n \"fontSize\": { \"value\": 11 },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"fontStyle\": { \"value\": \"italic\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"signal\": \"width - 100\" },\n \"y\": { \"scale\": \"yscale\", \"value\": \"LEGACY\", \"offset\": -20 },\n \"text\": { \"value\": \"Plan Carefully\" },\n \"fontSize\": { \"value\": 11 },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"fontStyle\": { \"value\": \"italic\" }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": { \"data\": \"all_items\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"cost\" },\n \"y\": { \"scale\": \"yscale\", \"field\": \"tier\" },\n \"size\": { \"scale\": \"sizescale\", \"field\": \"count\" },\n \"fill\": { \"scale\": \"colorscale\", \"field\": \"source\" },\n \"fillOpacity\": { \"value\": 0.65 },\n \"stroke\": { \"scale\": \"colorscale\", \"field\": \"source\" },\n \"strokeWidth\": { \"value\": 1.5 },\n \"tooltip\": {\n \"signal\": \"{'Label': datum.label, 'Tier': datum.tier, 'Category': datum.source, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Count': datum.count}\"\n }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"all_items\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"cost\" },\n \"y\": { \"scale\": \"yscale\", \"field\": \"tier\", \"offset\": -16 },\n \"align\": { \"value\": \"center\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"value\": \"#374151\" },\n \"text\": { \"field\": \"label\" }\n }\n }\n }\n ]\n}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"PQC Upgrade Cost \\u2014 Effort vs. Risk Bubble Chart. X=total_cost_usd, Y=tier, bubble size=count. Reads pre-computed values from tychon-pqc-system-readiness* using new row schema.\", \"autosize\": {\"type\": \"fit\", \"contains\": \"padding\"}, \"padding\": {\"left\": 90, \"right\": 40, \"top\": 40, \"bottom\": 60}, \"data\": [{\"name\": \"os_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-system-readiness*\", \"body\": {\"size\": 0, \"aggs\": {\"qa_only\": {\"filter\": {\"term\": {\"event.dataset\": \"quantum_assessment\"}}, \"aggs\": {\"categories\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.os_category\", \"size\": 30}, \"aggs\": {\"cost_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.os_total_cost_usd\"}}, \"tier_terms\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.os_tier\", \"size\": 1}}}}}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"buckets\", \"expr\": \"isValid(datum.qa_only) && isValid(datum.qa_only.categories) ? datum.qa_only.categories.buckets : []\"}, {\"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"]}, {\"type\": \"filter\", \"expr\": \"isValid(datum.item) && isValid(datum.item.key)\"}, {\"type\": \"formula\", \"as\": \"label\", \"expr\": \"datum.item.key\"}, {\"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\"}, {\"type\": \"formula\", \"as\": \"count\", \"expr\": \"datum.item.doc_count > 0 ? datum.item.doc_count : 1\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"}, {\"type\": \"formula\", \"as\": \"source\", \"expr\": \"'OS Upgrade'\"}]}, {\"name\": \"app_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-system-readiness*\", \"body\": {\"size\": 0, \"aggs\": {\"app_only\": {\"filter\": {\"term\": {\"event.dataset\": \"quantum_assessment.app_group\"}}, \"aggs\": {\"families\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.app_family\", \"size\": 20}, \"aggs\": {\"cost_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_cost_usd\"}}, \"instances_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.instance_count\"}}, \"tier_terms\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.tier\", \"size\": 1}}}}}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"buckets\", \"expr\": \"isValid(datum.app_only) && isValid(datum.app_only.families) ? datum.app_only.families.buckets : []\"}, {\"type\": \"flatten\", \"fields\": [\"buckets\"], \"as\": [\"item\"]}, {\"type\": \"filter\", \"expr\": \"isValid(datum.item) && isValid(datum.item.key)\"}, {\"type\": \"formula\", \"as\": \"label\", \"expr\": \"datum.item.key\"}, {\"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.item.cost_sum) ? datum.item.cost_sum.value : 0\"}, {\"type\": \"formula\", \"as\": \"count\", \"expr\": \"isValid(datum.item.instances_sum) && datum.item.instances_sum.value > 0 ? datum.item.instances_sum.value : 1\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"isValid(datum.item.tier_terms) && datum.item.tier_terms.buckets.length > 0 ? datum.item.tier_terms.buckets[0].key : 'CLASSICAL'\"}, {\"type\": \"formula\", \"as\": \"source\", \"expr\": \"'App Upgrade'\"}]}, {\"name\": \"all_items\", \"source\": [\"os_raw\", \"app_raw\"], \"transform\": [{\"type\": \"filter\", \"expr\": \"isFinite(datum.cost) && datum.cost > 0\"}]}], \"scales\": [{\"name\": \"xscale\", \"type\": \"linear\", \"domain\": {\"data\": \"all_items\", \"field\": \"cost\"}, \"range\": \"width\", \"nice\": true, \"zero\": true}, {\"name\": \"yscale\", \"type\": \"point\", \"domain\": [\"LEGACY\", \"CLASSICAL\"], \"range\": [80, 260], \"padding\": 0.5}, {\"name\": \"sizescale\", \"type\": \"sqrt\", \"domain\": {\"data\": \"all_items\", \"field\": \"count\"}, \"range\": [200, 3000], \"zero\": true}, {\"name\": \"colorscale\", \"type\": \"ordinal\", \"domain\": [\"OS Upgrade\", \"App Upgrade\"], \"range\": [\"#ef5350\", \"#3b82f6\"]}], \"axes\": [{\"orient\": \"bottom\", \"scale\": \"xscale\", \"format\": \"$,.0f\", \"title\": \"Total Upgrade Cost (USD)\", \"titleFontSize\": 12, \"labelAngle\": -30}, {\"orient\": \"left\", \"scale\": \"yscale\", \"title\": \"Risk Tier\", \"titleFontSize\": 12}], \"legends\": [{\"fill\": \"colorscale\", \"title\": \"Category\", \"symbolType\": \"circle\", \"orient\": \"top-right\"}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 60}, \"y\": {\"scale\": \"yscale\", \"value\": \"CLASSICAL\", \"offset\": 40}, \"text\": {\"value\": \"Quick Wins\"}, \"fontSize\": {\"value\": 11}, \"fill\": {\"value\": \"#d1d5db\"}, \"fontStyle\": {\"value\": \"italic\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width - 100\"}, \"y\": {\"scale\": \"yscale\", \"value\": \"LEGACY\", \"offset\": -20}, \"text\": {\"value\": \"Plan Carefully\"}, \"fontSize\": {\"value\": 11}, \"fill\": {\"value\": \"#d1d5db\"}, \"fontStyle\": {\"value\": \"italic\"}}}}, {\"type\": \"symbol\", \"from\": {\"data\": \"all_items\"}, \"encode\": {\"enter\": {\"x\": {\"scale\": \"xscale\", \"field\": \"cost\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"tier\"}, \"size\": {\"scale\": \"sizescale\", \"field\": \"count\"}, \"fill\": {\"scale\": \"colorscale\", \"field\": \"source\"}, \"fillOpacity\": {\"value\": 0.65}, \"stroke\": {\"scale\": \"colorscale\", \"field\": \"source\"}, \"strokeWidth\": {\"value\": 1.5}, \"tooltip\": {\"signal\": \"{'Label': datum.label, 'Tier': datum.tier, 'Category': datum.source, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Count': datum.count}\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"all_items\"}, \"encode\": {\"enter\": {\"x\": {\"scale\": \"xscale\", \"field\": \"cost\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"tier\", \"offset\": -16}, \"align\": {\"value\": \"center\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"value\": \"#374151\"}, \"text\": {\"field\": \"label\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('os_raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('os_raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -267,7 +267,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Cost Composition by App Family (compact). Stacked bars: labor + license + hardware.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 110, \"right\": 18, \"top\": 34, \"bottom\": 38 },\n \"background\": \"#111111\",\n\n \"signals\": [\n { \"name\": \"chartTitle\", \"value\": \"PQC COST COMPOSITION BY APP FAMILY\" },\n { \"name\": \"topN\", \"value\": 10 }\n ],\n\n \"data\": [\n {\n \"name\": \"raw_all\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment.app_group\" } },\n \"aggs\": {\n \"families\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.app_family\",\n \"size\": 30,\n \"order\": { \"total_cost\": \"desc\" }\n },\n \"aggs\": {\n \"labor_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.labor_cost_usd\" } },\n \"license_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.license_cost_usd\" } },\n \"hardware_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.hardware_cost_usd\" } },\n \"total_cost\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" } },\n \"instances\": { \"sum\": { \"field\": \"quantum_readiness.cost_analysis.instance_count\" } },\n \"tier_terms\": { \"terms\": { \"field\": \"quantum_readiness.cost_analysis.tier\", \"size\": 1 } }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.app_only.families.buckets\" },\n \"transform\": [\n { \"type\": \"filter\", \"expr\": \"datum \u0026\u0026 datum.key\" },\n { \"type\": \"formula\", \"as\": \"app_family\", \"expr\": \"datum.key\" },\n {\n \"type\": \"formula\",\n \"as\": \"app_family_short\",\n \"expr\": \"length(datum.key) \u003e 14 ? substring(datum.key,0,11) + '...' : datum.key\"\n },\n { \"type\": \"formula\", \"as\": \"labor\", \"expr\": \"isValid(datum.labor_cost) ? datum.labor_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"license\", \"expr\": \"isValid(datum.license_cost) ? datum.license_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"hardware\", \"expr\": \"isValid(datum.hardware_cost) ? datum.hardware_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"total\", \"expr\": \"isValid(datum.total_cost) ? datum.total_cost.value : 0\" },\n { \"type\": \"formula\", \"as\": \"instances\", \"expr\": \"isValid(datum.instances) ? datum.instances.value : 0\" },\n {\n \"type\": \"formula\",\n \"as\": \"tier\",\n \"expr\": \"isValid(datum.tier_terms) \u0026\u0026 datum.tier_terms.buckets.length \u003e 0 ? datum.tier_terms.buckets[0].key : 'CLASSICAL'\"\n },\n { \"type\": \"filter\", \"expr\": \"isFinite(datum.total) \u0026\u0026 datum.total \u003e 0\" },\n { \"type\": \"collect\", \"sort\": { \"field\": \"total\", \"order\": \"descending\" } },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rank\"] },\n { \"type\": \"filter\", \"expr\": \"datum.rank \u003c= topN\" }\n ]\n },\n\n {\n \"name\": \"components\",\n \"source\": \"raw_all\",\n \"transform\": [\n { \"type\": \"fold\", \"fields\": [\"labor\", \"license\", \"hardware\"], \"as\": [\"component\", \"value\"] },\n { \"type\": \"stack\", \"groupby\": [\"app_family_short\"], \"sort\": { \"field\": \"component\" }, \"field\": \"value\", \"as\": [\"x0\", \"x1\"] }\n ]\n }\n ],\n\n \"scales\": [\n {\n \"name\": \"yscale\",\n \"type\": \"band\",\n \"domain\": { \"data\": \"raw_all\", \"field\": \"app_family_short\" },\n \"range\": \"height\",\n \"paddingInner\": 0.18,\n \"paddingOuter\": 0.06\n },\n {\n \"name\": \"xscale\",\n \"type\": \"linear\",\n \"domain\": { \"data\": \"raw_all\", \"field\": \"total\" },\n \"nice\": true,\n \"zero\": true,\n \"range\": \"width\"\n },\n {\n \"name\": \"cscale\",\n \"type\": \"ordinal\",\n \"domain\": [\"labor\", \"license\", \"hardware\"],\n \"range\": [\"#f59e0b\", \"#3b82f6\", \"#ef4444\"]\n }\n ],\n\n \"axes\": [\n {\n \"orient\": \"left\",\n \"scale\": \"yscale\",\n \"labelLimit\": 96,\n \"labelColor\": \"#d1d5db\",\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\",\n \"title\": \"\",\n \"zindex\": 1\n },\n {\n \"orient\": \"bottom\",\n \"scale\": \"xscale\",\n \"format\": \"$,.2s\",\n \"title\": \"Total Cost (USD)\",\n \"titleColor\": \"#9ca3af\",\n \"labelColor\": \"#9ca3af\",\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\"\n }\n ],\n\n \"legends\": [\n {\n \"fill\": \"cscale\",\n \"title\": \"Cost Component\",\n \"orient\": \"top-right\",\n \"titleColor\": \"#d1d5db\",\n \"labelColor\": \"#9ca3af\"\n }\n ],\n\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 0 },\n \"y\": { \"value\": -10 },\n \"text\": { \"signal\": \"chartTitle + ' (TOP ' + topN + ')'\" },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"letterSpacing\": { \"value\": 0.8 }\n }\n }\n },\n\n {\n \"type\": \"rect\",\n \"from\": { \"data\": \"components\" },\n \"encode\": {\n \"enter\": {\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\" },\n \"height\": { \"scale\": \"yscale\", \"band\": 1 },\n \"x\": { \"scale\": \"xscale\", \"field\": \"x0\" },\n \"x2\": { \"scale\": \"xscale\", \"field\": \"x1\" },\n \"fill\": { \"scale\": \"cscale\", \"field\": \"component\" },\n \"stroke\": { \"value\": \"#0f0f0f\" },\n \"strokeWidth\": { \"value\": 0.6 },\n \"tooltip\": {\n \"signal\": \"{'App Family': datum.app_family, 'Tier': datum.tier, 'Component': datum.component, 'Component Cost': '$' + format(datum.value, ',.0f'), 'Total Cost': '$' + format(datum.total, ',.0f'), 'Instances': datum.instances}\"\n }\n }\n }\n },\n\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"raw_all\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"total\", \"offset\": 4 },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5 },\n \"text\": { \"signal\": \"'$' + format(datum.total, ',.2s')\" },\n \"fill\": { \"value\": \"#e5e7eb\" },\n \"fontSize\": { \"value\": 9 },\n \"align\": { \"value\": \"left\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"raw_all\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": -4 },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5 },\n \"text\": { \"signal\": \"datum.instances \u003e 0 ? '(' + format(datum.instances, ',.0f') + ')' : ''\" },\n \"fill\": { \"value\": \"#6b7280\" },\n \"fontSize\": { \"value\": 8 },\n \"align\": { \"value\": \"right\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n }\n ]\n}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"PQC Cost Composition by App Family (compact). Stacked bars: labor + license + hardware.\", \"autosize\": {\"type\": \"fit\", \"contains\": \"padding\"}, \"padding\": {\"left\": 110, \"right\": 18, \"top\": 34, \"bottom\": 38}, \"background\": \"#111111\", \"signals\": [{\"name\": \"chartTitle\", \"value\": \"PQC COST COMPOSITION BY APP FAMILY\"}, {\"name\": \"topN\", \"value\": 10}], \"data\": [{\"name\": \"raw_all\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-system-readiness*\", \"body\": {\"size\": 0, \"aggs\": {\"app_only\": {\"filter\": {\"term\": {\"event.dataset\": \"quantum_assessment.app_group\"}}, \"aggs\": {\"families\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.app_family\", \"size\": 30, \"order\": {\"total_cost\": \"desc\"}}, \"aggs\": {\"labor_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.labor_cost_usd\"}}, \"license_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.license_cost_usd\"}}, \"hardware_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.hardware_cost_usd\"}}, \"total_cost\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_cost_usd\"}}, \"instances\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.instance_count\"}}, \"tier_terms\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.tier\", \"size\": 1}}}}}}}}}, \"format\": {\"property\": \"aggregations.app_only.families.buckets\"}, \"transform\": [{\"type\": \"filter\", \"expr\": \"datum && datum.key\"}, {\"type\": \"formula\", \"as\": \"app_family\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"app_family_short\", \"expr\": \"length(datum.key) > 14 ? substring(datum.key,0,11) + '...' : datum.key\"}, {\"type\": \"formula\", \"as\": \"labor\", \"expr\": \"isValid(datum.labor_cost) ? datum.labor_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"license\", \"expr\": \"isValid(datum.license_cost) ? datum.license_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"hardware\", \"expr\": \"isValid(datum.hardware_cost) ? datum.hardware_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"total\", \"expr\": \"isValid(datum.total_cost) ? datum.total_cost.value : 0\"}, {\"type\": \"formula\", \"as\": \"instances\", \"expr\": \"isValid(datum.instances) ? datum.instances.value : 0\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"isValid(datum.tier_terms) && datum.tier_terms.buckets.length > 0 ? datum.tier_terms.buckets[0].key : 'CLASSICAL'\"}, {\"type\": \"filter\", \"expr\": \"isFinite(datum.total) && datum.total > 0\"}, {\"type\": \"collect\", \"sort\": {\"field\": \"total\", \"order\": \"descending\"}}, {\"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rank\"]}, {\"type\": \"filter\", \"expr\": \"datum.rank <= topN\"}]}, {\"name\": \"components\", \"source\": \"raw_all\", \"transform\": [{\"type\": \"fold\", \"fields\": [\"labor\", \"license\", \"hardware\"], \"as\": [\"component\", \"value\"]}, {\"type\": \"stack\", \"groupby\": [\"app_family_short\"], \"sort\": {\"field\": \"component\"}, \"field\": \"value\", \"as\": [\"x0\", \"x1\"]}]}], \"scales\": [{\"name\": \"yscale\", \"type\": \"band\", \"domain\": {\"data\": \"raw_all\", \"field\": \"app_family_short\"}, \"range\": \"height\", \"paddingInner\": 0.18, \"paddingOuter\": 0.06}, {\"name\": \"xscale\", \"type\": \"linear\", \"domain\": {\"data\": \"raw_all\", \"field\": \"total\"}, \"nice\": true, \"zero\": true, \"range\": \"width\"}, {\"name\": \"cscale\", \"type\": \"ordinal\", \"domain\": [\"labor\", \"license\", \"hardware\"], \"range\": [\"#f59e0b\", \"#3b82f6\", \"#ef4444\"]}], \"axes\": [{\"orient\": \"left\", \"scale\": \"yscale\", \"labelLimit\": 96, \"labelColor\": \"#d1d5db\", \"tickColor\": \"#333333\", \"domainColor\": \"#333333\", \"title\": \"\", \"zindex\": 1}, {\"orient\": \"bottom\", \"scale\": \"xscale\", \"format\": \"$,.2s\", \"title\": \"Total Cost (USD)\", \"titleColor\": \"#9ca3af\", \"labelColor\": \"#9ca3af\", \"tickColor\": \"#333333\", \"domainColor\": \"#333333\"}], \"legends\": [{\"fill\": \"cscale\", \"title\": \"Cost Component\", \"orient\": \"top-right\", \"titleColor\": \"#d1d5db\", \"labelColor\": \"#9ca3af\"}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"y\": {\"value\": -10}, \"text\": {\"signal\": \"chartTitle + ' (TOP ' + topN + ')'\"}, \"fill\": {\"value\": \"#d1d5db\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"components\"}, \"encode\": {\"enter\": {\"y\": {\"scale\": \"yscale\", \"field\": \"app_family_short\"}, \"height\": {\"scale\": \"yscale\", \"band\": 1}, \"x\": {\"scale\": \"xscale\", \"field\": \"x0\"}, \"x2\": {\"scale\": \"xscale\", \"field\": \"x1\"}, \"fill\": {\"scale\": \"cscale\", \"field\": \"component\"}, \"stroke\": {\"value\": \"#0f0f0f\"}, \"strokeWidth\": {\"value\": 0.6}, \"tooltip\": {\"signal\": \"{'App Family': datum.app_family, 'Tier': datum.tier, 'Component': datum.component, 'Component Cost': '$' + format(datum.value, ',.0f'), 'Total Cost': '$' + format(datum.total, ',.0f'), 'Instances': datum.instances}\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"raw_all\"}, \"encode\": {\"enter\": {\"x\": {\"scale\": \"xscale\", \"field\": \"total\", \"offset\": 4}, \"y\": {\"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5}, \"text\": {\"signal\": \"'$' + format(datum.total, ',.2s')\"}, \"fill\": {\"value\": \"#e5e7eb\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"left\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"raw_all\"}, \"encode\": {\"enter\": {\"x\": {\"value\": -4}, \"y\": {\"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5}, \"text\": {\"signal\": \"datum.instances > 0 ? '(' + format(datum.instances, ',.0f') + ')' : ''\"}, \"fill\": {\"value\": \"#6b7280\"}, \"fontSize\": {\"value\": 8}, \"align\": {\"value\": \"right\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw_all')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw_all')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -321,7 +321,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"PQC Priority Matrix — Tier x App Family heatmap. Responsive, compact layout.\",\n \"autosize\": { \"type\": \"fit\", \"contains\": \"padding\" },\n \"padding\": { \"left\": 92, \"right\": 16, \"top\": 34, \"bottom\": 46 },\n \"background\": \"#111111\",\n\n \"signals\": [\n { \"name\": \"topN\", \"value\": 10 },\n { \"name\": \"showCellText\", \"update\": \"bandwidth('yscale') \u003e= 18 \u0026\u0026 bandwidth('xscale') \u003e= 64\" }\n ],\n\n \"data\": [\n {\n \"name\": \"matrix_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-system-readiness*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"quantum_assessment.app_group\" } },\n \"aggs\": {\n \"families\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.app_family\",\n \"size\": 40\n },\n \"aggs\": {\n \"tiers\": {\n \"terms\": {\n \"field\": \"quantum_readiness.cost_analysis.tier\",\n \"size\": 5\n },\n \"aggs\": {\n \"cost_sum\": {\n \"sum\": { \"field\": \"quantum_readiness.cost_analysis.total_cost_usd\" }\n },\n \"instances_sum\": {\n \"sum\": { \"field\": \"quantum_readiness.cost_analysis.instance_count\" }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.app_only.families.buckets\" },\n \"transform\": [\n { \"type\": \"filter\", \"expr\": \"datum \u0026\u0026 datum.key \u0026\u0026 datum.tiers \u0026\u0026 datum.tiers.buckets\" },\n { \"type\": \"formula\", \"as\": \"app_family\", \"expr\": \"datum.key\" },\n { \"type\": \"flatten\", \"fields\": [\"tiers.buckets\"], \"as\": [\"tier_bucket\"] },\n { \"type\": \"filter\", \"expr\": \"datum.tier_bucket \u0026\u0026 datum.tier_bucket.key\" },\n { \"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.tier_bucket.key\" },\n { \"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.tier_bucket.cost_sum) ? datum.tier_bucket.cost_sum.value : 0\" },\n { \"type\": \"formula\", \"as\": \"instances\", \"expr\": \"isValid(datum.tier_bucket.instances_sum) ? datum.tier_bucket.instances_sum.value : 0\" },\n { \"type\": \"filter\", \"expr\": \"isFinite(datum.cost) \u0026\u0026 datum.cost \u003e= 0\" }\n ]\n },\n\n {\n \"name\": \"family_order\",\n \"source\": \"matrix_raw\",\n \"transform\": [\n { \"type\": \"aggregate\", \"groupby\": [\"app_family\"], \"ops\": [\"sum\"], \"fields\": [\"cost\"], \"as\": [\"family_total_cost\"] },\n { \"type\": \"collect\", \"sort\": { \"field\": \"family_total_cost\", \"order\": \"descending\" } },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rank\"] },\n { \"type\": \"filter\", \"expr\": \"datum.rank \u003c= topN\" },\n {\n \"type\": \"formula\",\n \"as\": \"app_family_short\",\n \"expr\": \"length(datum.app_family) \u003e 14 ? substring(datum.app_family,0,11) + '...' : datum.app_family\"\n }\n ]\n },\n\n {\n \"name\": \"matrix\",\n \"source\": \"matrix_raw\",\n \"transform\": [\n {\n \"type\": \"lookup\",\n \"from\": \"family_order\",\n \"key\": \"app_family\",\n \"fields\": [\"app_family\"],\n \"values\": [\"rank\", \"app_family_short\", \"family_total_cost\"],\n \"as\": [\"rank\", \"app_family_short\", \"family_total_cost\"]\n },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.rank)\" }\n ]\n }\n ],\n\n \"scales\": [\n {\n \"name\": \"xscale\",\n \"type\": \"band\",\n \"domain\": [\"LEGACY\", \"CLASSICAL\"],\n \"range\": \"width\",\n \"paddingInner\": 0.08,\n \"paddingOuter\": 0.03\n },\n {\n \"name\": \"yscale\",\n \"type\": \"band\",\n \"domain\": { \"data\": \"family_order\", \"field\": \"app_family_short\" },\n \"range\": \"height\",\n \"paddingInner\": 0.08,\n \"paddingOuter\": 0.03\n },\n {\n \"name\": \"cscale\",\n \"type\": \"linear\",\n \"domain\": { \"data\": \"matrix\", \"field\": \"cost\" },\n \"range\": [\"#1f2937\", \"#2563eb\", \"#7c3aed\", \"#dc2626\"],\n \"nice\": true,\n \"zero\": true\n }\n ],\n\n \"axes\": [\n {\n \"orient\": \"bottom\",\n \"scale\": \"xscale\",\n \"title\": \"Tier\",\n \"titleColor\": \"#d1d5db\",\n \"labelColor\": \"#d1d5db\",\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\"\n },\n {\n \"orient\": \"left\",\n \"scale\": \"yscale\",\n \"title\": \"\",\n \"labelColor\": \"#d1d5db\",\n \"labelLimit\": 86,\n \"tickColor\": \"#333333\",\n \"domainColor\": \"#333333\"\n }\n ],\n\n \"legends\": [\n {\n \"fill\": \"cscale\",\n \"title\": \"Cost\",\n \"orient\": \"right\",\n \"titleColor\": \"#d1d5db\",\n \"labelColor\": \"#9ca3af\",\n \"format\": \"$,.2s\"\n }\n ],\n\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 0 },\n \"y\": { \"value\": -12 },\n \"text\": { \"value\": \"PRIORITY MATRIX (TOP APP FAMILIES)\" },\n \"fill\": { \"value\": \"#d1d5db\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"letterSpacing\": { \"value\": 0.8 }\n }\n }\n },\n\n {\n \"type\": \"rect\",\n \"from\": { \"data\": \"matrix\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"tier\" },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\" },\n \"width\": { \"scale\": \"xscale\", \"band\": 1 },\n \"height\": { \"scale\": \"yscale\", \"band\": 1 },\n \"fill\": { \"scale\": \"cscale\", \"field\": \"cost\" },\n \"stroke\": { \"value\": \"#1a1a1a\" },\n \"strokeWidth\": { \"value\": 1 },\n \"tooltip\": {\n \"signal\": \"{'App Family': datum.app_family, 'Tier': datum.tier, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Instances': format(datum.instances, ',.0f')}\"\n }\n }\n }\n },\n\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"matrix\" },\n \"encode\": {\n \"enter\": {\n \"x\": { \"scale\": \"xscale\", \"field\": \"tier\", \"band\": 0.5 },\n \"y\": { \"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5 },\n \"align\": { \"value\": \"center\" },\n \"baseline\": { \"value\": \"middle\" },\n \"fontSize\": { \"value\": 9 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#f9fafb\" },\n \"text\": { \"signal\": \"showCellText \u0026\u0026 datum.instances \u003e 0 ? format(datum.instances, ',.0f') : ''\" }\n }\n }\n }\n ]\n}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"PQC Priority Matrix \\u2014 Tier x App Family heatmap. Responsive, compact layout.\", \"autosize\": {\"type\": \"fit\", \"contains\": \"padding\"}, \"padding\": {\"left\": 92, \"right\": 16, \"top\": 34, \"bottom\": 46}, \"background\": \"#111111\", \"signals\": [{\"name\": \"topN\", \"value\": 10}, {\"name\": \"showCellText\", \"update\": \"bandwidth('yscale') >= 18 && bandwidth('xscale') >= 64\"}], \"data\": [{\"name\": \"matrix_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-system-readiness*\", \"body\": {\"size\": 0, \"aggs\": {\"app_only\": {\"filter\": {\"term\": {\"event.dataset\": \"quantum_assessment.app_group\"}}, \"aggs\": {\"families\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.app_family\", \"size\": 40}, \"aggs\": {\"tiers\": {\"terms\": {\"field\": \"quantum_readiness.cost_analysis.tier\", \"size\": 5}, \"aggs\": {\"cost_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.total_cost_usd\"}}, \"instances_sum\": {\"sum\": {\"field\": \"quantum_readiness.cost_analysis.instance_count\"}}}}}}}}}}}, \"format\": {\"property\": \"aggregations.app_only.families.buckets\"}, \"transform\": [{\"type\": \"filter\", \"expr\": \"datum && datum.key && datum.tiers && datum.tiers.buckets\"}, {\"type\": \"formula\", \"as\": \"app_family\", \"expr\": \"datum.key\"}, {\"type\": \"flatten\", \"fields\": [\"tiers.buckets\"], \"as\": [\"tier_bucket\"]}, {\"type\": \"filter\", \"expr\": \"datum.tier_bucket && datum.tier_bucket.key\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.tier_bucket.key\"}, {\"type\": \"formula\", \"as\": \"cost\", \"expr\": \"isValid(datum.tier_bucket.cost_sum) ? datum.tier_bucket.cost_sum.value : 0\"}, {\"type\": \"formula\", \"as\": \"instances\", \"expr\": \"isValid(datum.tier_bucket.instances_sum) ? datum.tier_bucket.instances_sum.value : 0\"}, {\"type\": \"filter\", \"expr\": \"isFinite(datum.cost) && datum.cost >= 0\"}]}, {\"name\": \"family_order\", \"source\": \"matrix_raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"app_family\"], \"ops\": [\"sum\"], \"fields\": [\"cost\"], \"as\": [\"family_total_cost\"]}, {\"type\": \"collect\", \"sort\": {\"field\": \"family_total_cost\", \"order\": \"descending\"}}, {\"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rank\"]}, {\"type\": \"filter\", \"expr\": \"datum.rank <= topN\"}, {\"type\": \"formula\", \"as\": \"app_family_short\", \"expr\": \"length(datum.app_family) > 14 ? substring(datum.app_family,0,11) + '...' : datum.app_family\"}]}, {\"name\": \"matrix\", \"source\": \"matrix_raw\", \"transform\": [{\"type\": \"lookup\", \"from\": \"family_order\", \"key\": \"app_family\", \"fields\": [\"app_family\"], \"values\": [\"rank\", \"app_family_short\", \"family_total_cost\"], \"as\": [\"rank\", \"app_family_short\", \"family_total_cost\"]}, {\"type\": \"filter\", \"expr\": \"isValid(datum.rank)\"}]}], \"scales\": [{\"name\": \"xscale\", \"type\": \"band\", \"domain\": [\"LEGACY\", \"CLASSICAL\"], \"range\": \"width\", \"paddingInner\": 0.08, \"paddingOuter\": 0.03}, {\"name\": \"yscale\", \"type\": \"band\", \"domain\": {\"data\": \"family_order\", \"field\": \"app_family_short\"}, \"range\": \"height\", \"paddingInner\": 0.08, \"paddingOuter\": 0.03}, {\"name\": \"cscale\", \"type\": \"linear\", \"domain\": {\"data\": \"matrix\", \"field\": \"cost\"}, \"range\": [\"#1f2937\", \"#2563eb\", \"#7c3aed\", \"#dc2626\"], \"nice\": true, \"zero\": true}], \"axes\": [{\"orient\": \"bottom\", \"scale\": \"xscale\", \"title\": \"Tier\", \"titleColor\": \"#d1d5db\", \"labelColor\": \"#d1d5db\", \"tickColor\": \"#333333\", \"domainColor\": \"#333333\"}, {\"orient\": \"left\", \"scale\": \"yscale\", \"title\": \"\", \"labelColor\": \"#d1d5db\", \"labelLimit\": 86, \"tickColor\": \"#333333\", \"domainColor\": \"#333333\"}], \"legends\": [{\"fill\": \"cscale\", \"title\": \"Cost\", \"orient\": \"right\", \"titleColor\": \"#d1d5db\", \"labelColor\": \"#9ca3af\", \"format\": \"$,.2s\"}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"y\": {\"value\": -12}, \"text\": {\"value\": \"PRIORITY MATRIX (TOP APP FAMILIES)\"}, \"fill\": {\"value\": \"#d1d5db\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"matrix\"}, \"encode\": {\"enter\": {\"x\": {\"scale\": \"xscale\", \"field\": \"tier\"}, \"y\": {\"scale\": \"yscale\", \"field\": \"app_family_short\"}, \"width\": {\"scale\": \"xscale\", \"band\": 1}, \"height\": {\"scale\": \"yscale\", \"band\": 1}, \"fill\": {\"scale\": \"cscale\", \"field\": \"cost\"}, \"stroke\": {\"value\": \"#1a1a1a\"}, \"strokeWidth\": {\"value\": 1}, \"tooltip\": {\"signal\": \"{'App Family': datum.app_family, 'Tier': datum.tier, 'Total Cost': '$' + format(datum.cost, ',.0f'), 'Instances': format(datum.instances, ',.0f')}\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"matrix\"}, \"encode\": {\"enter\": {\"x\": {\"scale\": \"xscale\", \"field\": \"tier\", \"band\": 0.5}, \"y\": {\"scale\": \"yscale\", \"field\": \"app_family_short\", \"band\": 0.5}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#f9fafb\"}, \"text\": {\"signal\": \"showCellText && datum.instances > 0 ? format(datum.instances, ',.0f') : ''\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('matrix_raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('matrix_raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -350,7 +350,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-21T14:29:29.805Z", + "created_at": "2026-07-20T16:55:14.701Z", "id": "tychon_quantum_command-02366033-dee4-4ea4-8458-7c8a8b58987e-cost-analysis", "references": [ { @@ -396,4 +396,4 @@ ], "type": "dashboard", "typeMigrationVersion": "10.3.0" -} \ No newline at end of file +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json index d5af6d21c6f..14bda842ce2 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory.json @@ -105,7 +105,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"totalHosts\",\n \"update\": \"length(data('hosts_total'))\u003e0 ? data('hosts_total')[0].n : 0\"\n },\n {\n \"name\": \"osReady\",\n \"update\": \"length(data('os_pqc'))\u003e0 ? data('os_pqc')[0].n : 0\"\n },\n {\n \"name\": \"osPct\",\n \"update\": \"totalHosts \u003e 0 ? round(osReady / totalHosts * 100) : 0\"\n },\n {\n \"name\": \"osClr\",\n \"update\": \"osPct\u003e=90 ? '#00c853' : osPct\u003e=60 ? '#448aff' : osPct\u003e=30 ? '#ffa726' : '#ef5350'\"\n },\n {\n \"name\": \"kexReady\",\n \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"\n },\n {\n \"name\": \"kexPct\",\n \"update\": \"totalHosts \u003e 0 ? round(kexReady / totalHosts * 100) : 0\"\n },\n {\n \"name\": \"kexClr\",\n \"update\": \"kexPct\u003e=90 ? '#00c853' : kexPct\u003e=60 ? '#448aff' : kexPct\u003e=30 ? '#ffa726' : '#ef5350'\"\n },\n {\n \"name\": \"barW\",\n \"update\": \"width * 0.62 - 18\"\n }\n ],\n \"data\": [\n {\n \"name\": \"hosts_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"host.id\"}}}}\n },\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}\n ]\n },\n {\n \"name\": \"hosts_total\",\n \"source\": \"hosts_raw\"\n },\n {\n \"name\": \"os_pqc_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"host.os_pqc_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}\n ]\n },\n {\n \"name\": \"os_pqc\",\n \"source\": \"os_pqc_raw\"\n },\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}\n ]\n },\n {\n \"name\": \"kex_pqc\",\n \"source\": \"kex_pqc_raw\"\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 22},\n \"text\": {\"value\": \"QUANTUM READINESS REPORT\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 40},\n \"text\": {\"value\": \"PQC COMPLIANCE PROGRESS — unique hosts at PQC READY tier\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"osClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 78},\n \"text\": {\"value\": \"OS READINESS\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 93},\n \"text\": {\"signal\": \"(osReady\u003e=1000?format(osReady,'.3~s'):format(osReady,',')) + ' of ' + (totalHosts\u003e=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106},\n \"width\": {\"signal\": \"max(0, barW * osPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"osClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"osPct + '%'\"},\n \"fill\": {\"signal\": \"osClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 158},\n \"text\": {\"value\": \"KEY EXCHANGE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 173},\n \"text\": {\"signal\": \"(kexReady\u003e=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalHosts\u003e=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186},\n \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"totalHosts\", \"update\": \"length(data('hosts_total'))>0 ? data('hosts_total')[0].n : 0\"}, {\"name\": \"osReady\", \"update\": \"length(data('os_pqc'))>0 ? data('os_pqc')[0].n : 0\"}, {\"name\": \"osPct\", \"update\": \"totalHosts > 0 ? round(osReady / totalHosts * 100) : 0\"}, {\"name\": \"osClr\", \"update\": \"osPct>=90 ? '#00c853' : osPct>=60 ? '#448aff' : osPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\"}, {\"name\": \"kexPct\", \"update\": \"totalHosts > 0 ? round(kexReady / totalHosts * 100) : 0\"}, {\"name\": \"kexClr\", \"update\": \"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"barW\", \"update\": \"width * 0.62 - 18\"}], \"data\": [{\"name\": \"hosts_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"host.id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"hosts_total\", \"source\": \"hosts_raw\"}, {\"name\": \"os_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"host.os_pqc_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"os_pqc\", \"source\": \"os_pqc_raw\"}, {\"name\": \"kex_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 22}, \"text\": {\"value\": \"QUANTUM READINESS REPORT\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 40}, \"text\": {\"value\": \"PQC COMPLIANCE PROGRESS \\u2014 unique hosts at PQC READY tier\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"osClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 78}, \"text\": {\"value\": \"OS READINESS\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 93}, \"text\": {\"signal\": \"(osReady>=1000?format(osReady,'.3~s'):format(osReady,',')) + ' of ' + (totalHosts>=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"max(0, barW * osPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"osClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122}, \"text\": {\"signal\": \"osPct + '%'\"}, \"fill\": {\"signal\": \"osClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"kexClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 158}, \"text\": {\"value\": \"KEY EXCHANGE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 173}, \"text\": {\"signal\": \"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalHosts>=1000?format(totalHosts,'.3~s'):format(totalHosts,',')) + ' hosts'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"kexClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202}, \"text\": {\"signal\": \"kexPct + '%'\"}, \"fill\": {\"signal\": \"kexClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('hosts_raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('hosts_raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -159,7 +159,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\"name\": \"headerH\", \"value\": 48},\n {\"name\": \"maxR\", \"update\": \"min(width * 0.36, (height - headerH) / 2 - 10)\"},\n {\"name\": \"cx\", \"update\": \"width * 0.40\"},\n {\"name\": \"cy\", \"update\": \"headerH + (height - headerH) / 2\"},\n {\"name\": \"startA\", \"value\": -1.5707963},\n {\"name\": \"pi2\", \"value\": 6.2831853},\n {\"name\": \"lx\", \"update\": \"cx + maxR + 18\"},\n\n {\"name\": \"hostsTotal\", \"update\": \"length(data('hosts_total'))\u003e0 ? data('hosts_total')[0].n : 0\"},\n {\"name\": \"appsTotal\", \"update\": \"length(data('apps_total'))\u003e0 ? data('apps_total')[0].n : 0\"},\n\n {\"name\": \"osReady\", \"update\": \"length(data('os_pqc'))\u003e0 ? data('os_pqc')[0].n : 0\"},\n {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"},\n {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))\u003e0 ? data('sig_pqc')[0].n : 0\"},\n {\"name\": \"tlsReady\", \"update\": \"length(data('tls_pqc'))\u003e0 ? data('tls_pqc')[0].n : 0\"},\n\n {\"name\": \"osPct\", \"update\": \"hostsTotal \u003e 0 ? round(osReady / hostsTotal * 100) : 0\"},\n {\"name\": \"kexPct\", \"update\": \"appsTotal \u003e 0 ? round(kexReady / appsTotal * 100) : 0\"},\n {\"name\": \"sigPct\", \"update\": \"appsTotal \u003e 0 ? round(sigReady / appsTotal * 100) : 0\"},\n {\"name\": \"tlsPct\", \"update\": \"appsTotal \u003e 0 ? round(tlsReady / appsTotal * 100) : 0\"},\n\n {\"name\": \"overallPct\", \"update\": \"round((osPct + kexPct + sigPct + tlsPct) / 4)\"},\n\n {\"name\": \"osClr\", \"update\": \"osPct\u003e=90?'#00c853':osPct\u003e=60?'#448aff':osPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"kexClr\", \"update\": \"kexPct\u003e=90?'#00c853':kexPct\u003e=60?'#448aff':kexPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"sigClr\", \"update\": \"sigPct\u003e=90?'#00c853':sigPct\u003e=60?'#448aff':sigPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"tlsClr\", \"update\": \"tlsPct\u003e=90?'#00c853':tlsPct\u003e=60?'#448aff':tlsPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"overallClr\", \"update\": \"overallPct\u003e=90?'#00c853':overallPct\u003e=60?'#448aff':overallPct\u003e=30?'#ffa726':'#ef5350'\"},\n {\"name\": \"overallLbl\", \"update\": \"overallPct\u003e=90?'PQC READY':overallPct\u003e=60?'MODERN':overallPct\u003e=30?'CLASSICAL':'LEGACY'\"},\n\n {\"name\": \"lg\", \"update\": \"(height - headerH) / 5\"},\n {\"name\": \"ly0\", \"update\": \"headerH + lg * 0.8\"},\n {\"name\": \"ly1\", \"update\": \"headerH + lg * 1.8\"},\n {\"name\": \"ly2\", \"update\": \"headerH + lg * 2.8\"},\n {\"name\": \"ly3\", \"update\": \"headerH + lg * 3.8\"}\n ],\n \"data\": [\n {\n \"name\": \"hosts_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"host.id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"hosts_total\", \"source\": \"hosts_raw\"},\n {\n \"name\": \"apps_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"apps_total\", \"source\": \"apps_raw\"},\n {\n \"name\": \"os_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"host.os_pqc_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"os_pqc\", \"source\": \"os_pqc_raw\"},\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"},\n {\n \"name\": \"sig_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"},\n {\n \"name\": \"tls_pqc_raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}},\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"tls_pqc\", \"source\": \"tls_pqc_raw\"}\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 20},\n \"text\": {\"value\": \"CRYPTO POSTURE\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 38},\n \"text\": {\"value\": \"4-DIMENSION PQC READINESS SCORE\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 46},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.875\"}, \"outerRadius\": {\"signal\": \"maxR\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.875\"}, \"outerRadius\": {\"signal\": \"maxR\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"osPct \u003e 0 ? startA + osPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"osClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.655\"}, \"outerRadius\": {\"signal\": \"maxR * 0.8\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.655\"}, \"outerRadius\": {\"signal\": \"maxR * 0.8\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"kexPct \u003e 0 ? startA + kexPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"kexClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.435\"}, \"outerRadius\": {\"signal\": \"maxR * 0.58\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.435\"}, \"outerRadius\": {\"signal\": \"maxR * 0.58\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"sigPct \u003e 0 ? startA + sigPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"sigClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.215\"}, \"outerRadius\": {\"signal\": \"maxR * 0.36\"},\n \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.7123890},\n \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}\n }}\n },\n {\n \"type\": \"arc\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"maxR * 0.215\"}, \"outerRadius\": {\"signal\": \"maxR * 0.36\"},\n \"startAngle\": {\"signal\": \"startA\"},\n \"endAngle\": {\"signal\": \"tlsPct \u003e 0 ? startA + tlsPct/100 * pi2 : startA\"},\n \"fill\": {\"signal\": \"tlsClr\"}, \"cornerRadius\": {\"value\": 3}\n }}\n },\n\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + maxR * 0.06\"},\n \"text\": {\"signal\": \"overallPct + '%'\"},\n \"fill\": {\"signal\": \"overallClr\"},\n \"fontSize\": {\"signal\": \"max(14, maxR * 0.21)\"},\n \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"},\n \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + maxR * 0.24\"},\n \"text\": {\"value\": \"OVERALL\"},\n \"fill\": {\"value\": \"#2e2e2e\"}, \"fontSize\": {\"value\": 8},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy - maxR * 0.1\"},\n \"text\": {\"signal\": \"overallLbl\"},\n \"fill\": {\"signal\": \"overallClr + '44'\"},\n \"fontSize\": {\"value\": 7}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.5}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly0\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"osClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly0 + 12\"},\n \"text\": {\"value\": \"OS PLATFORM\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly0 + 26\"},\n \"text\": {\"value\": \"by host\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly0 + 20\"},\n \"text\": {\"signal\": \"osPct + '%'\"},\n \"fill\": {\"signal\": \"osClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly1\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly1 + 12\"},\n \"text\": {\"value\": \"KEY EXCHANGE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly1 + 26\"},\n \"text\": {\"value\": \"by application\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly1 + 20\"},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly2\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly2 + 12\"},\n \"text\": {\"value\": \"CERT SIGNATURE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly2 + 26\"},\n \"text\": {\"value\": \"by application\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly2 + 20\"},\n \"text\": {\"signal\": \"sigPct + '%'\"},\n \"fill\": {\"signal\": \"sigClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly3\"},\n \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"},\n \"fill\": {\"signal\": \"tlsClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly3 + 12\"},\n \"text\": {\"value\": \"TLS VERSION\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly3 + 26\"},\n \"text\": {\"value\": \"TLS 1.3 required\"},\n \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly3 + 20\"},\n \"text\": {\"signal\": \"tlsPct + '%'\"},\n \"fill\": {\"signal\": \"tlsClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"headerH\", \"value\": 48}, {\"name\": \"maxR\", \"update\": \"min(width * 0.36, (height - headerH) / 2 - 10)\"}, {\"name\": \"cx\", \"update\": \"width * 0.40\"}, {\"name\": \"cy\", \"update\": \"headerH + (height - headerH) / 2\"}, {\"name\": \"startA\", \"value\": -1.5707963}, {\"name\": \"pi2\", \"value\": 6.2831853}, {\"name\": \"lx\", \"update\": \"cx + maxR + 18\"}, {\"name\": \"hostsTotal\", \"update\": \"length(data('hosts_total'))>0 ? data('hosts_total')[0].n : 0\"}, {\"name\": \"appsTotal\", \"update\": \"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\"}, {\"name\": \"osReady\", \"update\": \"length(data('os_pqc'))>0 ? data('os_pqc')[0].n : 0\"}, {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\"}, {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\"}, {\"name\": \"tlsReady\", \"update\": \"length(data('tls_pqc'))>0 ? data('tls_pqc')[0].n : 0\"}, {\"name\": \"osPct\", \"update\": \"hostsTotal > 0 ? round(osReady / hostsTotal * 100) : 0\"}, {\"name\": \"kexPct\", \"update\": \"appsTotal > 0 ? round(kexReady / appsTotal * 100) : 0\"}, {\"name\": \"sigPct\", \"update\": \"appsTotal > 0 ? round(sigReady / appsTotal * 100) : 0\"}, {\"name\": \"tlsPct\", \"update\": \"appsTotal > 0 ? round(tlsReady / appsTotal * 100) : 0\"}, {\"name\": \"overallPct\", \"update\": \"round((osPct + kexPct + sigPct + tlsPct) / 4)\"}, {\"name\": \"osClr\", \"update\": \"osPct>=90?'#00c853':osPct>=60?'#448aff':osPct>=30?'#ffa726':'#ef5350'\"}, {\"name\": \"kexClr\", \"update\": \"kexPct>=90?'#00c853':kexPct>=60?'#448aff':kexPct>=30?'#ffa726':'#ef5350'\"}, {\"name\": \"sigClr\", \"update\": \"sigPct>=90?'#00c853':sigPct>=60?'#448aff':sigPct>=30?'#ffa726':'#ef5350'\"}, {\"name\": \"tlsClr\", \"update\": \"tlsPct>=90?'#00c853':tlsPct>=60?'#448aff':tlsPct>=30?'#ffa726':'#ef5350'\"}, {\"name\": \"overallClr\", \"update\": \"overallPct>=90?'#00c853':overallPct>=60?'#448aff':overallPct>=30?'#ffa726':'#ef5350'\"}, {\"name\": \"overallLbl\", \"update\": \"overallPct>=90?'PQC READY':overallPct>=60?'MODERN':overallPct>=30?'CLASSICAL':'LEGACY'\"}, {\"name\": \"lg\", \"update\": \"(height - headerH) / 5\"}, {\"name\": \"ly0\", \"update\": \"headerH + lg * 0.8\"}, {\"name\": \"ly1\", \"update\": \"headerH + lg * 1.8\"}, {\"name\": \"ly2\", \"update\": \"headerH + lg * 2.8\"}, {\"name\": \"ly3\", \"update\": \"headerH + lg * 3.8\"}], \"data\": [{\"name\": \"hosts_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"host.id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"hosts_total\", \"source\": \"hosts_raw\"}, {\"name\": \"apps_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"apps_total\", \"source\": \"apps_raw\"}, {\"name\": \"os_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"host.os_pqc_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"os_pqc\", \"source\": \"os_pqc_raw\"}, {\"name\": \"kex_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"}, {\"name\": \"sig_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"}, {\"name\": \"tls_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"tls_pqc\", \"source\": \"tls_pqc_raw\"}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 20}, \"text\": {\"value\": \"CRYPTO POSTURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"4-DIMENSION PQC READINESS SCORE\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 46}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.875\"}, \"outerRadius\": {\"signal\": \"maxR\"}, \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.712389}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.875\"}, \"outerRadius\": {\"signal\": \"maxR\"}, \"startAngle\": {\"signal\": \"startA\"}, \"endAngle\": {\"signal\": \"osPct > 0 ? startA + osPct/100 * pi2 : startA\"}, \"fill\": {\"signal\": \"osClr\"}, \"cornerRadius\": {\"value\": 3}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.655\"}, \"outerRadius\": {\"signal\": \"maxR * 0.8\"}, \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.712389}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.655\"}, \"outerRadius\": {\"signal\": \"maxR * 0.8\"}, \"startAngle\": {\"signal\": \"startA\"}, \"endAngle\": {\"signal\": \"kexPct > 0 ? startA + kexPct/100 * pi2 : startA\"}, \"fill\": {\"signal\": \"kexClr\"}, \"cornerRadius\": {\"value\": 3}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.435\"}, \"outerRadius\": {\"signal\": \"maxR * 0.58\"}, \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.712389}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.435\"}, \"outerRadius\": {\"signal\": \"maxR * 0.58\"}, \"startAngle\": {\"signal\": \"startA\"}, \"endAngle\": {\"signal\": \"sigPct > 0 ? startA + sigPct/100 * pi2 : startA\"}, \"fill\": {\"signal\": \"sigClr\"}, \"cornerRadius\": {\"value\": 3}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.215\"}, \"outerRadius\": {\"signal\": \"maxR * 0.36\"}, \"startAngle\": {\"value\": -1.5707963}, \"endAngle\": {\"value\": 4.712389}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 0.5}}}}, {\"type\": \"arc\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"maxR * 0.215\"}, \"outerRadius\": {\"signal\": \"maxR * 0.36\"}, \"startAngle\": {\"signal\": \"startA\"}, \"endAngle\": {\"signal\": \"tlsPct > 0 ? startA + tlsPct/100 * pi2 : startA\"}, \"fill\": {\"signal\": \"tlsClr\"}, \"cornerRadius\": {\"value\": 3}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + maxR * 0.06\"}, \"text\": {\"signal\": \"overallPct + '%'\"}, \"fill\": {\"signal\": \"overallClr\"}, \"fontSize\": {\"signal\": \"max(14, maxR * 0.21)\"}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + maxR * 0.24\"}, \"text\": {\"value\": \"OVERALL\"}, \"fill\": {\"value\": \"#2e2e2e\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy - maxR * 0.1\"}, \"text\": {\"signal\": \"overallLbl\"}, \"fill\": {\"signal\": \"overallClr + '44'\"}, \"fontSize\": {\"value\": 7}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.5}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly0\"}, \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"}, \"fill\": {\"signal\": \"osClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly0 + 12\"}, \"text\": {\"value\": \"OS PLATFORM\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly0 + 26\"}, \"text\": {\"value\": \"by host\"}, \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly0 + 20\"}, \"text\": {\"signal\": \"osPct + '%'\"}, \"fill\": {\"signal\": \"osClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly1\"}, \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"}, \"fill\": {\"signal\": \"kexClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly1 + 12\"}, \"text\": {\"value\": \"KEY EXCHANGE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly1 + 26\"}, \"text\": {\"value\": \"by application\"}, \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly1 + 20\"}, \"text\": {\"signal\": \"kexPct + '%'\"}, \"fill\": {\"signal\": \"kexClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly2\"}, \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"}, \"fill\": {\"signal\": \"sigClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly2 + 12\"}, \"text\": {\"value\": \"CERT SIGNATURE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly2 + 26\"}, \"text\": {\"value\": \"by application\"}, \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly2 + 20\"}, \"text\": {\"signal\": \"sigPct + '%'\"}, \"fill\": {\"signal\": \"sigClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx\"}, \"y\": {\"signal\": \"ly3\"}, \"width\": {\"value\": 3}, \"height\": {\"signal\": \"lg * 0.6\"}, \"fill\": {\"signal\": \"tlsClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly3 + 12\"}, \"text\": {\"value\": \"TLS VERSION\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"lx + 9\"}, \"y\": {\"signal\": \"ly3 + 26\"}, \"text\": {\"value\": \"TLS 1.3 required\"}, \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 12\"}, \"y\": {\"signal\": \"ly3 + 20\"}, \"text\": {\"signal\": \"tlsPct + '%'\"}, \"fill\": {\"signal\": \"tlsClr\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('hosts_raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('hosts_raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -213,7 +213,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum — harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve — quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH — quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy — deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum \\u2014 harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve \\u2014 quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH \\u2014 quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy \\u2014 deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "Quantum Inventory Report", "type": "vega", @@ -251,7 +251,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.protocol_tier\", \"size\": 50}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"TLS 1.3\", \"lbl\": \"TLS 1.3\", \"desc\": \"Required for PQC key exchange — carries ML-KEM key_share\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"TLS 1.2\", \"lbl\": \"TLS 1.2\", \"desc\": \"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\", \"badge\": \"NO KEM EXT\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1},\n {\"t\": \"LEGACY\", \"lbl\": \"TLS 1.1 or below\", \"desc\": \"Deprecated — contains known protocol vulnerabilities, should be disabled\", \"badge\": \"DEPRECATED\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"TLS PROTOCOL VERSION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"PREFERRED PROTOCOL — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.protocol_tier\", \"size\": 50}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"TLS 1.3\", \"lbl\": \"TLS 1.3\", \"desc\": \"Required for PQC key exchange \\u2014 carries ML-KEM key_share\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"TLS 1.2\", \"lbl\": \"TLS 1.2\", \"desc\": \"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\", \"badge\": \"NO KEM EXT\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}, {\"t\": \"LEGACY\", \"lbl\": \"TLS 1.1 or below\", \"desc\": \"Deprecated \\u2014 contains known protocol vulnerabilities, should be disabled\", \"badge\": \"DEPRECATED\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"TLS PROTOCOL VERSION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"PREFERRED PROTOCOL \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -289,7 +289,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 20}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature — quantum-resistant\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve signature — efficient, quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA signature — quantum-vulnerable via Shor's algorithm\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"Broken hash — deprecated by all modern standards\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 20}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature \\u2014 quantum-resistant\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve signature \\u2014 efficient, quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA signature \\u2014 quantum-vulnerable via Shor's algorithm\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"Broken hash \\u2014 deprecated by all modern standards\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -327,7 +327,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Windows 10\", \"Windows 11\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"Windows 11\", \"lbl\": \"Windows 11\", \"desc\": \"ML-KEM hybrid KEX in Schannel TLS 1.3 (24H2 / build 26100+) — native PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"Windows 10\", \"lbl\": \"Windows 10\", \"desc\": \"TLS 1.3 capable — no native PQC algorithm support in any release\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"WINDOWS WORKSTATIONS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Windows 10\", \"Windows 11\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"Windows 11\", \"lbl\": \"Windows 11\", \"desc\": \"ML-KEM hybrid KEX in Schannel TLS 1.3 (24H2 / build 26100+) \\u2014 native PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"Windows 10\", \"lbl\": \"Windows 10\", \"desc\": \"TLS 1.3 capable \\u2014 no native PQC algorithm support in any release\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"WINDOWS WORKSTATIONS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -365,7 +365,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Server 2025\", \"Server 2022\", \"Server 2019\", \"Server 2016\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"Server 2025\", \"lbl\": \"Windows Server 2025\", \"desc\": \"PQC-capable — ML-KEM and ML-DSA available via Windows CNG\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"Server 2022\", \"lbl\": \"Windows Server 2022\", \"desc\": \"TLS 1.3 default — no native PQC algorithm support in CNG\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"Server 2019\", \"lbl\": \"Windows Server 2019\", \"desc\": \"TLS 1.2/1.3 supported — no PQC, mainstream support ends Jan 2029\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"Server 2016\", \"lbl\": \"Windows Server 2016\", \"desc\": \"TLS 1.2 only — no PQC support, mainstream support ended Jan 2022\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"WINDOWS SERVER\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Server 2025\", \"Server 2022\", \"Server 2019\", \"Server 2016\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"Server 2025\", \"lbl\": \"Windows Server 2025\", \"desc\": \"PQC-capable \\u2014 ML-KEM and ML-DSA available via Windows CNG\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"Server 2022\", \"lbl\": \"Windows Server 2022\", \"desc\": \"TLS 1.3 default \\u2014 no native PQC algorithm support in CNG\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"Server 2019\", \"lbl\": \"Windows Server 2019\", \"desc\": \"TLS 1.2/1.3 supported \\u2014 no PQC, mainstream support ends Jan 2029\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2}, {\"t\": \"Server 2016\", \"lbl\": \"Windows Server 2016\", \"desc\": \"TLS 1.2 only \\u2014 no PQC support, mainstream support ended Jan 2022\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"WINDOWS SERVER\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -403,7 +403,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"macOS 26\", \"macOS 15\", \"macOS 14\", \"macOS 13\", \"macOS 12\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"macOS 26\", \"lbl\": \"macOS 26 Tahoe\", \"desc\": \"ML-KEM, ML-DSA, SLH-DSA native via Security.framework — full PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"macOS 15\", \"lbl\": \"macOS 15 Sequoia\", \"desc\": \"ML-KEM hybrid KEX via Network.framework — partial PQC, not FIPS 203/204 compliant\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"macOS 14\", \"lbl\": \"macOS 14 Sonoma\", \"desc\": \"TLS 1.3 default — no native PQC algorithm support in Security.framework\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2},\n {\"t\": \"macOS 13\", \"lbl\": \"macOS 13 Ventura\", \"desc\": \"TLS 1.3 default — no native PQC algorithm support in Security.framework\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 3},\n {\"t\": \"macOS 12\", \"lbl\": \"macOS 12 Monterey\", \"desc\": \"TLS 1.3 capable — older cipher defaults, no PQC support\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 4}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"MACOS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"macOS 26\", \"macOS 15\", \"macOS 14\", \"macOS 13\", \"macOS 12\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"macOS 26\", \"lbl\": \"macOS 26 Tahoe\", \"desc\": \"ML-KEM, ML-DSA, SLH-DSA native via Security.framework \\u2014 full PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"macOS 15\", \"lbl\": \"macOS 15 Sequoia\", \"desc\": \"ML-KEM hybrid KEX via Network.framework \\u2014 partial PQC, not FIPS 203/204 compliant\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"macOS 14\", \"lbl\": \"macOS 14 Sonoma\", \"desc\": \"TLS 1.3 default \\u2014 no native PQC algorithm support in Security.framework\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2}, {\"t\": \"macOS 13\", \"lbl\": \"macOS 13 Ventura\", \"desc\": \"TLS 1.3 default \\u2014 no native PQC algorithm support in Security.framework\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 3}, {\"t\": \"macOS 12\", \"lbl\": \"macOS 12 Monterey\", \"desc\": \"TLS 1.3 capable \\u2014 older cipher defaults, no PQC support\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 4}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"MACOS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -441,7 +441,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"CentOS 9\", \"CentOS 8\", \"CentOS 7\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"CentOS 9\", \"lbl\": \"CentOS Stream 9\", \"desc\": \"OpenSSL 3.x — TLS 1.3 default, OQS PQC provider available\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 0},\n {\"t\": \"CentOS 8\", \"lbl\": \"CentOS Stream 8\", \"desc\": \"EOL May 2024 — OpenSSL 1.1.1, TLS 1.3 supported, no PQC\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 1},\n {\"t\": \"CentOS 7\", \"lbl\": \"CentOS 7\", \"desc\": \"EOL Jun 2024 — OpenSSL 1.0.2, TLS 1.2 only, no PQC support\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CENTOS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"CentOS 9\", \"CentOS 8\", \"CentOS 7\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"CentOS 9\", \"lbl\": \"CentOS Stream 9\", \"desc\": \"OpenSSL 3.x \\u2014 TLS 1.3 default, OQS PQC provider available\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 0}, {\"t\": \"CentOS 8\", \"lbl\": \"CentOS Stream 8\", \"desc\": \"EOL May 2024 \\u2014 OpenSSL 1.1.1, TLS 1.3 supported, no PQC\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 1}, {\"t\": \"CentOS 7\", \"lbl\": \"CentOS 7\", \"desc\": \"EOL Jun 2024 \\u2014 OpenSSL 1.0.2, TLS 1.2 only, no PQC support\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CENTOS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"\\u2026\", \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"\\u2026\", \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -479,7 +479,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"RHEL 10\", \"RHEL 9\", \"RHEL 8\", \"RHEL 7\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"RHEL 10\", \"lbl\": \"RHEL 10\", \"desc\": \"OpenSSL 3.5.x — ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"RHEL 9\", \"lbl\": \"RHEL 9\", \"desc\": \"OpenSSL 3.x — TLS 1.3 default, OQS PQC provider available separately\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"RHEL 8\", \"lbl\": \"RHEL 8\", \"desc\": \"OpenSSL 1.1.1 — TLS 1.3 supported, no native PQC support\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"RHEL 7\", \"lbl\": \"RHEL 7\", \"desc\": \"OpenSSL 1.0.2 — EOL Jun 2024, TLS 1.2 only, no PQC support\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"RED HAT ENTERPRISE LINUX\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"RHEL 10\", \"RHEL 9\", \"RHEL 8\", \"RHEL 7\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"RHEL 10\", \"lbl\": \"RHEL 10\", \"desc\": \"OpenSSL 3.5.x \\u2014 ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"RHEL 9\", \"lbl\": \"RHEL 9\", \"desc\": \"OpenSSL 3.x \\u2014 TLS 1.3 default, OQS PQC provider available separately\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"RHEL 8\", \"lbl\": \"RHEL 8\", \"desc\": \"OpenSSL 1.1.1 \\u2014 TLS 1.3 supported, no native PQC support\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2}, {\"t\": \"RHEL 7\", \"lbl\": \"RHEL 7\", \"desc\": \"OpenSSL 1.0.2 \\u2014 EOL Jun 2024, TLS 1.2 only, no PQC support\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"RED HAT ENTERPRISE LINUX\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"\\u2026\", \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"\\u2026\", \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -517,7 +517,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Ubuntu 26.04\", \"Ubuntu 25.04\", \"Ubuntu 24.04\", \"Ubuntu 22.04\", \"Ubuntu 20.04\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"Ubuntu 26.04\", \"lbl\": \"Ubuntu 26.04 LTS\", \"desc\": \"OpenSSL 3.5.x — ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"Ubuntu 25.04\", \"lbl\": \"Ubuntu 25.04\", \"desc\": \"OpenSSL 3.4.x — ML-KEM/ML-DSA built-in, NIST PQC without oqs-provider\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 1},\n {\"t\": \"Ubuntu 24.04\", \"lbl\": \"Ubuntu 24.04 LTS\", \"desc\": \"OpenSSL 3.0.x — TLS 1.3 default, OQS PQC provider available separately\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2},\n {\"t\": \"Ubuntu 22.04\", \"lbl\": \"Ubuntu 22.04 LTS\", \"desc\": \"OpenSSL 3.0.x — TLS 1.3 default, no native PQC support\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 3},\n {\"t\": \"Ubuntu 20.04\", \"lbl\": \"Ubuntu 20.04 LTS\", \"desc\": \"OpenSSL 1.1.1 — TLS 1.3 capable, standard support ends Apr 2025\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 4}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"UBUNTU\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"…\",\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'host.os_category': datum.t}}) : kibanaAddFilter({'match_phrase': {'host.os_category': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"host.os_category\", \"size\": 20, \"include\": [\"Ubuntu 26.04\", \"Ubuntu 25.04\", \"Ubuntu 24.04\", \"Ubuntu 22.04\", \"Ubuntu 20.04\"]}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"Ubuntu 26.04\", \"lbl\": \"Ubuntu 26.04 LTS\", \"desc\": \"OpenSSL 3.5.x \\u2014 ML-KEM/ML-DSA/SLH-DSA built-in, full NIST PQC support\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"Ubuntu 25.04\", \"lbl\": \"Ubuntu 25.04\", \"desc\": \"OpenSSL 3.4.x \\u2014 ML-KEM/ML-DSA built-in, NIST PQC without oqs-provider\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 1}, {\"t\": \"Ubuntu 24.04\", \"lbl\": \"Ubuntu 24.04 LTS\", \"desc\": \"OpenSSL 3.0.x \\u2014 TLS 1.3 default, OQS PQC provider available separately\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2}, {\"t\": \"Ubuntu 22.04\", \"lbl\": \"Ubuntu 22.04 LTS\", \"desc\": \"OpenSSL 3.0.x \\u2014 TLS 1.3 default, no native PQC support\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 3}, {\"t\": \"Ubuntu 20.04\", \"lbl\": \"Ubuntu 20.04 LTS\", \"desc\": \"OpenSSL 1.1.1 \\u2014 TLS 1.3 capable, standard support ends Apr 2025\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 4}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"UBUNTU\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"OS VERSION \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"\\u2026\", \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.60-18\"}, \"ellipsis\": \"\\u2026\", \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -540,7 +540,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-21T14:29:29.805Z", + "created_at": "2026-07-20T16:55:14.701Z", "id": "tychon_quantum_command-32c01eb5-0d80-4a28-9de7-55b2046f7c45-inventory", "references": [ { @@ -576,4 +576,4 @@ ], "type": "dashboard", "typeMigrationVersion": "10.3.0" -} \ No newline at end of file +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json index 31c979f6f1d..28e8e762ef0 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report.json @@ -89,7 +89,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum — harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve — quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH — quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy — deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum \\u2014 harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve \\u2014 quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH \\u2014 quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy \\u2014 deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -128,7 +128,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\"name\": \"totalApps\", \"update\": \"length(data('apps_total'))\u003e0 ? data('apps_total')[0].n : 0\"},\n {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"},\n {\"name\": \"kexPct\", \"update\": \"totalApps \u003e 0 ? round(kexReady / totalApps * 100) : 0\"},\n {\"name\": \"kexClr\", \"update\": \"kexPct\u003e=90 ? '#00c853' : kexPct\u003e=60 ? '#448aff' : kexPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"protoReady\", \"update\": \"length(data('proto_pqc'))\u003e0 ? data('proto_pqc')[0].n : 0\"},\n {\"name\": \"protoPct\", \"update\": \"totalApps \u003e 0 ? round(protoReady / totalApps * 100) : 0\"},\n {\"name\": \"protoClr\", \"update\": \"protoPct\u003e=90 ? '#00c853' : protoPct\u003e=60 ? '#448aff' : protoPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))\u003e0 ? data('sig_pqc')[0].n : 0\"},\n {\"name\": \"sigPct\", \"update\": \"totalApps \u003e 0 ? round(sigReady / totalApps * 100) : 0\"},\n {\"name\": \"sigClr\", \"update\": \"sigPct\u003e=90 ? '#00c853' : sigPct\u003e=60 ? '#448aff' : sigPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"barW\", \"update\": \"width * 0.62 - 18\"}\n ],\n \"data\": [\n {\n \"name\": \"apps_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}\n },\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"apps_total\", \"source\": \"apps_raw\"},\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"},\n {\n \"name\": \"proto_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"proto_pqc\", \"source\": \"proto_pqc_raw\"},\n {\n \"name\": \"sig_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"}\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 22},\n \"text\": {\"value\": \"APPLICATION PQC DASHBOARD\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 40},\n \"text\": {\"signal\": \"'PQC COMPLIANCE PROGRESS — ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 78},\n \"text\": {\"value\": \"KEX COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 93},\n \"text\": {\"signal\": \"(kexReady\u003e=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY key exchange'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106},\n \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 158},\n \"text\": {\"value\": \"PROTOCOL COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 173},\n \"text\": {\"signal\": \"(protoReady\u003e=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — TLS 1.3 capable'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186},\n \"width\": {\"signal\": \"max(0, barW * protoPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202},\n \"text\": {\"signal\": \"protoPct + '%'\"},\n \"fill\": {\"signal\": \"protoClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 218},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 238},\n \"text\": {\"value\": \"CERT SIGNATURE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 253},\n \"text\": {\"signal\": \"(sigReady\u003e=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY signature'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266},\n \"width\": {\"signal\": \"max(0, barW * sigPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 282},\n \"text\": {\"signal\": \"sigPct + '%'\"},\n \"fill\": {\"signal\": \"sigClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"totalApps\", \"update\": \"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\"}, {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\"}, {\"name\": \"kexPct\", \"update\": \"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\"}, {\"name\": \"kexClr\", \"update\": \"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"protoReady\", \"update\": \"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\"}, {\"name\": \"protoPct\", \"update\": \"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\"}, {\"name\": \"protoClr\", \"update\": \"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\"}, {\"name\": \"sigPct\", \"update\": \"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\"}, {\"name\": \"sigClr\", \"update\": \"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"barW\", \"update\": \"width * 0.62 - 18\"}], \"data\": [{\"name\": \"apps_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"apps_total\", \"source\": \"apps_raw\"}, {\"name\": \"kex_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"}, {\"name\": \"proto_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"proto_pqc\", \"source\": \"proto_pqc_raw\"}, {\"name\": \"sig_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 22}, \"text\": {\"value\": \"APPLICATION PQC DASHBOARD\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 40}, \"text\": {\"signal\": \"'PQC COMPLIANCE PROGRESS \\u2014 ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"kexClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 78}, \"text\": {\"value\": \"KEX COMPLIANCE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 93}, \"text\": {\"signal\": \"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY key exchange'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"kexClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122}, \"text\": {\"signal\": \"kexPct + '%'\"}, \"fill\": {\"signal\": \"kexClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"protoClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 158}, \"text\": {\"value\": \"PROTOCOL COMPLIANCE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 173}, \"text\": {\"signal\": \"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 TLS 1.3 capable'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"max(0, barW * protoPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"protoClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202}, \"text\": {\"signal\": \"protoPct + '%'\"}, \"fill\": {\"signal\": \"protoClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 218}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"sigClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 238}, \"text\": {\"value\": \"CERT SIGNATURE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 253}, \"text\": {\"signal\": \"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY signature'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"max(0, barW * sigPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"sigClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 282}, \"text\": {\"signal\": \"sigPct + '%'\"}, \"fill\": {\"signal\": \"sigClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('apps_raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('apps_raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -167,7 +167,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 20}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature — quantum-resistant\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve signature — efficient, quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA signature — quantum-vulnerable via Shor's algorithm\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"Broken hash — deprecated by all modern standards\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 20}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature \\u2014 quantum-resistant\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve signature \\u2014 efficient, quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA signature \\u2014 quantum-vulnerable via Shor's algorithm\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"Broken hash \\u2014 deprecated by all modern standards\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -206,7 +206,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [\n {\n \"events\": {\"type\": \"click\", \"markname\": \"rowBg\"},\n \"update\": \"datum.family === sel ? null : datum.family\",\n \"force\": true\n }\n ]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [\n {\n \"events\": {\"type\": \"click\", \"markname\": \"rowBg\"},\n \"update\": \"datum.family === sel ? kibanaRemoveFilter({'terms': {'process.name': datum.filterTerms}}) : kibanaAddFilter({'terms': {'process.name': datum.filterTerms}})\",\n \"force\": true\n }\n ]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"procs\": {\n \"terms\": {\"field\": \"process.name\", \"size\": 80},\n \"aggs\": {\n \"kex\": {\n \"terms\": {\"field\": \"omb.kex_tier\", \"size\": 5},\n \"aggs\": {\"thosts\": {\"cardinality\": {\"field\": \"host.id\"}}}\n }\n }\n }\n }\n }\n },\n \"format\": {\"property\": \"aggregations.procs.buckets\"},\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"family\",\n \"expr\": \"lower(datum.key)==='w3wp.exe'||lower(datum.key)==='iisexpress.exe'||lower(datum.key)==='inetinfo.exe' ? 'IIS' : lower(datum.key)==='node'||lower(datum.key)==='node.exe'||lower(datum.key)==='nodejs'||lower(datum.key)==='nodejs.exe' ? 'Node.js' : lower(datum.key)==='apache2'||lower(datum.key)==='httpd'||lower(datum.key)==='apache'||lower(datum.key)==='httpd.exe'||lower(datum.key)==='apache.exe'||lower(datum.key)==='httpd.worker' ? 'Apache' : lower(datum.key)==='nginx'||lower(datum.key)==='nginx.exe'||lower(datum.key)==='nginx-debug'||lower(datum.key)==='openresty' ? 'Nginx' : lower(datum.key)==='jsvc'||lower(datum.key)==='tomcat'||lower(datum.key)==='tomcat.exe'||lower(datum.key)==='tomcat9'||lower(datum.key)==='tomcat9.exe'||lower(datum.key)==='tomcat10'||lower(datum.key)==='tomcat10.exe'||lower(datum.key)==='tomcat8'||lower(datum.key)==='tomcat8.exe'||lower(datum.key)==='tomcat7'||lower(datum.key)==='tomcat7.exe'||lower(datum.key)==='catalina'||lower(datum.key)==='catalina.sh' ? 'Tomcat' : lower(datum.key)==='dotnet'||lower(datum.key)==='dotnet.exe' ? '.NET / Kestrel' : lower(datum.key)==='caddy'||lower(datum.key)==='caddy.exe' ? 'Caddy' : lower(datum.key)==='traefik'||lower(datum.key)==='traefik.exe' ? 'Traefik' : lower(datum.key)==='haproxy' ? 'HAProxy' : lower(datum.key)==='gunicorn' ? 'Gunicorn' : lower(datum.key)==='uwsgi' ? 'uWSGI' : lower(datum.key)==='puma'||lower(datum.key)==='passenger'||lower(datum.key)==='passenger-ruby' ? 'Puma' : lower(datum.key)==='varnishd' ? 'Varnish' : lower(datum.key)==='lighttpd' ? 'Lighttpd' : lower(datum.key)==='java'||lower(datum.key)==='java.exe'||lower(datum.key)==='javaw.exe' ? 'Java App Server' : 'Other'\"\n },\n {\"type\": \"filter\", \"expr\": \"datum.family != null\"}\n ]\n },\n {\n \"name\": \"mapped\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"flatten\", \"fields\": [\"kex.buckets\"], \"as\": [\"tb\"]},\n {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.tb.key\"},\n {\"type\": \"formula\", \"as\": \"tier_h\", \"expr\": \"datum.tb.thosts ? datum.tb.thosts.value : 0\"},\n {\"type\": \"formula\", \"as\": \"tier_ord\", \"expr\": \"datum.tier==='LEGACY' ? 0 : datum.tier==='CLASSICAL' ? 1 : datum.tier==='MODERN' ? 2 : datum.tier==='PQC READY' ? 3 : 4\"}\n ]\n },\n {\n \"name\": \"by_ft\",\n \"source\": \"mapped\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\", \"tier\", \"tier_ord\"],\n \"fields\": [\"tier_h\"],\n \"ops\": [\"sum\"],\n \"as\": [\"tier_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_totals\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\"],\n \"fields\": [\"tier_total\"],\n \"ops\": [\"sum\"],\n \"as\": [\"fam_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_risk\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\"type\": \"filter\", \"expr\": \"datum.tier === 'LEGACY' || datum.tier === 'CLASSICAL'\"},\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\"],\n \"fields\": [\"tier_total\"],\n \"ops\": [\"sum\"],\n \"as\": [\"risk_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_pqc\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\"type\": \"filter\", \"expr\": \"datum.tier === 'PQC READY'\"},\n {\n \"type\": \"aggregate\",\n \"groupby\": [\"family\"],\n \"fields\": [\"tier_total\"],\n \"ops\": [\"sum\"],\n \"as\": [\"pqc_total\"]\n }\n ]\n },\n {\n \"name\": \"fam_rows\",\n \"source\": \"fam_totals\",\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"fam_risk\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"risk_total\"], \"default\": 0},\n {\"type\": \"lookup\", \"from\": \"fam_pqc\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"pqc_total\"], \"default\": 0},\n {\n \"type\": \"formula\",\n \"as\": \"clr\",\n \"expr\": \"datum.family==='IIS' ? '#0078d4' : datum.family==='Node.js' ? '#68a063' : datum.family==='Apache' ? '#d22128' : datum.family==='Nginx' ? '#009900' : datum.family==='Tomcat' ? '#f8a51a' : datum.family==='.NET / Kestrel' ? '#7b5ea7' : datum.family==='Caddy' ? '#00acd7' : datum.family==='Traefik' ? '#24a1c1' : datum.family==='HAProxy' ? '#7db8e8' : datum.family==='Gunicorn' ? '#499848' : datum.family==='uWSGI' ? '#cc4125' : datum.family==='Puma' ? '#e040fb' : datum.family==='Varnish' ? '#ff6d00' : datum.family==='Lighttpd' ? '#909090' : datum.family==='Java App Server' ? '#c7a008' : '#666666'\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"filterTerms\",\n \"expr\": \"datum.family==='IIS' ? ['w3wp.exe','iisexpress.exe','inetinfo.exe'] : datum.family==='Node.js' ? ['node','node.exe','nodejs','nodejs.exe'] : datum.family==='Apache' ? ['apache2','httpd','apache','httpd.exe','apache.exe','httpd.worker'] : datum.family==='Nginx' ? ['nginx','nginx.exe','nginx-debug','openresty'] : datum.family==='Tomcat' ? ['jsvc','tomcat','tomcat.exe','tomcat9','tomcat9.exe','tomcat10','tomcat10.exe','tomcat8','tomcat8.exe','tomcat7','tomcat7.exe','catalina','catalina.sh'] : datum.family==='.NET / Kestrel' ? ['dotnet','dotnet.exe'] : datum.family==='Caddy' ? ['caddy','caddy.exe'] : datum.family==='Traefik' ? ['traefik','traefik.exe'] : datum.family==='HAProxy' ? ['haproxy'] : datum.family==='Gunicorn' ? ['gunicorn'] : datum.family==='uWSGI' ? ['uwsgi'] : datum.family==='Puma' ? ['puma','passenger','passenger-ruby'] : datum.family==='Varnish' ? ['varnishd'] : datum.family==='Lighttpd' ? ['lighttpd'] : datum.family==='Java App Server' ? ['java','java.exe','javaw.exe'] : [datum.family]\"\n },\n {\"type\": \"collect\", \"sort\": {\"field\": \"risk_total\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rowIdx\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rowIdx - 1) * 38 + 52\"}\n ]\n },\n {\n \"name\": \"stacked\",\n \"source\": \"by_ft\",\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"fam_rows\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"y\", \"fam_total\", \"risk_total\"]},\n {\"type\": \"filter\", \"expr\": \"datum.y != null\"},\n {\"type\": \"formula\", \"as\": \"tier_clr\", \"expr\": \"datum.tier==='LEGACY' ? '#ef5350' : datum.tier==='CLASSICAL' ? '#ffa726' : datum.tier==='MODERN' ? '#42a5f5' : datum.tier==='PQC READY' ? '#66bb6a' : '#555555'\"},\n {\"type\": \"joinaggregate\", \"fields\": [\"fam_total\"], \"ops\": [\"max\"], \"as\": [\"max_fam\"]},\n {\n \"type\": \"window\",\n \"groupby\": [\"family\"],\n \"sort\": {\"field\": \"tier_ord\", \"order\": \"ascending\"},\n \"ops\": [\"sum\"],\n \"fields\": [\"tier_total\"],\n \"as\": [\"cumul\"]\n }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"WEB SERVER DISTRIBUTION\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 30},\n \"text\": {\"value\": \"HOSTS BY SERVER FAMILY \u0026 PQC KEX TIER · sorted by at-risk count · click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 170}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#ef5350\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 180}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"LEGACY\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 228}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#ffa726\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 238}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"CLASSICAL\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 300}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#42a5f5\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 310}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"MODERN\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 362}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#66bb6a\"}, \"cornerRadius\": {\"value\": 1}}}},\n {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 372}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"PQC READY\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}},\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 50},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"name\": \"rowBg\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"},\n \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 37},\n \"fill\": {\"signal\": \"datum.family===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"},\n \"width\": {\"value\": 4}, \"height\": {\"value\": 37},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 14\"},\n \"text\": {\"field\": \"family\"}, \"limit\": {\"value\": 148},\n \"fill\": {\"signal\": \"datum.family===sel ? '#ffffff' : '#e8e8e8'\"},\n \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 170}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"width\": {\"signal\": \"width - 245\"}, \"height\": {\"value\": 8},\n \"fill\": {\"value\": \"#1e1e1e\"}, \"cornerRadius\": {\"value\": 2}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"stacked\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"170 + ((datum.cumul - datum.tier_total) / (datum.max_fam \u003e 0 ? datum.max_fam : 1)) * (width - 245)\"},\n \"x2\": {\"signal\": \"170 + (datum.cumul / (datum.max_fam \u003e 0 ? datum.max_fam : 1)) * (width - 245)\"},\n \"y\": {\"signal\": \"datum.y + 22\"},\n \"height\": {\"value\": 8},\n \"fill\": {\"field\": \"tier_clr\"},\n \"fillOpacity\": {\"signal\": \"datum.family===sel ? 1 : 0.8\"},\n \"cornerRadius\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 14\"},\n \"text\": {\"signal\": \"datum.fam_total \u003e= 1000 ? format(datum.fam_total, '.3~s') : format(datum.fam_total, ',')\"},\n \"fill\": {\"signal\": \"datum.family===sel ? datum.clr : '#cccccc'\"},\n \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"},\n \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 35\"},\n \"text\": {\"signal\": \"datum.risk_total \u003e 0 ? format(datum.risk_total, ',') + ' AT RISK' : datum.pqc_total \u003e 0 ? 'PQC READY' : 'NOT PQC READY'\"},\n \"fill\": {\"signal\": \"datum.risk_total \u003e 0 ? '#ef5350' : datum.pqc_total \u003e 0 ? '#66bb6a' : '#ffa726'\"},\n \"fontSize\": {\"value\": 7}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"},\n \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"fam_rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 37\"},\n \"stroke\": {\"value\": \"#1e1e1e\"}, \"strokeWidth\": {\"value\": 1}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"rowBg\"}, \"update\": \"datum.family === sel ? null : datum.family\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"rowBg\"}, \"update\": \"datum.family === sel ? kibanaRemoveFilter({'terms': {'process.name': datum.filterTerms}}) : kibanaAddFilter({'terms': {'process.name': datum.filterTerms}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc*\", \"body\": {\"size\": 0, \"aggs\": {\"procs\": {\"terms\": {\"field\": \"process.name\", \"size\": 80}, \"aggs\": {\"kex\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 5}, \"aggs\": {\"thosts\": {\"cardinality\": {\"field\": \"host.id\"}}}}}}}}}, \"format\": {\"property\": \"aggregations.procs.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"family\", \"expr\": \"lower(datum.key)==='w3wp.exe'||lower(datum.key)==='iisexpress.exe'||lower(datum.key)==='inetinfo.exe' ? 'IIS' : lower(datum.key)==='node'||lower(datum.key)==='node.exe'||lower(datum.key)==='nodejs'||lower(datum.key)==='nodejs.exe' ? 'Node.js' : lower(datum.key)==='apache2'||lower(datum.key)==='httpd'||lower(datum.key)==='apache'||lower(datum.key)==='httpd.exe'||lower(datum.key)==='apache.exe'||lower(datum.key)==='httpd.worker' ? 'Apache' : lower(datum.key)==='nginx'||lower(datum.key)==='nginx.exe'||lower(datum.key)==='nginx-debug'||lower(datum.key)==='openresty' ? 'Nginx' : lower(datum.key)==='jsvc'||lower(datum.key)==='tomcat'||lower(datum.key)==='tomcat.exe'||lower(datum.key)==='tomcat9'||lower(datum.key)==='tomcat9.exe'||lower(datum.key)==='tomcat10'||lower(datum.key)==='tomcat10.exe'||lower(datum.key)==='tomcat8'||lower(datum.key)==='tomcat8.exe'||lower(datum.key)==='tomcat7'||lower(datum.key)==='tomcat7.exe'||lower(datum.key)==='catalina'||lower(datum.key)==='catalina.sh' ? 'Tomcat' : lower(datum.key)==='dotnet'||lower(datum.key)==='dotnet.exe' ? '.NET / Kestrel' : lower(datum.key)==='caddy'||lower(datum.key)==='caddy.exe' ? 'Caddy' : lower(datum.key)==='traefik'||lower(datum.key)==='traefik.exe' ? 'Traefik' : lower(datum.key)==='haproxy' ? 'HAProxy' : lower(datum.key)==='gunicorn' ? 'Gunicorn' : lower(datum.key)==='uwsgi' ? 'uWSGI' : lower(datum.key)==='puma'||lower(datum.key)==='passenger'||lower(datum.key)==='passenger-ruby' ? 'Puma' : lower(datum.key)==='varnishd' ? 'Varnish' : lower(datum.key)==='lighttpd' ? 'Lighttpd' : lower(datum.key)==='java'||lower(datum.key)==='java.exe'||lower(datum.key)==='javaw.exe' ? 'Java App Server' : 'Other'\"}, {\"type\": \"filter\", \"expr\": \"datum.family != null\"}]}, {\"name\": \"mapped\", \"source\": \"raw\", \"transform\": [{\"type\": \"flatten\", \"fields\": [\"kex.buckets\"], \"as\": [\"tb\"]}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.tb.key\"}, {\"type\": \"formula\", \"as\": \"tier_h\", \"expr\": \"datum.tb.thosts ? datum.tb.thosts.value : 0\"}, {\"type\": \"formula\", \"as\": \"tier_ord\", \"expr\": \"datum.tier==='LEGACY' ? 0 : datum.tier==='CLASSICAL' ? 1 : datum.tier==='MODERN' ? 2 : datum.tier==='PQC READY' ? 3 : 4\"}]}, {\"name\": \"by_ft\", \"source\": \"mapped\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"family\", \"tier\", \"tier_ord\"], \"fields\": [\"tier_h\"], \"ops\": [\"sum\"], \"as\": [\"tier_total\"]}]}, {\"name\": \"fam_totals\", \"source\": \"by_ft\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"family\"], \"fields\": [\"tier_total\"], \"ops\": [\"sum\"], \"as\": [\"fam_total\"]}]}, {\"name\": \"fam_risk\", \"source\": \"by_ft\", \"transform\": [{\"type\": \"filter\", \"expr\": \"datum.tier === 'LEGACY' || datum.tier === 'CLASSICAL'\"}, {\"type\": \"aggregate\", \"groupby\": [\"family\"], \"fields\": [\"tier_total\"], \"ops\": [\"sum\"], \"as\": [\"risk_total\"]}]}, {\"name\": \"fam_pqc\", \"source\": \"by_ft\", \"transform\": [{\"type\": \"filter\", \"expr\": \"datum.tier === 'PQC READY'\"}, {\"type\": \"aggregate\", \"groupby\": [\"family\"], \"fields\": [\"tier_total\"], \"ops\": [\"sum\"], \"as\": [\"pqc_total\"]}]}, {\"name\": \"fam_rows\", \"source\": \"fam_totals\", \"transform\": [{\"type\": \"lookup\", \"from\": \"fam_risk\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"risk_total\"], \"default\": 0}, {\"type\": \"lookup\", \"from\": \"fam_pqc\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"pqc_total\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.family==='IIS' ? '#0078d4' : datum.family==='Node.js' ? '#68a063' : datum.family==='Apache' ? '#d22128' : datum.family==='Nginx' ? '#009900' : datum.family==='Tomcat' ? '#f8a51a' : datum.family==='.NET / Kestrel' ? '#7b5ea7' : datum.family==='Caddy' ? '#00acd7' : datum.family==='Traefik' ? '#24a1c1' : datum.family==='HAProxy' ? '#7db8e8' : datum.family==='Gunicorn' ? '#499848' : datum.family==='uWSGI' ? '#cc4125' : datum.family==='Puma' ? '#e040fb' : datum.family==='Varnish' ? '#ff6d00' : datum.family==='Lighttpd' ? '#909090' : datum.family==='Java App Server' ? '#c7a008' : '#666666'\"}, {\"type\": \"formula\", \"as\": \"filterTerms\", \"expr\": \"datum.family==='IIS' ? ['w3wp.exe','iisexpress.exe','inetinfo.exe'] : datum.family==='Node.js' ? ['node','node.exe','nodejs','nodejs.exe'] : datum.family==='Apache' ? ['apache2','httpd','apache','httpd.exe','apache.exe','httpd.worker'] : datum.family==='Nginx' ? ['nginx','nginx.exe','nginx-debug','openresty'] : datum.family==='Tomcat' ? ['jsvc','tomcat','tomcat.exe','tomcat9','tomcat9.exe','tomcat10','tomcat10.exe','tomcat8','tomcat8.exe','tomcat7','tomcat7.exe','catalina','catalina.sh'] : datum.family==='.NET / Kestrel' ? ['dotnet','dotnet.exe'] : datum.family==='Caddy' ? ['caddy','caddy.exe'] : datum.family==='Traefik' ? ['traefik','traefik.exe'] : datum.family==='HAProxy' ? ['haproxy'] : datum.family==='Gunicorn' ? ['gunicorn'] : datum.family==='uWSGI' ? ['uwsgi'] : datum.family==='Puma' ? ['puma','passenger','passenger-ruby'] : datum.family==='Varnish' ? ['varnishd'] : datum.family==='Lighttpd' ? ['lighttpd'] : datum.family==='Java App Server' ? ['java','java.exe','javaw.exe'] : [datum.family]\"}, {\"type\": \"collect\", \"sort\": {\"field\": \"risk_total\", \"order\": \"descending\"}}, {\"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rowIdx\"]}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rowIdx - 1) * 38 + 52\"}]}, {\"name\": \"stacked\", \"source\": \"by_ft\", \"transform\": [{\"type\": \"lookup\", \"from\": \"fam_rows\", \"key\": \"family\", \"fields\": [\"family\"], \"values\": [\"y\", \"fam_total\", \"risk_total\"]}, {\"type\": \"filter\", \"expr\": \"datum.y != null\"}, {\"type\": \"formula\", \"as\": \"tier_clr\", \"expr\": \"datum.tier==='LEGACY' ? '#ef5350' : datum.tier==='CLASSICAL' ? '#ffa726' : datum.tier==='MODERN' ? '#42a5f5' : datum.tier==='PQC READY' ? '#66bb6a' : '#555555'\"}, {\"type\": \"joinaggregate\", \"fields\": [\"fam_total\"], \"ops\": [\"max\"], \"as\": [\"max_fam\"]}, {\"type\": \"window\", \"groupby\": [\"family\"], \"sort\": {\"field\": \"tier_ord\", \"order\": \"ascending\"}, \"ops\": [\"sum\"], \"fields\": [\"tier_total\"], \"as\": [\"cumul\"]}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"WEB SERVER DISTRIBUTION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 30}, \"text\": {\"value\": \"HOSTS BY SERVER FAMILY & PQC KEX TIER \\u00c2\\u00b7 sorted by at-risk count \\u00c2\\u00b7 click to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 170}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#ef5350\"}, \"cornerRadius\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 180}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"LEGACY\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 228}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#ffa726\"}, \"cornerRadius\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 238}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"CLASSICAL\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 300}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#42a5f5\"}, \"cornerRadius\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 310}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"MODERN\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 362}, \"y\": {\"value\": 37}, \"width\": {\"value\": 7}, \"height\": {\"value\": 6}, \"fill\": {\"value\": \"#66bb6a\"}, \"cornerRadius\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 372}, \"y\": {\"value\": 44}, \"text\": {\"value\": \"PQC READY\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 50}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"rowBg\", \"from\": {\"data\": \"fam_rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 37}, \"fill\": {\"signal\": \"datum.family===sel ? '#1c1c2e' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"fam_rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 37}, \"fill\": {\"field\": \"clr\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"fam_rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 14\"}, \"text\": {\"field\": \"family\"}, \"limit\": {\"value\": 148}, \"fill\": {\"signal\": \"datum.family===sel ? '#ffffff' : '#e8e8e8'\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"fam_rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 170}, \"y\": {\"signal\": \"datum.y + 22\"}, \"width\": {\"signal\": \"width - 245\"}, \"height\": {\"value\": 8}, \"fill\": {\"value\": \"#1e1e1e\"}, \"cornerRadius\": {\"value\": 2}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"stacked\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"170 + ((datum.cumul - datum.tier_total) / (datum.max_fam > 0 ? datum.max_fam : 1)) * (width - 245)\"}, \"x2\": {\"signal\": \"170 + (datum.cumul / (datum.max_fam > 0 ? datum.max_fam : 1)) * (width - 245)\"}, \"y\": {\"signal\": \"datum.y + 22\"}, \"height\": {\"value\": 8}, \"fill\": {\"field\": \"tier_clr\"}, \"fillOpacity\": {\"signal\": \"datum.family===sel ? 1 : 0.8\"}, \"cornerRadius\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"fam_rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 14\"}, \"text\": {\"signal\": \"datum.fam_total >= 1000 ? format(datum.fam_total, '.3~s') : format(datum.fam_total, ',')\"}, \"fill\": {\"signal\": \"datum.family===sel ? datum.clr : '#cccccc'\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"fam_rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 35\"}, \"text\": {\"signal\": \"datum.risk_total > 0 ? format(datum.risk_total, ',') + ' AT RISK' : datum.pqc_total > 0 ? 'PQC READY' : 'NOT PQC READY'\"}, \"fill\": {\"signal\": \"datum.risk_total > 0 ? '#ef5350' : datum.pqc_total > 0 ? '#66bb6a' : '#ffa726'\"}, \"fontSize\": {\"value\": 7}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"fam_rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 37\"}, \"stroke\": {\"value\": \"#1e1e1e\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -2429,7 +2429,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-21T14:29:29.805Z", + "created_at": "2026-07-20T16:55:14.701Z", "id": "tychon_quantum_command-443e5928-b1c4-4e07-b0b9-c675dd057e2f-application-report", "references": [ { @@ -2530,4 +2530,4 @@ ], "type": "dashboard", "typeMigrationVersion": "10.3.0" -} \ No newline at end of file +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json index cf5c2ccb2d3..610f352f268 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail.json @@ -223,7 +223,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum — harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve — quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1},\n {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH — quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2},\n {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy — deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.kex_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.kex_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.kex_tier\", \"size\": 20}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"hcount\", \"expr\": \"datum.u ? datum.u.value : 0\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"hcount\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-KEM / Kyber\", \"desc\": \"Post-quantum \\u2014 harvest-proof\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"X25519 / ECDHE\", \"desc\": \"Elliptic curve \\u2014 quantum-vulnerable\", \"badge\": \"MODERN\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"DHE / DH\", \"desc\": \"Finite-field DH \\u2014 quantum-vulnerable\", \"badge\": \"CLASSICAL\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"RSA Key Exchange\", \"desc\": \"No forward secrecy \\u2014 deprecated\", \"badge\": \"LEGACY\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"POST-QUANTUM CRYPTOGRAPHY READINESS\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"KEY EXCHANGE \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -261,7 +261,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? null : datum.t\",\n \"force\": true\n }]\n },\n {\n \"name\": \"_kf\",\n \"value\": null,\n \"on\": [{\n \"events\": {\"type\": \"click\", \"markname\": \"bg\"},\n \"update\": \"datum.t === sel ? kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\",\n \"force\": true\n }]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.protocol_tier\", \"size\": 50}}}}\n },\n \"format\": {\"property\": \"aggregations.k.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}\n ]\n },\n {\n \"name\": \"tc\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"tc\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"values\": [\n {\"t\": \"TLS 1.3\", \"lbl\": \"TLS 1.3\", \"desc\": \"Required for PQC key exchange — carries ML-KEM key_share\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0},\n {\"t\": \"TLS 1.2\", \"lbl\": \"TLS 1.2\", \"desc\": \"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\", \"badge\": \"NO KEM EXT\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1},\n {\"t\": \"LEGACY\", \"lbl\": \"TLS 1.1 or below\", \"desc\": \"Deprecated — contains known protocol vulnerabilities, should be disabled\", \"badge\": \"DEPRECATED\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}\n ],\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"TLS PROTOCOL VERSION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"PREFERRED PROTOCOL — click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}\n },\n {\n \"type\": \"rect\",\n \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"},\n \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"},\n \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.bg:'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.badge\"},\n \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#383838'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"'#1a1a1a'\"},\n \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"},\n \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"},\n \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n\u003e0?(datum.n\u003e=1000?format(datum.n,'.3~s'):format(datum.n,',')):'—'\"},\n \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n\u003e0?'#dddddd':'#333333'\"},\n \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"↑ at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.protocol_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.protocol_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.protocol_tier\", \"size\": 50}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"doc_count\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"TLS 1.3\", \"lbl\": \"TLS 1.3\", \"desc\": \"Required for PQC key exchange \\u2014 carries ML-KEM key_share\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"TLS 1.2\", \"lbl\": \"TLS 1.2\", \"desc\": \"Supports ECDHE/DHE forward secrecy but not ML-KEM key encapsulation\", \"badge\": \"NO KEM EXT\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}, {\"t\": \"LEGACY\", \"lbl\": \"TLS 1.1 or below\", \"desc\": \"Deprecated \\u2014 contains known protocol vulnerabilities, should be disabled\", \"badge\": \"DEPRECATED\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"TLS PROTOCOL VERSION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"PREFERRED PROTOCOL \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"signal\": \"datum.lbl\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"signal\": \"datum.desc\"}, \"limit\": {\"signal\": \"width*0.62-18\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0?datum.bg:'#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.badge\"}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#383838'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65\"}, \"y\": {\"signal\": \"datum.y + 31\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 17}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"'#1a1a1a'\"}, \"stroke\": {\"signal\": \"'#333333'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width*0.65+41\"}, \"y\": {\"signal\": \"datum.y + 43\"}, \"text\": {\"signal\": \"datum.t===sel?'SELECTED':''\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:'#448aff'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width-10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n>0?(datum.n>=1000?format(datum.n,'.3~s'):format(datum.n,',')):'\\u2014'\"}, \"fill\": {\"signal\": \"datum.t===sel?datum.clr:datum.n>0?'#dddddd':'#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"signal\": \"width/2\"}, \"y\": {\"signal\": \"height-8\"}, \"text\": {\"value\": \"\\u2191 at the highest tier\"}, \"fill\": {\"value\": \"#2a2a2a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "", "type": "vega", @@ -2146,7 +2146,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-21T14:29:29.805Z", + "created_at": "2026-07-20T16:55:14.701Z", "id": "tychon_quantum_command-6dfff015-3cc9-48b6-9410-7d8c01ff0d9a-application-detail", "references": [ { @@ -2232,4 +2232,4 @@ ], "type": "dashboard", "typeMigrationVersion": "10.3.0" -} \ No newline at end of file +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json index 1f769e63c22..8367d66a43d 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology.json @@ -107,7 +107,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"Application filter list panel (multi-select) with dashboard filter integration.\",\n \"autosize\": \"fit\",\n \"padding\": 10,\n \"background\": \"#000000\",\n \"signals\": [\n {\n \"name\": \"selectedApps\",\n \"value\": \"|\",\n \"on\": [\n {\n \"events\": \"@appRowBg:click\",\n \"update\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? replace(selectedApps, '|' + datum.app + '|', '|') : selectedApps + datum.app + '|'\"\n }\n ]\n },\n {\n \"name\": \"selectedAppsArray\",\n \"update\": \"selectedApps == '|' ? [] : split(slice(selectedApps, 1, length(selectedApps)-1), '|')\"\n },\n {\n \"name\": \"activeFilter\",\n \"update\": \"length(selectedAppsArray) \u003e 0 ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'terms': {'tychon.application.name': selectedAppsArray}}]}} : {'term': {'event.dataset': 'tychon.application'}}\"\n },\n {\n \"name\": \"_applyAppFilter\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"@applyBtn:click\",\n \"update\": \"kibanaAddFilter(activeFilter)\",\n \"force\": true\n }\n ]\n }\n ],\n \"data\": [\n {\n \"name\": \"apps\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-applications\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"app_only\": {\n \"filter\": { \"term\": { \"event.dataset\": \"tychon.application\" } },\n \"aggs\": {\n \"app_names\": {\n \"terms\": {\n \"field\": \"tychon.application.name\",\n \"size\": 200,\n \"order\": { \"_count\": \"desc\" }\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.app_only.app_names.buckets\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"app\", \"expr\": \"datum.key\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"datum.doc_count\" },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rn\"] },\n { \"type\": \"formula\", \"as\": \"y\", \"expr\": \"72 + (datum.rn - 1) * 26\" },\n { \"type\": \"filter\", \"expr\": \"datum.rn \u003c= 15\" }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"signal\": \"height - 10\" },\n \"fill\": { \"value\": \"#0f1115\" },\n \"fillOpacity\": { \"value\": 0.96 },\n \"stroke\": { \"value\": \"#2b3440\" },\n \"strokeWidth\": { \"value\": 1.2 },\n \"cornerRadius\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"value\": 42 },\n \"fill\": { \"value\": \"#17324a\" },\n \"fillOpacity\": { \"value\": 0.92 },\n \"cornerRadiusTopLeft\": { \"value\": 8 },\n \"cornerRadiusTopRight\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 24 },\n \"y\": { \"value\": 30 },\n \"text\": { \"value\": \"APPLICATION FILTER\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 12 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#e8f3ff\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"name\": \"applyBtn\",\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"width - 92\" },\n \"y\": { \"value\": 16 },\n \"width\": { \"value\": 76 },\n \"height\": { \"value\": 20 },\n \"cornerRadius\": { \"value\": 10 },\n \"fill\": { \"value\": \"#17324a\" },\n \"stroke\": { \"value\": \"#9fd7ff\" },\n \"strokeWidth\": { \"value\": 1 },\n \"cursor\": { \"value\": \"pointer\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"width - 54\" },\n \"y\": { \"value\": 26 },\n \"text\": { \"value\": \"APPLY\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#dff0ff\" },\n \"align\": { \"value\": \"center\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"from\": { \"data\": \"apps\" },\n \"name\": \"appRowBg\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 18 },\n \"y\": { \"signal\": \"datum.y - 10\" },\n \"x2\": { \"signal\": \"width - 18\" },\n \"y2\": { \"signal\": \"datum.y + 10\" },\n \"cornerRadius\": { \"value\": 6 },\n \"fill\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#1f4d74' : '#0f1115'\" },\n \"stroke\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#9fd7ff' : '#253241'\" },\n \"strokeWidth\": { \"value\": 1 },\n \"cursor\": { \"value\": \"pointer\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"apps\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 30 },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"field\": \"app\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#e8f3ff' : '#c9d7e5'\" },\n \"baseline\": { \"value\": \"middle\" },\n \"limit\": { \"signal\": \"width - 110\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"apps\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"width - 30\" },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"signal\": \"format(datum.count, ',')\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"signal\": \"indexof(selectedApps, '|' + datum.app + '|') \u003e= 0 ? '#d9eeff' : '#8ea3b8'\" },\n \"align\": { \"value\": \"right\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n }\n ]\n}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"Application filter list panel (multi-select) with dashboard filter integration.\", \"autosize\": \"fit\", \"padding\": 10, \"background\": \"#000000\", \"signals\": [{\"name\": \"selectedApps\", \"value\": \"|\", \"on\": [{\"events\": \"@appRowBg:click\", \"update\": \"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? replace(selectedApps, '|' + datum.app + '|', '|') : selectedApps + datum.app + '|'\"}]}, {\"name\": \"selectedAppsArray\", \"update\": \"selectedApps == '|' ? [] : split(slice(selectedApps, 1, length(selectedApps)-1), '|')\"}, {\"name\": \"activeFilter\", \"update\": \"length(selectedAppsArray) > 0 ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'terms': {'tychon.application.name': selectedAppsArray}}]}} : {'term': {'event.dataset': 'tychon.application'}}\"}, {\"name\": \"_applyAppFilter\", \"value\": 0, \"on\": [{\"events\": \"@applyBtn:click\", \"update\": \"kibanaAddFilter(activeFilter)\", \"force\": true}]}], \"data\": [{\"name\": \"apps\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-applications\", \"body\": {\"size\": 0, \"aggs\": {\"app_only\": {\"filter\": {\"term\": {\"event.dataset\": \"tychon.application\"}}, \"aggs\": {\"app_names\": {\"terms\": {\"field\": \"tychon.application.name\", \"size\": 200, \"order\": {\"_count\": \"desc\"}}}}}}}}, \"format\": {\"property\": \"aggregations.app_only.app_names.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"app\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"count\", \"expr\": \"datum.doc_count\"}, {\"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rn\"]}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"72 + (datum.rn - 1) * 26\"}, {\"type\": \"filter\", \"expr\": \"datum.rn <= 15\"}]}], \"marks\": [{\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 10}, \"y\": {\"value\": 10}, \"x2\": {\"signal\": \"width - 10\"}, \"y2\": {\"signal\": \"height - 10\"}, \"fill\": {\"value\": \"#0f1115\"}, \"fillOpacity\": {\"value\": 0.96}, \"stroke\": {\"value\": \"#2b3440\"}, \"strokeWidth\": {\"value\": 1.2}, \"cornerRadius\": {\"value\": 8}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 10}, \"y\": {\"value\": 10}, \"x2\": {\"signal\": \"width - 10\"}, \"y2\": {\"value\": 42}, \"fill\": {\"value\": \"#17324a\"}, \"fillOpacity\": {\"value\": 0.92}, \"cornerRadiusTopLeft\": {\"value\": 8}, \"cornerRadiusTopRight\": {\"value\": 8}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 24}, \"y\": {\"value\": 30}, \"text\": {\"value\": \"APPLICATION FILTER\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#e8f3ff\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"rect\", \"name\": \"applyBtn\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 92\"}, \"y\": {\"value\": 16}, \"width\": {\"value\": 76}, \"height\": {\"value\": 20}, \"cornerRadius\": {\"value\": 10}, \"fill\": {\"value\": \"#17324a\"}, \"stroke\": {\"value\": \"#9fd7ff\"}, \"strokeWidth\": {\"value\": 1}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 54\"}, \"y\": {\"value\": 26}, \"text\": {\"value\": \"APPLY\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#dff0ff\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"apps\"}, \"name\": \"appRowBg\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"signal\": \"datum.y - 10\"}, \"x2\": {\"signal\": \"width - 18\"}, \"y2\": {\"signal\": \"datum.y + 10\"}, \"cornerRadius\": {\"value\": 6}, \"fill\": {\"signal\": \"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#1f4d74' : '#0f1115'\"}, \"stroke\": {\"signal\": \"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#9fd7ff' : '#253241'\"}, \"strokeWidth\": {\"value\": 1}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"apps\"}, \"encode\": {\"update\": {\"x\": {\"value\": 30}, \"y\": {\"field\": \"y\"}, \"text\": {\"field\": \"app\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"signal\": \"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#e8f3ff' : '#c9d7e5'\"}, \"baseline\": {\"value\": \"middle\"}, \"limit\": {\"signal\": \"width - 110\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"apps\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 30\"}, \"y\": {\"field\": \"y\"}, \"text\": {\"signal\": \"format(datum.count, ',')\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"signal\": \"indexof(selectedApps, '|' + datum.app + '|') >= 0 ? '#d9eeff' : '#8ea3b8'\"}, \"align\": {\"value\": \"right\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('apps')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('apps')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "QuantumApplicationList", "type": "vega", @@ -148,7 +148,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"autosize\": \"fit\",\n \"padding\": 8,\n \"background\": \"#000000\",\n \"signals\": [\n {\n \"name\": \"zoom\",\n \"value\": 0.55,\n \"on\": [\n {\n \"events\": { \"type\": \"wheel\" },\n \"update\": \"clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6)\"\n }\n ]\n },\n {\n \"name\": \"panX\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": { \"type\": \"wheel\" },\n \"update\": \"((panX - (width/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (width/2)\"\n },\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"mousemove\",\n \"between\": [\n { \"source\": \"view\", \"type\": \"mousedown\" },\n { \"source\": \"window\", \"type\": \"mouseup\" }\n ]\n },\n \"update\": \"panX + event.movementX\"\n }\n ]\n },\n {\n \"name\": \"panY\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": { \"type\": \"wheel\" },\n \"update\": \"((panY - (height/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (height/2)\"\n },\n {\n \"events\": {\n \"source\": \"window\",\n \"type\": \"mousemove\",\n \"between\": [\n { \"source\": \"view\", \"type\": \"mousedown\" },\n { \"source\": \"window\", \"type\": \"mouseup\" }\n ]\n },\n \"update\": \"panY + event.movementY\"\n }\n ]\n },\n {\n \"name\": \"selectedNode\",\n \"value\": null,\n \"on\": [\n {\n \"events\": \"@nodeMark:click\",\n \"update\": \"datum \u0026\u0026 isValid(datum.id) ? (selectedNode \u0026\u0026 selectedNode.id===datum.id ? null : datum) : selectedNode\"\n }\n ]\n },\n {\n \"name\": \"_applyNodeFilter\",\n \"value\": 0,\n \"on\": [\n {\n \"events\": \"@nodeMark:dblclick\",\n \"update\": \"datum \u0026\u0026 isValid(datum.id) ? kibanaAddFilter((datum.nodeType === 'application' ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'tychon.application.name': toString(datum.id)}}]}} : {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'host.hostname': toString(datum.id)}}]}})) : 0\",\n \"force\": true\n }\n ]\n },\n {\n \"name\": \"adjPeerIds\",\n \"update\": \"isArray(data('adjacency')) ? pluck(data('adjacency'), 'peer') : []\"\n },\n {\n \"name\": \"adjPeer2Ids\",\n \"update\": \"isArray(data('adjacency2')) ? pluck(data('adjacency2'), 'peer') : []\"\n },\n {\n \"name\": \"highlightNodeIdsCsv\",\n \"update\": \"selectedNode ? (',' + toString(selectedNode.id) + ',' + join(adjPeerIds, ',') + ',' + join(adjPeer2Ids, ',') + ',') : ''\"\n },\n {\n \"name\": \"autoPanX\",\n \"update\": \"length(data('layout_center')) \u003e 0 \u0026\u0026 isFinite(data('layout_center')[0].cx) ? (width * 0.5) - (data('layout_center')[0].cx * zoom) : (width * (1 - zoom) * 0.5)\"\n },\n {\n \"name\": \"autoPanY\",\n \"update\": \"length(data('layout_center')) \u003e 0 \u0026\u0026 isFinite(data('layout_center')[0].cy) ? (height * 0.52) - (data('layout_center')[0].cy * zoom) : (height * (1 - zoom) * 0.5)\"\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-applications\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"pairs\": {\n \"filter\": {\n \"bool\": {\n \"must\": [\n { \"exists\": { \"field\": \"host.hostname\" } },\n { \"exists\": { \"field\": \"tychon.application.name\" } },\n { \"term\": { \"event.dataset\": \"tychon.application\" } }\n ]\n }\n },\n \"aggs\": {\n \"links\": {\n \"composite\": {\n \"size\": 500,\n \"sources\": [\n { \"src\": { \"terms\": { \"field\": \"host.hostname\" } } },\n { \"dst\": { \"terms\": { \"field\": \"tychon.application.name\" } } }\n ]\n }\n }\n }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations.pairs.links.buckets\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"datum.key.src\" },\n { \"type\": \"formula\", \"as\": \"target\", \"expr\": \"datum.key.dst\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"toNumber(datum.doc_count)\" },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.target) \u0026\u0026 datum.source!='' \u0026\u0026 datum.target!=''\" }\n ]\n },\n {\n \"name\": \"nodes\",\n \"source\": \"raw\",\n \"transform\": [\n { \"type\": \"fold\", \"fields\": [\"source\", \"target\"], \"as\": [\"side\", \"id\"] },\n { \"type\": \"aggregate\", \"groupby\": [\"id\", \"side\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"] },\n { \"type\": \"formula\", \"as\": \"nodeType\", \"expr\": \"datum.side==='source' ? 'host' : 'application'\" }\n ]\n },\n {\n \"name\": \"edges\",\n \"source\": \"raw\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"source\", \"expr\": \"toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"target\", \"expr\": \"toString(datum.target)\" },\n { \"type\": \"formula\", \"as\": \"count\", \"expr\": \"toNumber(datum.count)\" },\n { \"type\": \"filter\", \"expr\": \"datum.source != '' \u0026\u0026 datum.target != ''\" }\n ]\n },\n {\n \"name\": \"layout\",\n \"source\": \"nodes\",\n \"transform\": [\n {\n \"type\": \"force\",\n \"iterations\": 300,\n \"static\": true,\n \"forces\": [\n { \"force\": \"center\", \"x\": { \"signal\": \"width * 0.5\" }, \"y\": { \"signal\": \"height * 0.52\" } },\n { \"force\": \"collide\", \"radius\": 20 },\n { \"force\": \"nbody\", \"strength\": -180 },\n { \"force\": \"link\", \"links\": \"edges\", \"id\": \"id\", \"distance\": 130 }\n ]\n }\n ]\n },\n {\n \"name\": \"layout_center\",\n \"source\": \"layout\",\n \"transform\": [\n {\n \"type\": \"aggregate\",\n \"ops\": [\"median\", \"median\"],\n \"fields\": [\"x\", \"y\"],\n \"as\": [\"cx\", \"cy\"]\n },\n { \"type\": \"formula\", \"as\": \"cx\", \"expr\": \"isFinite(datum.cx) ? datum.cx : 0\" },\n { \"type\": \"formula\", \"as\": \"cy\", \"expr\": \"isFinite(datum.cy) ? datum.cy : 0\" }\n ]\n },\n {\n \"name\": \"edges_draw\",\n \"source\": \"edges\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\" },\n { \"type\": \"formula\", \"as\": \"sx\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.x) ? datum.source.x * zoom + autoPanX + panX : null\" },\n { \"type\": \"formula\", \"as\": \"sy\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.y) ? datum.source.y * zoom + autoPanY + panY : null\" },\n { \"type\": \"formula\", \"as\": \"tx\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.x) ? datum.target.x * zoom + autoPanX + panX : null\" },\n { \"type\": \"formula\", \"as\": \"ty\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.y) ? datum.target.y * zoom + autoPanY + panY : null\" },\n { \"type\": \"filter\", \"expr\": \"isValid(datum.sx) \u0026\u0026 isValid(datum.sy) \u0026\u0026 isValid(datum.tx) \u0026\u0026 isValid(datum.ty)\" }\n ]\n },\n {\n \"name\": \"adjacency\",\n \"source\": \"edges\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\" },\n { \"type\": \"filter\", \"expr\": \"selectedNode \u0026\u0026 (datum.srcId===toString(selectedNode.id) || datum.dstId===toString(selectedNode.id))\" },\n { \"type\": \"fold\", \"fields\": [\"srcId\", \"dstId\"], \"as\": [\"side\", \"peer\"] },\n { \"type\": \"filter\", \"expr\": \"datum.peer !== toString(selectedNode.id)\" },\n { \"type\": \"aggregate\", \"groupby\": [\"peer\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"] }\n ]\n },\n {\n \"name\": \"adjacency2\",\n \"source\": \"edges\",\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) \u0026\u0026 isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\" },\n { \"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) \u0026\u0026 isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\" },\n { \"type\": \"filter\", \"expr\": \"selectedNode \u0026\u0026 (indexof(adjPeerIds, datum.srcId) \u003e= 0 || indexof(adjPeerIds, datum.dstId) \u003e= 0)\" },\n { \"type\": \"fold\", \"fields\": [\"srcId\", \"dstId\"], \"as\": [\"side\", \"peer\"] },\n { \"type\": \"filter\", \"expr\": \"datum.peer !== toString(selectedNode.id) \u0026\u0026 indexof(adjPeerIds, datum.peer) \u003c 0\" },\n { \"type\": \"aggregate\", \"groupby\": [\"peer\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"] }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": {\n \"enter\": {\n \"x\": { \"value\": 0 },\n \"y\": { \"value\": 0 },\n \"x2\": { \"signal\": \"width\" },\n \"y2\": { \"signal\": \"height\" },\n \"fill\": { \"value\": \"#000000\" }\n }\n }\n },\n {\n \"type\": \"rule\",\n \"from\": { \"data\": \"edges_draw\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"field\": \"sx\" },\n \"y\": { \"field\": \"sy\" },\n \"x2\": { \"field\": \"tx\" },\n \"y2\": { \"field\": \"ty\" },\n \"stroke\": {\n \"signal\": \"!selectedNode ? '#4fc3f7' : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') \u003e= 0 \u0026\u0026 indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') \u003e= 0) ? '#7fe8ff' : '#213240')\"\n },\n \"strokeOpacity\": {\n \"signal\": \"!selectedNode ? 0.42 : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') \u003e= 0 \u0026\u0026 indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') \u003e= 0) ? 0.75 : 0.08)\"\n },\n \"strokeWidth\": { \"value\": 0.9 }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"from\": { \"data\": \"layout\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"datum.x * zoom + autoPanX + panX\" },\n \"y\": { \"signal\": \"datum.y * zoom + autoPanY + panY\" },\n \"size\": { \"value\": 980 },\n \"fill\": { \"signal\": \"datum.nodeType==='application' ? '#3b2b1a' : '#1a2c3b'\" },\n \"fillOpacity\": { \"value\": 0.9 },\n \"stroke\": { \"signal\": \"datum.nodeType==='application' ? '#ffd7a2' : '#a9dbff'\" },\n \"strokeWidth\": { \"value\": 1.2 },\n \"opacity\": { \"signal\": \"!selectedNode ? 1 : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') \u003e= 0 ? 1 : 0.2)\" }\n }\n }\n },\n {\n \"type\": \"symbol\",\n \"name\": \"nodeMark\",\n \"from\": { \"data\": \"layout\" },\n \"encode\": {\n \"enter\": {\n \"size\": { \"value\": 980 },\n \"fill\": { \"value\": \"#000000\" },\n \"fillOpacity\": { \"value\": 0.001 },\n \"stroke\": { \"value\": \"#000000\" },\n \"strokeOpacity\": { \"value\": 0.001 },\n \"cursor\": { \"value\": \"pointer\" }\n },\n \"update\": {\n \"x\": { \"signal\": \"datum.x * zoom + autoPanX + panX\" },\n \"y\": { \"signal\": \"datum.y * zoom + autoPanY + panY\" },\n \"size\": { \"value\": 980 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"layout\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"datum.x * zoom + autoPanX + panX\" },\n \"y\": { \"signal\": \"datum.y * zoom + autoPanY + panY - 14\" },\n \"text\": { \"field\": \"id\" },\n \"fill\": { \"signal\": \"!selectedNode ? '#e0e0e0' : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') \u003e= 0 ? '#f2f7ff' : '#4f5f6f')\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 9 },\n \"align\": { \"value\": \"center\" },\n \"baseline\": { \"value\": \"bottom\" }\n }\n }\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"autosize\": \"fit\", \"padding\": 8, \"background\": \"#000000\", \"signals\": [{\"name\": \"zoom\", \"value\": 0.55, \"on\": [{\"events\": {\"type\": \"wheel\"}, \"update\": \"clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6)\"}]}, {\"name\": \"panX\", \"value\": 0, \"on\": [{\"events\": {\"type\": \"wheel\"}, \"update\": \"((panX - (width/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (width/2)\"}, {\"events\": {\"source\": \"window\", \"type\": \"mousemove\", \"between\": [{\"source\": \"view\", \"type\": \"mousedown\"}, {\"source\": \"window\", \"type\": \"mouseup\"}]}, \"update\": \"panX + event.movementX\"}]}, {\"name\": \"panY\", \"value\": 0, \"on\": [{\"events\": {\"type\": \"wheel\"}, \"update\": \"((panY - (height/2)) * (clamp(zoom * pow(1.0015, -event.deltaY), 0.55, 2.6) / zoom)) + (height/2)\"}, {\"events\": {\"source\": \"window\", \"type\": \"mousemove\", \"between\": [{\"source\": \"view\", \"type\": \"mousedown\"}, {\"source\": \"window\", \"type\": \"mouseup\"}]}, \"update\": \"panY + event.movementY\"}]}, {\"name\": \"selectedNode\", \"value\": null, \"on\": [{\"events\": \"@nodeMark:click\", \"update\": \"datum && isValid(datum.id) ? (selectedNode && selectedNode.id===datum.id ? null : datum) : selectedNode\"}]}, {\"name\": \"_applyNodeFilter\", \"value\": 0, \"on\": [{\"events\": \"@nodeMark:dblclick\", \"update\": \"datum && isValid(datum.id) ? kibanaAddFilter((datum.nodeType === 'application' ? {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'tychon.application.name': toString(datum.id)}}]}} : {'bool': {'filter': [{'term': {'event.dataset': 'tychon.application'}}, {'term': {'host.hostname': toString(datum.id)}}]}})) : 0\", \"force\": true}]}, {\"name\": \"adjPeerIds\", \"update\": \"isArray(data('adjacency')) ? pluck(data('adjacency'), 'peer') : []\"}, {\"name\": \"adjPeer2Ids\", \"update\": \"isArray(data('adjacency2')) ? pluck(data('adjacency2'), 'peer') : []\"}, {\"name\": \"highlightNodeIdsCsv\", \"update\": \"selectedNode ? (',' + toString(selectedNode.id) + ',' + join(adjPeerIds, ',') + ',' + join(adjPeer2Ids, ',') + ',') : ''\"}, {\"name\": \"autoPanX\", \"update\": \"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cx) ? (width * 0.5) - (data('layout_center')[0].cx * zoom) : (width * (1 - zoom) * 0.5)\"}, {\"name\": \"autoPanY\", \"update\": \"length(data('layout_center')) > 0 && isFinite(data('layout_center')[0].cy) ? (height * 0.52) - (data('layout_center')[0].cy * zoom) : (height * (1 - zoom) * 0.5)\"}, {\"name\": \"rawBucketLimitReached\", \"update\": \"length(data('raw')) >= 500\"}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-applications\", \"body\": {\"size\": 0, \"aggs\": {\"pairs\": {\"filter\": {\"bool\": {\"must\": [{\"exists\": {\"field\": \"host.hostname\"}}, {\"exists\": {\"field\": \"tychon.application.name\"}}, {\"term\": {\"event.dataset\": \"tychon.application\"}}]}}, \"aggs\": {\"links\": {\"composite\": {\"size\": 500, \"sources\": [{\"src\": {\"terms\": {\"field\": \"host.hostname\"}}}, {\"dst\": {\"terms\": {\"field\": \"tychon.application.name\"}}}]}}}}}}}, \"format\": {\"property\": \"aggregations.pairs.links.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"source\", \"expr\": \"datum.key.src\"}, {\"type\": \"formula\", \"as\": \"target\", \"expr\": \"datum.key.dst\"}, {\"type\": \"formula\", \"as\": \"count\", \"expr\": \"toNumber(datum.doc_count)\"}, {\"type\": \"filter\", \"expr\": \"isValid(datum.source) && isValid(datum.target) && datum.source!='' && datum.target!=''\"}]}, {\"name\": \"nodes\", \"source\": \"raw\", \"transform\": [{\"type\": \"fold\", \"fields\": [\"source\", \"target\"], \"as\": [\"side\", \"id\"]}, {\"type\": \"aggregate\", \"groupby\": [\"id\", \"side\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"]}, {\"type\": \"formula\", \"as\": \"nodeType\", \"expr\": \"datum.side==='source' ? 'host' : 'application'\"}]}, {\"name\": \"edges\", \"source\": \"raw\", \"transform\": [{\"type\": \"formula\", \"as\": \"source\", \"expr\": \"toString(datum.source)\"}, {\"type\": \"formula\", \"as\": \"target\", \"expr\": \"toString(datum.target)\"}, {\"type\": \"formula\", \"as\": \"count\", \"expr\": \"toNumber(datum.count)\"}, {\"type\": \"filter\", \"expr\": \"datum.source != '' && datum.target != ''\"}]}, {\"name\": \"layout\", \"source\": \"nodes\", \"transform\": [{\"type\": \"force\", \"iterations\": 300, \"static\": true, \"forces\": [{\"force\": \"center\", \"x\": {\"signal\": \"width * 0.5\"}, \"y\": {\"signal\": \"height * 0.52\"}}, {\"force\": \"collide\", \"radius\": 20}, {\"force\": \"nbody\", \"strength\": -180}, {\"force\": \"link\", \"links\": \"edges\", \"id\": \"id\", \"distance\": 130}]}]}, {\"name\": \"layout_center\", \"source\": \"layout\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"median\", \"median\"], \"fields\": [\"x\", \"y\"], \"as\": [\"cx\", \"cy\"]}, {\"type\": \"formula\", \"as\": \"cx\", \"expr\": \"isFinite(datum.cx) ? datum.cx : 0\"}, {\"type\": \"formula\", \"as\": \"cy\", \"expr\": \"isFinite(datum.cy) ? datum.cy : 0\"}]}, {\"name\": \"edges_draw\", \"source\": \"edges\", \"transform\": [{\"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\"}, {\"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\"}, {\"type\": \"formula\", \"as\": \"sx\", \"expr\": \"isValid(datum.source) && isValid(datum.source.x) ? datum.source.x * zoom + autoPanX + panX : null\"}, {\"type\": \"formula\", \"as\": \"sy\", \"expr\": \"isValid(datum.source) && isValid(datum.source.y) ? datum.source.y * zoom + autoPanY + panY : null\"}, {\"type\": \"formula\", \"as\": \"tx\", \"expr\": \"isValid(datum.target) && isValid(datum.target.x) ? datum.target.x * zoom + autoPanX + panX : null\"}, {\"type\": \"formula\", \"as\": \"ty\", \"expr\": \"isValid(datum.target) && isValid(datum.target.y) ? datum.target.y * zoom + autoPanY + panY : null\"}, {\"type\": \"filter\", \"expr\": \"isValid(datum.sx) && isValid(datum.sy) && isValid(datum.tx) && isValid(datum.ty)\"}]}, {\"name\": \"adjacency\", \"source\": \"edges\", \"transform\": [{\"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\"}, {\"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\"}, {\"type\": \"filter\", \"expr\": \"selectedNode && (datum.srcId===toString(selectedNode.id) || datum.dstId===toString(selectedNode.id))\"}, {\"type\": \"fold\", \"fields\": [\"srcId\", \"dstId\"], \"as\": [\"side\", \"peer\"]}, {\"type\": \"filter\", \"expr\": \"datum.peer !== toString(selectedNode.id)\"}, {\"type\": \"aggregate\", \"groupby\": [\"peer\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"]}]}, {\"name\": \"adjacency2\", \"source\": \"edges\", \"transform\": [{\"type\": \"formula\", \"as\": \"srcId\", \"expr\": \"isValid(datum.source) && isValid(datum.source.id) ? toString(datum.source.id) : toString(datum.source)\"}, {\"type\": \"formula\", \"as\": \"dstId\", \"expr\": \"isValid(datum.target) && isValid(datum.target.id) ? toString(datum.target.id) : toString(datum.target)\"}, {\"type\": \"filter\", \"expr\": \"selectedNode && (indexof(adjPeerIds, datum.srcId) >= 0 || indexof(adjPeerIds, datum.dstId) >= 0)\"}, {\"type\": \"fold\", \"fields\": [\"srcId\", \"dstId\"], \"as\": [\"side\", \"peer\"]}, {\"type\": \"filter\", \"expr\": \"datum.peer !== toString(selectedNode.id) && indexof(adjPeerIds, datum.peer) < 0\"}, {\"type\": \"aggregate\", \"groupby\": [\"peer\"], \"fields\": [\"count\"], \"ops\": [\"sum\"], \"as\": [\"traffic\"]}]}], \"marks\": [{\"type\": \"rect\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y2\": {\"signal\": \"height\"}, \"fill\": {\"value\": \"#000000\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"edges_draw\"}, \"encode\": {\"update\": {\"x\": {\"field\": \"sx\"}, \"y\": {\"field\": \"sy\"}, \"x2\": {\"field\": \"tx\"}, \"y2\": {\"field\": \"ty\"}, \"stroke\": {\"signal\": \"!selectedNode ? '#4fc3f7' : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? '#7fe8ff' : '#213240')\"}, \"strokeOpacity\": {\"signal\": \"!selectedNode ? 0.42 : ((indexof(highlightNodeIdsCsv, ',' + datum.srcId + ',') >= 0 && indexof(highlightNodeIdsCsv, ',' + datum.dstId + ',') >= 0) ? 0.75 : 0.08)\"}, \"strokeWidth\": {\"value\": 0.9}}}}, {\"type\": \"symbol\", \"from\": {\"data\": \"layout\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x * zoom + autoPanX + panX\"}, \"y\": {\"signal\": \"datum.y * zoom + autoPanY + panY\"}, \"size\": {\"value\": 980}, \"fill\": {\"signal\": \"datum.nodeType==='application' ? '#3b2b1a' : '#1a2c3b'\"}, \"fillOpacity\": {\"value\": 0.9}, \"stroke\": {\"signal\": \"datum.nodeType==='application' ? '#ffd7a2' : '#a9dbff'\"}, \"strokeWidth\": {\"value\": 1.2}, \"opacity\": {\"signal\": \"!selectedNode ? 1 : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? 1 : 0.2)\"}}}}, {\"type\": \"symbol\", \"name\": \"nodeMark\", \"from\": {\"data\": \"layout\"}, \"encode\": {\"enter\": {\"size\": {\"value\": 980}, \"fill\": {\"value\": \"#000000\"}, \"fillOpacity\": {\"value\": 0.001}, \"stroke\": {\"value\": \"#000000\"}, \"strokeOpacity\": {\"value\": 0.001}, \"cursor\": {\"value\": \"pointer\"}}, \"update\": {\"x\": {\"signal\": \"datum.x * zoom + autoPanX + panX\"}, \"y\": {\"signal\": \"datum.y * zoom + autoPanY + panY\"}, \"size\": {\"value\": 980}}}}, {\"type\": \"text\", \"from\": {\"data\": \"layout\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x * zoom + autoPanX + panX\"}, \"y\": {\"signal\": \"datum.y * zoom + autoPanY + panY - 14\"}, \"text\": {\"field\": \"id\"}, \"fill\": {\"signal\": \"!selectedNode ? '#e0e0e0' : (indexof(highlightNodeIdsCsv, ',' + toString(datum.id) + ',') >= 0 ? '#f2f7ff' : '#4f5f6f')\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"bottom\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 12\"}, \"y\": {\"value\": 14}, \"text\": {\"signal\": \"rawBucketLimitReached ? 'Topology may be truncated at 500 relationships; add pagination to show the complete graph.' : ''\"}, \"fill\": {\"value\": \"#fbbf24\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"right\"}, \"baseline\": {\"value\": \"top\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "PQC Connections Topology", "type": "vega", @@ -205,7 +205,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"Selection details panel for host/application context using dashboard filters.\",\n \"autosize\": \"fit\",\n \"padding\": 10,\n \"background\": \"#000000\",\n \"signals\": [\n { \"name\": \"panelW\", \"update\": \"width - 20\" },\n { \"name\": \"labelX\", \"value\": 26 },\n { \"name\": \"valueX\", \"update\": \"width * 0.42\" },\n { \"name\": \"row0\", \"value\": 74 },\n { \"name\": \"rowH\", \"value\": 24 }\n ],\n \"data\": [\n {\n \"name\": \"context\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"host\": { \"terms\": { \"field\": \"observer.hostname\", \"size\": 1 } },\n \"app\": { \"terms\": { \"field\": \"tychon.application.name.keyword\", \"size\": 1 } },\n \"dst\": { \"terms\": { \"field\": \"server.address\", \"size\": 1 } },\n \"proto\": { \"terms\": { \"field\": \"network.protocol\", \"size\": 1 } },\n \"tls_ver\": { \"terms\": { \"field\": \"tls.preferred_protocol\", \"size\": 1 } },\n \"cipher\": { \"terms\": { \"field\": \"tls.preferred_cipher\", \"size\": 1 } },\n \"events\": { \"value_count\": { \"field\": \"@timestamp\" } },\n \"first_seen\": { \"min\": { \"field\": \"@timestamp\" } },\n \"last_seen\": { \"max\": { \"field\": \"@timestamp\" } }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n {\n \"type\": \"formula\",\n \"as\": \"host\",\n \"expr\": \"datum.host \u0026\u0026 datum.host.buckets \u0026\u0026 length(datum.host.buckets)\u003e0 ? datum.host.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"app\",\n \"expr\": \"datum.app \u0026\u0026 datum.app.buckets \u0026\u0026 length(datum.app.buckets)\u003e0 ? datum.app.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"dst\",\n \"expr\": \"datum.dst \u0026\u0026 datum.dst.buckets \u0026\u0026 length(datum.dst.buckets)\u003e0 ? datum.dst.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"proto\",\n \"expr\": \"datum.proto \u0026\u0026 datum.proto.buckets \u0026\u0026 length(datum.proto.buckets)\u003e0 ? datum.proto.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"tlsVer\",\n \"expr\": \"datum.tls_ver \u0026\u0026 datum.tls_ver.buckets \u0026\u0026 length(datum.tls_ver.buckets)\u003e0 ? datum.tls_ver.buckets[0].key : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"cipher\",\n \"expr\": \"datum.cipher \u0026\u0026 datum.cipher.buckets \u0026\u0026 length(datum.cipher.buckets)\u003e0 ? datum.cipher.buckets[0].key : ''\"\n },\n { \"type\": \"formula\", \"as\": \"events\", \"expr\": \"datum.events ? datum.events.value : 0\" },\n {\n \"type\": \"formula\",\n \"as\": \"firstSeen\",\n \"expr\": \"datum.first_seen \u0026\u0026 isValid(datum.first_seen.value_as_string) ? datum.first_seen.value_as_string : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"lastSeen\",\n \"expr\": \"datum.last_seen \u0026\u0026 isValid(datum.last_seen.value_as_string) ? datum.last_seen.value_as_string : ''\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"selectionType\",\n \"expr\": \"datum.app != '' ? 'APPLICATION CONTEXT' : (datum.host != '' ? 'HOST CONTEXT' : 'NO SELECTION')\"\n },\n {\n \"type\": \"formula\",\n \"as\": \"selectionId\",\n \"expr\": \"datum.app != '' ? datum.app : (datum.host != '' ? datum.host : 'Select a host/app in the graph')\"\n }\n ]\n },\n {\n \"name\": \"rows\",\n \"source\": \"context\",\n \"transform\": [\n {\n \"type\": \"project\",\n \"fields\": [\n \"selectionType\",\n \"selectionId\",\n \"host\",\n \"app\",\n \"dst\",\n \"proto\",\n \"tlsVer\",\n \"cipher\",\n \"events\",\n \"firstSeen\",\n \"lastSeen\"\n ],\n \"as\": [\n \"selectionType\",\n \"selectionId\",\n \"host\",\n \"app\",\n \"dst\",\n \"proto\",\n \"tlsVer\",\n \"cipher\",\n \"events\",\n \"firstSeen\",\n \"lastSeen\"\n ]\n },\n {\n \"type\": \"formula\",\n \"as\": \"kv\",\n \"expr\": \"[{k:'Context',v:datum.selectionType},{k:'Selection',v:datum.selectionId},{k:'Source Host',v:datum.host},{k:'Application',v:datum.app},{k:'Destination',v:datum.dst},{k:'Protocol',v:datum.proto},{k:'TLS Version',v:datum.tlsVer},{k:'Cipher',v:datum.cipher},{k:'Event Count',v:format(datum.events, ',')},{k:'First Seen',v:datum.firstSeen},{k:'Last Seen',v:datum.lastSeen}]\"\n },\n { \"type\": \"flatten\", \"fields\": [\"kv\"], \"as\": [\"row\"] },\n { \"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rn\"] },\n { \"type\": \"formula\", \"as\": \"y\", \"expr\": \"row0 + (datum.rn - 1) * rowH\" }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"signal\": \"height - 10\" },\n \"fill\": { \"value\": \"#0f1115\" },\n \"fillOpacity\": { \"value\": 0.96 },\n \"stroke\": { \"value\": \"#2b3440\" },\n \"strokeWidth\": { \"value\": 1.2 },\n \"cornerRadius\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"rect\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 10 },\n \"y\": { \"value\": 10 },\n \"x2\": { \"signal\": \"width - 10\" },\n \"y2\": { \"value\": 42 },\n \"fill\": { \"value\": \"#17324a\" },\n \"fillOpacity\": { \"value\": 0.92 },\n \"cornerRadiusTopLeft\": { \"value\": 8 },\n \"cornerRadiusTopRight\": { \"value\": 8 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"encode\": {\n \"update\": {\n \"x\": { \"value\": 24 },\n \"y\": { \"value\": 30 },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 12 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#e8f3ff\" },\n \"text\": { \"value\": \"SELECTION DETAILS\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"rule\",\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"valueX - 10\" },\n \"y\": { \"value\": 54 },\n \"y2\": { \"signal\": \"height - 20\" },\n \"stroke\": { \"value\": \"#1f2a36\" },\n \"strokeWidth\": { \"value\": 1 }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"rows\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"labelX\" },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"signal\": \"datum.row.k\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fontWeight\": { \"value\": \"bold\" },\n \"fill\": { \"value\": \"#9fc4e0\" },\n \"baseline\": { \"value\": \"middle\" }\n }\n }\n },\n {\n \"type\": \"text\",\n \"from\": { \"data\": \"rows\" },\n \"encode\": {\n \"update\": {\n \"x\": { \"signal\": \"valueX\" },\n \"y\": { \"field\": \"y\" },\n \"text\": { \"signal\": \"datum.row.v == '' ? '—' : datum.row.v\" },\n \"font\": { \"value\": \"monospace\" },\n \"fontSize\": { \"value\": 10 },\n \"fill\": { \"value\": \"#e8eef5\" },\n \"baseline\": { \"value\": \"middle\" },\n \"limit\": { \"signal\": \"width - valueX - 18\" }\n }\n }\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"Selection details panel for host/application context using dashboard filters.\", \"autosize\": \"fit\", \"padding\": 10, \"background\": \"#000000\", \"signals\": [{\"name\": \"panelW\", \"update\": \"width - 20\"}, {\"name\": \"labelX\", \"value\": 26}, {\"name\": \"valueX\", \"update\": \"width * 0.42\"}, {\"name\": \"row0\", \"value\": 74}, {\"name\": \"rowH\", \"value\": 24}], \"data\": [{\"name\": \"context\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc*\", \"body\": {\"size\": 0, \"aggs\": {\"host\": {\"terms\": {\"field\": \"observer.hostname\", \"size\": 1}}, \"app\": {\"terms\": {\"field\": \"tychon.application.name.keyword\", \"size\": 1}}, \"dst\": {\"terms\": {\"field\": \"server.address\", \"size\": 1}}, \"proto\": {\"terms\": {\"field\": \"network.protocol\", \"size\": 1}}, \"tls_ver\": {\"terms\": {\"field\": \"tls.preferred_protocol\", \"size\": 1}}, \"cipher\": {\"terms\": {\"field\": \"tls.preferred_cipher\", \"size\": 1}}, \"events\": {\"value_count\": {\"field\": \"@timestamp\"}}, \"first_seen\": {\"min\": {\"field\": \"@timestamp\"}}, \"last_seen\": {\"max\": {\"field\": \"@timestamp\"}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"host\", \"expr\": \"datum.host && datum.host.buckets && length(datum.host.buckets)>0 ? datum.host.buckets[0].key : ''\"}, {\"type\": \"formula\", \"as\": \"app\", \"expr\": \"datum.app && datum.app.buckets && length(datum.app.buckets)>0 ? datum.app.buckets[0].key : ''\"}, {\"type\": \"formula\", \"as\": \"dst\", \"expr\": \"datum.dst && datum.dst.buckets && length(datum.dst.buckets)>0 ? datum.dst.buckets[0].key : ''\"}, {\"type\": \"formula\", \"as\": \"proto\", \"expr\": \"datum.proto && datum.proto.buckets && length(datum.proto.buckets)>0 ? datum.proto.buckets[0].key : ''\"}, {\"type\": \"formula\", \"as\": \"tlsVer\", \"expr\": \"datum.tls_ver && datum.tls_ver.buckets && length(datum.tls_ver.buckets)>0 ? datum.tls_ver.buckets[0].key : ''\"}, {\"type\": \"formula\", \"as\": \"cipher\", \"expr\": \"datum.cipher && datum.cipher.buckets && length(datum.cipher.buckets)>0 ? datum.cipher.buckets[0].key : ''\"}, {\"type\": \"formula\", \"as\": \"events\", \"expr\": \"datum.events ? datum.events.value : 0\"}, {\"type\": \"formula\", \"as\": \"firstSeen\", \"expr\": \"datum.first_seen && isValid(datum.first_seen.value_as_string) ? datum.first_seen.value_as_string : ''\"}, {\"type\": \"formula\", \"as\": \"lastSeen\", \"expr\": \"datum.last_seen && isValid(datum.last_seen.value_as_string) ? datum.last_seen.value_as_string : ''\"}, {\"type\": \"formula\", \"as\": \"selectionType\", \"expr\": \"datum.app != '' ? 'APPLICATION CONTEXT' : (datum.host != '' ? 'HOST CONTEXT' : 'NO SELECTION')\"}, {\"type\": \"formula\", \"as\": \"selectionId\", \"expr\": \"datum.app != '' ? datum.app : (datum.host != '' ? datum.host : 'Select a host/app in the graph')\"}]}, {\"name\": \"rows\", \"source\": \"context\", \"transform\": [{\"type\": \"project\", \"fields\": [\"selectionType\", \"selectionId\", \"host\", \"app\", \"dst\", \"proto\", \"tlsVer\", \"cipher\", \"events\", \"firstSeen\", \"lastSeen\"], \"as\": [\"selectionType\", \"selectionId\", \"host\", \"app\", \"dst\", \"proto\", \"tlsVer\", \"cipher\", \"events\", \"firstSeen\", \"lastSeen\"]}, {\"type\": \"formula\", \"as\": \"kv\", \"expr\": \"[{k:'Context',v:datum.selectionType},{k:'Selection',v:datum.selectionId},{k:'Source Host',v:datum.host},{k:'Application',v:datum.app},{k:'Destination',v:datum.dst},{k:'Protocol',v:datum.proto},{k:'TLS Version',v:datum.tlsVer},{k:'Cipher',v:datum.cipher},{k:'Event Count',v:format(datum.events, ',')},{k:'First Seen',v:datum.firstSeen},{k:'Last Seen',v:datum.lastSeen}]\"}, {\"type\": \"flatten\", \"fields\": [\"kv\"], \"as\": [\"row\"]}, {\"type\": \"window\", \"ops\": [\"row_number\"], \"as\": [\"rn\"]}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"row0 + (datum.rn - 1) * rowH\"}]}], \"marks\": [{\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 10}, \"y\": {\"value\": 10}, \"x2\": {\"signal\": \"width - 10\"}, \"y2\": {\"signal\": \"height - 10\"}, \"fill\": {\"value\": \"#0f1115\"}, \"fillOpacity\": {\"value\": 0.96}, \"stroke\": {\"value\": \"#2b3440\"}, \"strokeWidth\": {\"value\": 1.2}, \"cornerRadius\": {\"value\": 8}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 10}, \"y\": {\"value\": 10}, \"x2\": {\"signal\": \"width - 10\"}, \"y2\": {\"value\": 42}, \"fill\": {\"value\": \"#17324a\"}, \"fillOpacity\": {\"value\": 0.92}, \"cornerRadiusTopLeft\": {\"value\": 8}, \"cornerRadiusTopRight\": {\"value\": 8}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 24}, \"y\": {\"value\": 30}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#e8f3ff\"}, \"text\": {\"value\": \"SELECTION DETAILS\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"rule\", \"encode\": {\"update\": {\"x\": {\"signal\": \"valueX - 10\"}, \"y\": {\"value\": 54}, \"y2\": {\"signal\": \"height - 20\"}, \"stroke\": {\"value\": \"#1f2a36\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"labelX\"}, \"y\": {\"field\": \"y\"}, \"text\": {\"signal\": \"datum.row.k\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#9fc4e0\"}, \"baseline\": {\"value\": \"middle\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"valueX\"}, \"y\": {\"field\": \"y\"}, \"text\": {\"signal\": \"datum.row.v == '' ? '\\u2014' : datum.row.v\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 10}, \"fill\": {\"value\": \"#e8eef5\"}, \"baseline\": {\"value\": \"middle\"}, \"limit\": {\"signal\": \"width - valueX - 18\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('context')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('context')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "Connections Selection Details", "type": "vega", @@ -262,7 +262,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#000000\",\n \"signals\": [\n {\"name\": \"totalApps\", \"update\": \"length(data('apps_total'))\u003e0 ? data('apps_total')[0].n : 0\"},\n {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))\u003e0 ? data('kex_pqc')[0].n : 0\"},\n {\"name\": \"kexPct\", \"update\": \"totalApps \u003e 0 ? round(kexReady / totalApps * 100) : 0\"},\n {\"name\": \"kexClr\", \"update\": \"kexPct\u003e=90 ? '#00c853' : kexPct\u003e=60 ? '#448aff' : kexPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"protoReady\", \"update\": \"length(data('proto_pqc'))\u003e0 ? data('proto_pqc')[0].n : 0\"},\n {\"name\": \"protoPct\", \"update\": \"totalApps \u003e 0 ? round(protoReady / totalApps * 100) : 0\"},\n {\"name\": \"protoClr\", \"update\": \"protoPct\u003e=90 ? '#00c853' : protoPct\u003e=60 ? '#448aff' : protoPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))\u003e0 ? data('sig_pqc')[0].n : 0\"},\n {\"name\": \"sigPct\", \"update\": \"totalApps \u003e 0 ? round(sigReady / totalApps * 100) : 0\"},\n {\"name\": \"sigClr\", \"update\": \"sigPct\u003e=90 ? '#00c853' : sigPct\u003e=60 ? '#448aff' : sigPct\u003e=30 ? '#ffa726' : '#ef5350'\"},\n {\"name\": \"barW\", \"update\": \"width * 0.62 - 18\"}\n ],\n \"data\": [\n {\n \"name\": \"apps_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}\n },\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"apps_total\", \"source\": \"apps_raw\"},\n {\n \"name\": \"kex_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"},\n {\n \"name\": \"proto_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"proto_pqc\", \"source\": \"proto_pqc_raw\"},\n {\n \"name\": \"sig_pqc_raw\",\n \"url\": {\n \"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}\n },\n \"format\": {\"property\": \"aggregations.f.u\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"}\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 22},\n \"text\": {\"value\": \"APPLICATION PQC DASHBOARD\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 16}, \"y\": {\"value\": 40},\n \"text\": {\"signal\": \"'PQC COMPLIANCE PROGRESS — ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 78},\n \"text\": {\"value\": \"KEX COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 93},\n \"text\": {\"signal\": \"(kexReady\u003e=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY key exchange'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 106},\n \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"kexClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122},\n \"text\": {\"signal\": \"kexPct + '%'\"},\n \"fill\": {\"signal\": \"kexClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 158},\n \"text\": {\"value\": \"PROTOCOL COMPLIANCE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 173},\n \"text\": {\"signal\": \"(protoReady\u003e=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — TLS 1.3 capable'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 186},\n \"width\": {\"signal\": \"max(0, barW * protoPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"protoClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202},\n \"text\": {\"signal\": \"protoPct + '%'\"},\n \"fill\": {\"signal\": \"protoClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 218},\n \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78},\n \"fill\": {\"value\": \"#161616\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 238},\n \"text\": {\"value\": \"CERT SIGNATURE\"},\n \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 253},\n \"text\": {\"signal\": \"(sigReady\u003e=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps\u003e=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications — PQC READY signature'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8},\n \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\",\n \"encode\": {\"update\": {\n \"x\": {\"value\": 18}, \"y\": {\"value\": 266},\n \"width\": {\"signal\": \"max(0, barW * sigPct / 100)\"},\n \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4},\n \"fill\": {\"signal\": \"sigClr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 282},\n \"text\": {\"signal\": \"sigPct + '%'\"},\n \"fill\": {\"signal\": \"sigClr\"},\n \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#000000\", \"signals\": [{\"name\": \"totalApps\", \"update\": \"length(data('apps_total'))>0 ? data('apps_total')[0].n : 0\"}, {\"name\": \"kexReady\", \"update\": \"length(data('kex_pqc'))>0 ? data('kex_pqc')[0].n : 0\"}, {\"name\": \"kexPct\", \"update\": \"totalApps > 0 ? round(kexReady / totalApps * 100) : 0\"}, {\"name\": \"kexClr\", \"update\": \"kexPct>=90 ? '#00c853' : kexPct>=60 ? '#448aff' : kexPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"protoReady\", \"update\": \"length(data('proto_pqc'))>0 ? data('proto_pqc')[0].n : 0\"}, {\"name\": \"protoPct\", \"update\": \"totalApps > 0 ? round(protoReady / totalApps * 100) : 0\"}, {\"name\": \"protoClr\", \"update\": \"protoPct>=90 ? '#00c853' : protoPct>=60 ? '#448aff' : protoPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"sigReady\", \"update\": \"length(data('sig_pqc'))>0 ? data('sig_pqc')[0].n : 0\"}, {\"name\": \"sigPct\", \"update\": \"totalApps > 0 ? round(sigReady / totalApps * 100) : 0\"}, {\"name\": \"sigClr\", \"update\": \"sigPct>=90 ? '#00c853' : sigPct>=60 ? '#448aff' : sigPct>=30 ? '#ffa726' : '#ef5350'\"}, {\"name\": \"barW\", \"update\": \"width * 0.62 - 18\"}], \"data\": [{\"name\": \"apps_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"apps_total\", \"source\": \"apps_raw\"}, {\"name\": \"kex_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"kex_pqc\", \"source\": \"kex_pqc_raw\"}, {\"name\": \"proto_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"proto_pqc\", \"source\": \"proto_pqc_raw\"}, {\"name\": \"sig_pqc_raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations.f.u\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"sig_pqc\", \"source\": \"sig_pqc_raw\"}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 22}, \"text\": {\"value\": \"APPLICATION PQC DASHBOARD\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 40}, \"text\": {\"signal\": \"'PQC COMPLIANCE PROGRESS \\u2014 ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' unique applications'\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 60}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"kexClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 78}, \"text\": {\"value\": \"KEX COMPLIANCE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 93}, \"text\": {\"signal\": \"(kexReady>=1000?format(kexReady,'.3~s'):format(kexReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY key exchange'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 106}, \"width\": {\"signal\": \"max(0, barW * kexPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"kexClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 122}, \"text\": {\"signal\": \"kexPct + '%'\"}, \"fill\": {\"signal\": \"kexClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 138}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 140}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"protoClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 158}, \"text\": {\"value\": \"PROTOCOL COMPLIANCE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 173}, \"text\": {\"signal\": \"(protoReady>=1000?format(protoReady,'.3~s'):format(protoReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 TLS 1.3 capable'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 186}, \"width\": {\"signal\": \"max(0, barW * protoPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"protoClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 202}, \"text\": {\"signal\": \"protoPct + '%'\"}, \"fill\": {\"signal\": \"protoClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 218}, \"stroke\": {\"value\": \"#222222\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 78}, \"fill\": {\"value\": \"#161616\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"value\": 220}, \"width\": {\"value\": 4}, \"height\": {\"value\": 78}, \"fill\": {\"signal\": \"sigClr\"}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 238}, \"text\": {\"value\": \"CERT SIGNATURE\"}, \"fill\": {\"value\": \"#888888\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 253}, \"text\": {\"signal\": \"(sigReady>=1000?format(sigReady,'.3~s'):format(sigReady,',')) + ' of ' + (totalApps>=1000?format(totalApps,'.3~s'):format(totalApps,',')) + ' applications \\u2014 PQC READY signature'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"barW\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"value\": \"#1e1e1e\"}, \"stroke\": {\"value\": \"#2a2a2a\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"encode\": {\"update\": {\"x\": {\"value\": 18}, \"y\": {\"value\": 266}, \"width\": {\"signal\": \"max(0, barW * sigPct / 100)\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 4}, \"fill\": {\"signal\": \"sigClr\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"value\": 282}, \"text\": {\"signal\": \"sigPct + '%'\"}, \"fill\": {\"signal\": \"sigClr\"}, \"fontSize\": {\"value\": 24}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('apps_raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('apps_raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "Application PQC Dashboard Risk", "type": "vega", @@ -318,7 +318,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"description\": \"Selection risk dial aligned to inventory OMB readiness tiers.\",\n \"autosize\": \"fit\",\n \"padding\": 10,\n \"background\": \"#000000\",\n \"signals\": [\n { \"name\": \"cx\", \"update\": \"width/2\" },\n { \"name\": \"cy\", \"update\": \"height*0.56\" },\n { \"name\": \"r\", \"update\": \"min(width, height) * 0.34\" }\n ],\n \"data\": [\n {\n \"name\": \"risk\",\n \"url\": {\n \"%context%\": true,\n \"%timefield%\": \"@timestamp\",\n \"index\": \"tychon-pqc-inventory*\",\n \"body\": {\n \"size\": 0,\n \"aggs\": {\n \"apps_total\": { \"cardinality\": { \"field\": \"process.executable\" } },\n \"kex_ready\": {\n \"filter\": { \"term\": { \"omb.kex_tier\": \"PQC READY\" } },\n \"aggs\": { \"u\": { \"cardinality\": { \"field\": \"process.executable\" } } }\n },\n \"proto_ready\": {\n \"filter\": { \"term\": { \"omb.protocol_tier\": \"TLS 1.3\" } },\n \"aggs\": { \"u\": { \"cardinality\": { \"field\": \"process.executable\" } } }\n },\n \"sig_ready\": {\n \"filter\": { \"term\": { \"omb.sig_tier\": \"PQC READY\" } },\n \"aggs\": { \"u\": { \"cardinality\": { \"field\": \"process.executable\" } } }\n }\n }\n }\n },\n \"format\": { \"property\": \"aggregations\" },\n \"transform\": [\n { \"type\": \"formula\", \"as\": \"n\", \"expr\": \"isValid(datum.apps_total) \u0026\u0026 isValid(datum.apps_total.value) ? max(1, datum.apps_total.value) : 1\" },\n { \"type\": \"formula\", \"as\": \"kex_ready_n\", \"expr\": \"isValid(datum.kex_ready) \u0026\u0026 isValid(datum.kex_ready.u) \u0026\u0026 isValid(datum.kex_ready.u.value) ? datum.kex_ready.u.value : 0\" },\n { \"type\": \"formula\", \"as\": \"proto_ready_n\", \"expr\": \"isValid(datum.proto_ready) \u0026\u0026 isValid(datum.proto_ready.u) \u0026\u0026 isValid(datum.proto_ready.u.value) ? datum.proto_ready.u.value : 0\" },\n { \"type\": \"formula\", \"as\": \"sig_ready_n\", \"expr\": \"isValid(datum.sig_ready) \u0026\u0026 isValid(datum.sig_ready.u) \u0026\u0026 isValid(datum.sig_ready.u.value) ? datum.sig_ready.u.value : 0\" },\n { \"type\": \"formula\", \"as\": \"p_kex_ready\", \"expr\": \"100 * datum.kex_ready_n / datum.n\" },\n { \"type\": \"formula\", \"as\": \"p_proto_ready\", \"expr\": \"100 * datum.proto_ready_n / datum.n\" },\n { \"type\": \"formula\", \"as\": \"p_sig_ready\", \"expr\": \"100 * datum.sig_ready_n / datum.n\" },\n { \"type\": \"formula\", \"as\": \"readiness\", \"expr\": \"clamp(round((datum.p_kex_ready + datum.p_proto_ready + datum.p_sig_ready) / 3), 0, 100)\" },\n { \"type\": \"formula\", \"as\": \"score\", \"expr\": \"clamp(100 - datum.readiness, 0, 100)\" },\n { \"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.readiness \u003e= 90 ? 'LOW' : datum.readiness \u003e= 60 ? 'MEDIUM' : 'HIGH'\" },\n { \"type\": \"formula\", \"as\": \"color\", \"expr\": \"datum.readiness \u003e= 90 ? '#22c55e' : datum.readiness \u003e= 60 ? '#f59e0b' : '#ef4444'\" },\n { \"type\": \"formula\", \"as\": \"angle\", \"expr\": \"-3.1415926 + (datum.score/100) * 3.1415926 * 2\" }\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"arc\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"r-18\"}, \"outerRadius\": {\"signal\": \"r\"},\n \"startAngle\": {\"value\": -3.1415926}, \"endAngle\": {\"value\": 3.1415926},\n \"fill\": {\"value\": \"#1f2937\"}\n }}\n },\n {\n \"type\": \"arc\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"},\n \"innerRadius\": {\"signal\": \"r-18\"}, \"outerRadius\": {\"signal\": \"r\"},\n \"startAngle\": {\"value\": -3.1415926}, \"endAngle\": {\"field\": \"angle\"},\n \"fill\": {\"field\": \"color\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy - 6\"}, \"align\": {\"value\": \"center\"},\n \"text\": {\"signal\": \"format(datum.score, 'd') + '/100'\"}, \"font\": {\"value\": \"monospace\"},\n \"fontSize\": {\"value\": 28}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"field\": \"color\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"risk\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + 24\"}, \"align\": {\"value\": \"center\"},\n \"text\": {\"signal\": \"datum.tier + ' RISK'\"}, \"font\": {\"value\": \"monospace\"},\n \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#cfe3f7\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"description\": \"Selection risk dial aligned to inventory OMB readiness tiers.\", \"autosize\": \"fit\", \"padding\": 10, \"background\": \"#000000\", \"signals\": [{\"name\": \"cx\", \"update\": \"width/2\"}, {\"name\": \"cy\", \"update\": \"height*0.56\"}, {\"name\": \"r\", \"update\": \"min(width, height) * 0.34\"}], \"data\": [{\"name\": \"risk\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"aggs\": {\"apps_total\": {\"cardinality\": {\"field\": \"process.executable\"}}, \"kex_ready\": {\"filter\": {\"term\": {\"omb.kex_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}, \"proto_ready\": {\"filter\": {\"term\": {\"omb.protocol_tier\": \"TLS 1.3\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}, \"sig_ready\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"PQC READY\"}}, \"aggs\": {\"u\": {\"cardinality\": {\"field\": \"process.executable\"}}}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"isValid(datum.apps_total) && isValid(datum.apps_total.value) ? max(1, datum.apps_total.value) : 1\"}, {\"type\": \"formula\", \"as\": \"kex_ready_n\", \"expr\": \"isValid(datum.kex_ready) && isValid(datum.kex_ready.u) && isValid(datum.kex_ready.u.value) ? datum.kex_ready.u.value : 0\"}, {\"type\": \"formula\", \"as\": \"proto_ready_n\", \"expr\": \"isValid(datum.proto_ready) && isValid(datum.proto_ready.u) && isValid(datum.proto_ready.u.value) ? datum.proto_ready.u.value : 0\"}, {\"type\": \"formula\", \"as\": \"sig_ready_n\", \"expr\": \"isValid(datum.sig_ready) && isValid(datum.sig_ready.u) && isValid(datum.sig_ready.u.value) ? datum.sig_ready.u.value : 0\"}, {\"type\": \"formula\", \"as\": \"p_kex_ready\", \"expr\": \"100 * datum.kex_ready_n / datum.n\"}, {\"type\": \"formula\", \"as\": \"p_proto_ready\", \"expr\": \"100 * datum.proto_ready_n / datum.n\"}, {\"type\": \"formula\", \"as\": \"p_sig_ready\", \"expr\": \"100 * datum.sig_ready_n / datum.n\"}, {\"type\": \"formula\", \"as\": \"readiness\", \"expr\": \"clamp(round((datum.p_kex_ready + datum.p_proto_ready + datum.p_sig_ready) / 3), 0, 100)\"}, {\"type\": \"formula\", \"as\": \"score\", \"expr\": \"clamp(100 - datum.readiness, 0, 100)\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.readiness >= 90 ? 'LOW' : datum.readiness >= 60 ? 'MEDIUM' : 'HIGH'\"}, {\"type\": \"formula\", \"as\": \"color\", \"expr\": \"datum.readiness >= 90 ? '#22c55e' : datum.readiness >= 60 ? '#f59e0b' : '#ef4444'\"}, {\"type\": \"formula\", \"as\": \"angle\", \"expr\": \"-3.1415926 + (datum.score/100) * 3.1415926 * 2\"}]}], \"marks\": [{\"type\": \"arc\", \"from\": {\"data\": \"risk\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"r-18\"}, \"outerRadius\": {\"signal\": \"r\"}, \"startAngle\": {\"value\": -3.1415926}, \"endAngle\": {\"value\": 3.1415926}, \"fill\": {\"value\": \"#1f2937\"}}}}, {\"type\": \"arc\", \"from\": {\"data\": \"risk\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy\"}, \"innerRadius\": {\"signal\": \"r-18\"}, \"outerRadius\": {\"signal\": \"r\"}, \"startAngle\": {\"value\": -3.1415926}, \"endAngle\": {\"field\": \"angle\"}, \"fill\": {\"field\": \"color\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"risk\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy - 6\"}, \"align\": {\"value\": \"center\"}, \"text\": {\"signal\": \"format(datum.score, 'd') + '/100'\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 28}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"field\": \"color\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"risk\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"cx\"}, \"y\": {\"signal\": \"cy + 24\"}, \"align\": {\"value\": \"center\"}, \"text\": {\"signal\": \"datum.tier + ' RISK'\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"fill\": {\"value\": \"#cfe3f7\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('risk')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('risk')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "QuantumRiskRadial", "type": "vega", @@ -342,7 +342,7 @@ "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-21T14:29:29.805Z", + "created_at": "2026-07-20T16:55:14.701Z", "id": "tychon_quantum_command-6f3d60d5-b5fb-45a5-9298-acf3ceb3ea1b-application-connections-topology", "references": [ { @@ -383,4 +383,4 @@ ], "type": "dashboard", "typeMigrationVersion": "10.3.0" -} \ No newline at end of file +} diff --git a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json index 80511537c96..ba097456e3c 100644 --- a/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json +++ b/packages/tychon_quantum_command/kibana/dashboard/tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard.json @@ -90,7 +90,7 @@ "description": "", "id": "", "params": { - "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"total\", \"update\": \"length(data('d_total'))\u003e0 ? data('d_total')[0].n : 0\"}, {\"name\": \"expired\", \"update\": \"length(data('d_expired'))\u003e0 ? data('d_expired')[0].n : 0\"}, {\"name\": \"exp30\", \"update\": \"length(data('d_exp30'))\u003e0 ? data('d_exp30')[0].n : 0\"}, {\"name\": \"self\", \"update\": \"length(data('d_self'))\u003e0 ? data('d_self')[0].n : 0\"}, {\"name\": \"legacy\", \"update\": \"length(data('d_legacy'))\u003e0 ? data('d_legacy')[0].n : 0\"}, {\"name\": \"pqcvuln\", \"update\": \"length(data('d_pqcvuln'))\u003e0 ? data('d_pqcvuln')[0].n : 0\"}, {\"name\": \"bw\", \"update\": \"floor((width - 10) / 6) - 4\"}, {\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"tile\"}, \"update\": \"datum.filt ? (datum.k === sel ? null : datum.k) : sel\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"tile\"}, \"update\": \"datum.filt ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"d_total\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"tychon.type\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"d_expired\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_exp30\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_self\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"certificate.is_self_signed\": true}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_legacy\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"LEGACY\"}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_pqcvuln\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"terms\": {\"omb.sig_tier\": [\"CLASSICAL\", \"MODERN\", \"LEGACY\"]}}}}}}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"tiles\", \"values\": [{\"k\": \"TOTAL\", \"ord\": 0, \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"sig\": \"total\", \"filt\": null}, {\"k\": \"EXPIRED\", \"ord\": 1, \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"sig\": \"expired\", \"filt\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, {\"k\": \"EXP 30D\", \"ord\": 2, \"clr\": \"#ff7043\", \"bg\": \"#ff704318\", \"sig\": \"exp30\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, {\"k\": \"SELF-SIGNED\", \"ord\": 3, \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"sig\": \"self\", \"filt\": {\"term\": {\"certificate.is_self_signed\": true}}}, {\"k\": \"LEGACY\", \"ord\": 4, \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"sig\": \"legacy\", \"filt\": {\"term\": {\"omb.sig_tier\": \"LEGACY\"}}}, {\"k\": \"PQC VULN\", \"ord\": 5, \"clr\": \"#ab47bc\", \"bg\": \"#ab47bc18\", \"sig\": \"pqcvuln\", \"filt\": {\"terms\": {\"omb.sig_tier\": [\"CLASSICAL\", \"MODERN\", \"LEGACY\"]}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"x\", \"expr\": \"datum.ord * (bw + 4) + 8\"}, {\"type\": \"formula\", \"as\": \"val\", \"expr\": \"datum.sig === 'total' ? total : datum.sig === 'expired' ? expired : datum.sig === 'exp30' ? exp30 : datum.sig === 'self' ? self : datum.sig === 'legacy' ? legacy : pqcvuln\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE INVENTORY\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"OPERATIONAL OVERVIEW \\u2014 click a tile to filter the dashboard\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"tile\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"field\": \"x\"}, \"y\": {\"value\": 52}, \"width\": {\"signal\": \"bw\"}, \"height\": {\"value\": 72}, \"fill\": {\"signal\": \"datum.k === sel ? datum.bg : '#161616'\"}, \"cornerRadius\": {\"value\": 3}, \"stroke\": {\"signal\": \"datum.k === sel ? datum.clr : (datum.val \u003e 0 \u0026\u0026 datum.filt ? '#2a2a3a' : '#222222')\"}, \"strokeWidth\": {\"signal\": \"datum.k === sel ? 2 : 1\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x + bw/2\"}, \"y\": {\"value\": 88}, \"text\": {\"signal\": \"datum.val \u003e= 1000 ? format(datum.val,'.3~s') : format(datum.val,',')\"}, \"fill\": {\"signal\": \"datum.k === sel ? datum.clr : (datum.val \u003e 0 ? datum.clr : '#3a3a3a')\"}, \"fontSize\": {\"value\": 22}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x + bw/2\"}, \"y\": {\"value\": 108}, \"text\": {\"field\": \"k\"}, \"fill\": {\"signal\": \"datum.k === sel ? datum.clr : '#666666'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}]}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"total\", \"update\": \"length(data('d_total'))>0 ? data('d_total')[0].n : 0\"}, {\"name\": \"expired\", \"update\": \"length(data('d_expired'))>0 ? data('d_expired')[0].n : 0\"}, {\"name\": \"exp30\", \"update\": \"length(data('d_exp30'))>0 ? data('d_exp30')[0].n : 0\"}, {\"name\": \"self\", \"update\": \"length(data('d_self'))>0 ? data('d_self')[0].n : 0\"}, {\"name\": \"legacy\", \"update\": \"length(data('d_legacy'))>0 ? data('d_legacy')[0].n : 0\"}, {\"name\": \"pqcvuln\", \"update\": \"length(data('d_pqcvuln'))>0 ? data('d_pqcvuln')[0].n : 0\"}, {\"name\": \"bw\", \"update\": \"floor((width - 10) / 6) - 4\"}, {\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"tile\"}, \"update\": \"datum.filt ? (datum.k === sel ? null : datum.k) : sel\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"tile\"}, \"update\": \"datum.filt ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"d_total\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"tychon.type\"}}}}, \"%timefield%\": \"@timestamp\"}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"d_expired\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}}}, \"%timefield%\": \"@timestamp\"}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_exp30\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}}}, \"%timefield%\": \"@timestamp\"}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_self\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"certificate.is_self_signed\": true}}}}}, \"%timefield%\": \"@timestamp\"}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_legacy\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"term\": {\"omb.sig_tier\": \"LEGACY\"}}}}}, \"%timefield%\": \"@timestamp\"}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"d_pqcvuln\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"f\": {\"filter\": {\"terms\": {\"omb.sig_tier\": [\"CLASSICAL\", \"MODERN\", \"LEGACY\"]}}}}}, \"%timefield%\": \"@timestamp\"}, \"format\": {\"property\": \"aggregations.f\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"tiles\", \"values\": [{\"k\": \"TOTAL\", \"ord\": 0, \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"sig\": \"total\", \"filt\": null}, {\"k\": \"EXPIRED\", \"ord\": 1, \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"sig\": \"expired\", \"filt\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, {\"k\": \"EXP 30D\", \"ord\": 2, \"clr\": \"#ff7043\", \"bg\": \"#ff704318\", \"sig\": \"exp30\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, {\"k\": \"SELF-SIGNED\", \"ord\": 3, \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"sig\": \"self\", \"filt\": {\"term\": {\"certificate.is_self_signed\": true}}}, {\"k\": \"LEGACY\", \"ord\": 4, \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"sig\": \"legacy\", \"filt\": {\"term\": {\"omb.sig_tier\": \"LEGACY\"}}}, {\"k\": \"PQC VULN\", \"ord\": 5, \"clr\": \"#ab47bc\", \"bg\": \"#ab47bc18\", \"sig\": \"pqcvuln\", \"filt\": {\"terms\": {\"omb.sig_tier\": [\"CLASSICAL\", \"MODERN\", \"LEGACY\"]}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"x\", \"expr\": \"datum.ord * (bw + 4) + 8\"}, {\"type\": \"formula\", \"as\": \"val\", \"expr\": \"datum.sig === 'total' ? total : datum.sig === 'expired' ? expired : datum.sig === 'exp30' ? exp30 : datum.sig === 'self' ? self : datum.sig === 'legacy' ? legacy : pqcvuln\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE INVENTORY\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"OPERATIONAL OVERVIEW \\u2014 click a tile to filter the dashboard\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"tile\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"field\": \"x\"}, \"y\": {\"value\": 52}, \"width\": {\"signal\": \"bw\"}, \"height\": {\"value\": 72}, \"fill\": {\"signal\": \"datum.k === sel ? datum.bg : '#161616'\"}, \"cornerRadius\": {\"value\": 3}, \"stroke\": {\"signal\": \"datum.k === sel ? datum.clr : (datum.val > 0 && datum.filt ? '#2a2a3a' : '#222222')\"}, \"strokeWidth\": {\"signal\": \"datum.k === sel ? 2 : 1\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x + bw/2\"}, \"y\": {\"value\": 88}, \"text\": {\"signal\": \"datum.val >= 1000 ? format(datum.val,'.3~s') : format(datum.val,',')\"}, \"fill\": {\"signal\": \"datum.k === sel ? datum.clr : (datum.val > 0 ? datum.clr : '#3a3a3a')\"}, \"fontSize\": {\"value\": 22}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"tiles\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"datum.x + bw/2\"}, \"y\": {\"value\": 108}, \"text\": {\"field\": \"k\"}, \"fill\": {\"signal\": \"datum.k === sel ? datum.clr : '#666666'\"}, \"fontSize\": {\"value\": 9}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('d_total')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('d_total')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "CERT OPS — Inventory Header", "type": "vega", @@ -146,7 +146,7 @@ "description": "", "id": "", "params": { - "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 10}}}}}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"n\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature \\u2014 quantum-resistant, CNSA 2.0 approved\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve \\u2014 quantum-vulnerable via Shor's algorithm, must be replaced pre-2035\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA \\u2014 quantum-vulnerable via Shor's algorithm, harvest-now-decrypt-later risk today\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"SHA-1/MD5 hash \\u2014 classically broken and quantum-vulnerable, replace immediately\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#b71c1c\", \"bg\": \"#b71c1c22\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n\u003e0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n\u003e0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 55}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"field\": \"badge\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 106}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.5\"}, \"fill\": {\"signal\": \"datum.n\u003e0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 106}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.56\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 38\"}, \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"}, \"fill\": {\"signal\": \"datum.t===sel ? datum.clr : datum.n\u003e0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 50\"}, \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\"}, \"height\": {\"value\": 6}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.clr + '55'\"}}}}]}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? null : datum.t\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.t === sel ? kibanaRemoveFilter({'match_phrase': {'omb.sig_tier': datum.t}}) : kibanaAddFilter({'match_phrase': {'omb.sig_tier': datum.t}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"k\": {\"terms\": {\"field\": \"omb.sig_tier\", \"size\": 10}}}}, \"%timefield%\": \"@timestamp\"}, \"format\": {\"property\": \"aggregations.k.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"t\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"tc\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"groupby\": [\"t\"], \"ops\": [\"sum\"], \"fields\": [\"n\"], \"as\": [\"n\"]}]}, {\"name\": \"mx\", \"source\": \"tc\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"values\": [{\"t\": \"PQC READY\", \"lbl\": \"ML-DSA / Dilithium\", \"desc\": \"Post-quantum lattice signature \\u2014 quantum-resistant, CNSA 2.0 approved\", \"badge\": \"PQC READY\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0}, {\"t\": \"MODERN\", \"lbl\": \"ECDSA (P-256 / P-384)\", \"desc\": \"Elliptic curve \\u2014 quantum-vulnerable via Shor's algorithm, must be replaced pre-2035\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 1}, {\"t\": \"CLASSICAL\", \"lbl\": \"RSA / SHA-256 RSA\", \"desc\": \"RSA \\u2014 quantum-vulnerable via Shor's algorithm, harvest-now-decrypt-later risk today\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 2}, {\"t\": \"LEGACY\", \"lbl\": \"MD5 / SHA-1 RSA\", \"desc\": \"SHA-1/MD5 hash \\u2014 classically broken and quantum-vulnerable, replace immediately\", \"badge\": \"QUANTUM VULN\", \"clr\": \"#b71c1c\", \"bg\": \"#b71c1c22\", \"ord\": 3}], \"transform\": [{\"type\": \"lookup\", \"from\": \"tc\", \"key\": \"t\", \"fields\": [\"t\"], \"values\": [\"n\"], \"as\": [\"n\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 60\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SIGNATURE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 16}, \"y\": {\"value\": 38}, \"text\": {\"value\": \"SIGNATURE ALGORITHM \\u2014 click a tier to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 48}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.t===sel?'#1c1c2e':datum.n>0?'#161622':'#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0?datum.clr:'#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 55}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"field\": \"badge\"}, \"fill\": {\"signal\": \"datum.n>0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 106}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.5\"}, \"fill\": {\"signal\": \"datum.n>0?'#e8e8e8':'#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 106}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.56\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 38\"}, \"text\": {\"signal\": \"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"}, \"fill\": {\"signal\": \"datum.t===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 50\"}, \"width\": {\"signal\": \"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\"}, \"height\": {\"value\": 6}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.clr + '55'\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "CERT OPS — Quantum Tier", "type": "vega", @@ -202,7 +202,7 @@ "description": "", "id": "", "params": { - "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.n \u003e 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"expired\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, \"exp30\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, \"exp90\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now+30d\", \"lt\": \"now+90d\"}}}}, \"selfsign\": {\"filter\": {\"term\": {\"certificate.is_self_signed\": true}}}, \"weakkey\": {\"filter\": {\"terms\": {\"certificate.subject_public_key_info.bit_size\": [512, 1024]}}}, \"total\": {\"value_count\": {\"field\": \"certificate.not_after\"}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"expired\", \"expr\": \"datum.expired ? datum.expired.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"exp30\", \"expr\": \"datum.exp30 ? datum.exp30.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"exp90\", \"expr\": \"datum.exp90 ? datum.exp90.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"selfsign\", \"expr\": \"datum.selfsign ? datum.selfsign.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"weakkey\", \"expr\": \"datum.weakkey ? datum.weakkey.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"total\", \"expr\": \"datum.total ? datum.total.value : 0\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"EXPIRED\", \"lbl\": \"Expired\", \"desc\": \"certificate.not_after \u003c now \\u2014 no longer trusted by any client\", \"sev\": \"critical\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 0, \"field\": \"expired\", \"filt\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, {\"k\": \"EXP 30D\", \"lbl\": \"Expiring in 30 days\", \"desc\": \"certificate.not_after within 30 days \\u2014 immediate renewal required\", \"sev\": \"high\", \"clr\": \"#ff7043\", \"bg\": \"#ff704318\", \"ord\": 1, \"field\": \"exp30\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, {\"k\": \"EXP 90D\", \"lbl\": \"Expiring in 90 days\", \"desc\": \"certificate.not_after within 90 days \\u2014 plan renewal now\", \"sev\": \"medium\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2, \"field\": \"exp90\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now+30d\", \"lt\": \"now+90d\"}}}}, {\"k\": \"SELF-SIGNED\", \"lbl\": \"Self-Signed\", \"desc\": \"certificate.is_self_signed = true \\u2014 no CA trust chain, browser errors\", \"sev\": \"medium\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 3, \"field\": \"selfsign\", \"filt\": {\"term\": {\"certificate.is_self_signed\": true}}}, {\"k\": \"WEAK KEY\", \"lbl\": \"Weak Key \\u22641024-bit\", \"desc\": \"RSA/DSA key \\u22641024 bits \\u2014 computationally breakable, must be replaced\", \"sev\": \"critical\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 4, \"field\": \"weakkey\", \"filt\": {\"terms\": {\"certificate.subject_public_key_info.bit_size\": [512, 1024]}}}], \"transform\": [{\"type\": \"lookup\", \"from\": \"raw\", \"key\": \"total\", \"fields\": [\"ord\"], \"values\": [\"expired\", \"exp30\", \"exp90\", \"selfsign\", \"weakkey\", \"total\"], \"as\": [\"v_expired\", \"v_exp30\", \"v_exp90\", \"v_selfsign\", \"v_weakkey\", \"v_total\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.field==='expired' ? (length(data('raw'))\u003e0?data('raw')[0].expired:0) : datum.field==='exp30' ? (length(data('raw'))\u003e0?data('raw')[0].exp30:0) : datum.field==='exp90' ? (length(data('raw'))\u003e0?data('raw')[0].exp90:0) : datum.field==='selfsign' ? (length(data('raw'))\u003e0?data('raw')[0].selfsign:0) : (length(data('raw'))\u003e0?data('raw')[0].weakkey:0)\"}, {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('raw'))\u003e0 ? data('raw')[0].total : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 68 + 52\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE HYGIENE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"OPERATIONAL ISSUES \\u2014 expiry \\u00b7 trust \\u00b7 key strength\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 62}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n\u003e0 ? datum.bg : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 62}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 61\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 7\"}, \"width\": {\"value\": 72}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 36\"}, \"y\": {\"signal\": \"datum.y + 19\"}, \"text\": {\"field\": \"sev\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 29\"}, \"width\": {\"value\": 72}, \"height\": {\"value\": 14}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"signal\": \"datum.n \u003e 0 ? '#333333' : '#222222'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 36\"}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"signal\": \"datum.tot \u003e 0 ? format(datum.pct * 100, '.1f') + '%' : '\\u2014'\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n \u003e 0 ? (datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.n\u003e0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}]}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"expired\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, \"exp30\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, \"exp90\": {\"filter\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now+30d\", \"lt\": \"now+90d\"}}}}, \"selfsign\": {\"filter\": {\"term\": {\"certificate.is_self_signed\": true}}}, \"weakkey\": {\"filter\": {\"terms\": {\"certificate.subject_public_key_info.bit_size\": [512, 1024]}}}, \"total\": {\"value_count\": {\"field\": \"certificate.not_after\"}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"expired\", \"expr\": \"datum.expired ? datum.expired.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"exp30\", \"expr\": \"datum.exp30 ? datum.exp30.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"exp90\", \"expr\": \"datum.exp90 ? datum.exp90.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"selfsign\", \"expr\": \"datum.selfsign ? datum.selfsign.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"weakkey\", \"expr\": \"datum.weakkey ? datum.weakkey.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"total\", \"expr\": \"datum.total ? datum.total.value : 0\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"EXPIRED\", \"lbl\": \"Expired\", \"desc\": \"certificate.not_after < now \\u2014 no longer trusted by any client\", \"sev\": \"critical\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 0, \"field\": \"expired\", \"filt\": {\"range\": {\"certificate.not_after\": {\"lt\": \"now\"}}}}, {\"k\": \"EXP 30D\", \"lbl\": \"Expiring in 30 days\", \"desc\": \"certificate.not_after within 30 days \\u2014 immediate renewal required\", \"sev\": \"high\", \"clr\": \"#ff7043\", \"bg\": \"#ff704318\", \"ord\": 1, \"field\": \"exp30\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now\", \"lt\": \"now+30d\"}}}}, {\"k\": \"EXP 90D\", \"lbl\": \"Expiring in 90 days\", \"desc\": \"certificate.not_after within 90 days \\u2014 plan renewal now\", \"sev\": \"medium\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 2, \"field\": \"exp90\", \"filt\": {\"range\": {\"certificate.not_after\": {\"gte\": \"now+30d\", \"lt\": \"now+90d\"}}}}, {\"k\": \"SELF-SIGNED\", \"lbl\": \"Self-Signed\", \"desc\": \"certificate.is_self_signed = true \\u2014 no CA trust chain, browser errors\", \"sev\": \"medium\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 3, \"field\": \"selfsign\", \"filt\": {\"term\": {\"certificate.is_self_signed\": true}}}, {\"k\": \"WEAK KEY\", \"lbl\": \"Weak Key \\u22641024-bit\", \"desc\": \"RSA/DSA key \\u22641024 bits \\u2014 computationally breakable, must be replaced\", \"sev\": \"critical\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 4, \"field\": \"weakkey\", \"filt\": {\"terms\": {\"certificate.subject_public_key_info.bit_size\": [512, 1024]}}}], \"transform\": [{\"type\": \"lookup\", \"from\": \"raw\", \"key\": \"total\", \"fields\": [\"ord\"], \"values\": [\"expired\", \"exp30\", \"exp90\", \"selfsign\", \"weakkey\", \"total\"], \"as\": [\"v_expired\", \"v_exp30\", \"v_exp90\", \"v_selfsign\", \"v_weakkey\", \"v_total\"], \"default\": 0}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.field==='expired' ? (length(data('raw'))>0?data('raw')[0].expired:0) : datum.field==='exp30' ? (length(data('raw'))>0?data('raw')[0].exp30:0) : datum.field==='exp90' ? (length(data('raw'))>0?data('raw')[0].exp90:0) : datum.field==='selfsign' ? (length(data('raw'))>0?data('raw')[0].selfsign:0) : (length(data('raw'))>0?data('raw')[0].weakkey:0)\"}, {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('raw'))>0 ? data('raw')[0].total : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot > 0 ? datum.n / datum.tot : 0\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 68 + 52\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE HYGIENE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"OPERATIONAL ISSUES \\u2014 expiry \\u00b7 trust \\u00b7 key strength\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 62}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n>0 ? datum.bg : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 62}, \"fill\": {\"signal\": \"datum.n>0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 61\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"signal\": \"datum.n>0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 16}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 7\"}, \"width\": {\"value\": 72}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 36\"}, \"y\": {\"signal\": \"datum.y + 19\"}, \"text\": {\"field\": \"sev\"}, \"fill\": {\"signal\": \"datum.n>0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62\"}, \"y\": {\"signal\": \"datum.y + 29\"}, \"width\": {\"value\": 72}, \"height\": {\"value\": 14}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"value\": \"#1a1a1a\"}, \"stroke\": {\"signal\": \"datum.n > 0 ? '#333333' : '#222222'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.62 + 36\"}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"signal\": \"datum.tot > 0 ? format(datum.pct * 100, '.1f') + '%' : '\\u2014'\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 8}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "Certificate Hygiene", "type": "vega", @@ -258,7 +258,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.issuer_organization': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.issuer_organization': datum.k}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_issuer\": {\"terms\": {\"field\": \"certificate.issuer_organization\", \"size\": 10, \"order\": {\"_count\": \"desc\"}}}\n }}},\n \"format\": {\"property\": \"aggregations.by_issuer.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 52 + 52\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.rnk === 1 ? '#448aff' : datum.rnk === 2 ? '#4db6ac' : datum.rnk \u003c= 5 ? '#546e7a' : '#37474f'\"}\n ]\n },\n {\n \"name\": \"mx\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"TOP ISSUING CAs\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"CERTIFICATE AUTHORITY — who issued your certificates · click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 46},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 3}, \"height\": {\"value\": 46},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 30}, \"y\": {\"signal\": \"datum.y + 17\"},\n \"text\": {\"signal\": \"format(datum.rnk, 'd') + '.'\"},\n \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 10},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 36}, \"y\": {\"signal\": \"datum.y + 17\"},\n \"text\": {\"field\": \"k\"}, \"limit\": {\"signal\": \"width * 0.62\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 36}, \"y\": {\"signal\": \"datum.y + 24\"},\n \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * (width * 0.62) : 0\"},\n \"height\": {\"value\": 5}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.clr + '66'\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 45\"},\n \"stroke\": {\"value\": \"#1e1e1e\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"raw\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#888888'\"},\n \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.issuer_organization': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.issuer_organization': datum.k}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"by_issuer\": {\"terms\": {\"field\": \"certificate.issuer_organization\", \"size\": 10, \"order\": {\"_count\": \"desc\"}}}}}}, \"format\": {\"property\": \"aggregations.by_issuer.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}, {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}}, {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 52 + 52\"}, {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.rnk === 1 ? '#448aff' : datum.rnk === 2 ? '#4db6ac' : datum.rnk <= 5 ? '#546e7a' : '#37474f'\"}]}, {\"name\": \"mx\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"TOP ISSUING CAs\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"CERTIFICATE AUTHORITY \\u2014 who issued your certificates \\u00b7 click to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"raw\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 46}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"raw\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 3}, \"height\": {\"value\": 46}, \"fill\": {\"field\": \"clr\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"raw\"}, \"encode\": {\"update\": {\"x\": {\"value\": 30}, \"y\": {\"signal\": \"datum.y + 17\"}, \"text\": {\"signal\": \"format(datum.rnk, 'd') + '.'\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 10}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"raw\"}, \"encode\": {\"update\": {\"x\": {\"value\": 36}, \"y\": {\"signal\": \"datum.y + 17\"}, \"text\": {\"field\": \"k\"}, \"limit\": {\"signal\": \"width * 0.62\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"}, \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"raw\"}, \"encode\": {\"update\": {\"x\": {\"value\": 36}, \"y\": {\"signal\": \"datum.y + 24\"}, \"width\": {\"signal\": \"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.62) : 0\"}, \"height\": {\"value\": 5}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.clr + '66'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"raw\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 45\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"raw\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"signal\": \"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#888888'\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "CERT OPS — Top Issuing CAs", "type": "vega", @@ -314,7 +314,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_algo\": {\"terms\": {\"field\": \"certificate.subject_public_key_info.algorithm\", \"size\": 10}},\n \"total\": {\"value_count\": {\"field\": \"id\"}}\n }}},\n \"format\": {\"property\": \"aggregations.by_algo.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}\n ]\n },\n {\n \"name\": \"tot\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\n \"name\": \"palette\",\n \"values\": [\n {\"k\": \"RSA\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"lbl\": \"RSA\", \"desc\": \"Rivest–Shamir–Adleman — quantum-vulnerable via Shor's algorithm\"},\n {\"k\": \"ECDSA\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"lbl\": \"ECDSA\", \"desc\": \"Elliptic curve — quantum-vulnerable, efficient on classical hardware\"},\n {\"k\": \"DSA\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"lbl\": \"DSA\", \"desc\": \"Digital Signature Algorithm — deprecated, should not be in new certs\"},\n {\"k\": \"unknown_der\", \"clr\": \"#78909c\", \"bg\": \"#78909c18\", \"lbl\": \"Unknown DER\", \"desc\": \"DER-encoded cert with unrecognized key OID\"},\n {\"k\": \"unknown_pem\", \"clr\": \"#78909c\", \"bg\": \"#78909c18\", \"lbl\": \"Unknown PEM\", \"desc\": \"PEM-encoded cert with unrecognized key OID\"},\n {\"k\": \"ML-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"ML-DSA\", \"desc\": \"Lattice-based PQC signature — CNSA 2.0 quantum-resistant\"},\n {\"k\": \"SLH-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"SLH-DSA\", \"desc\": \"Hash-based PQC signature — CNSA 2.0 quantum-resistant\"},\n {\"k\": \"FN-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"FN-DSA\", \"desc\": \"Falcon lattice signature — CNSA 2.0 quantum-resistant\"}\n ]\n },\n {\n \"name\": \"rows\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"lookup\", \"from\": \"palette\", \"key\": \"k\", \"fields\": [\"k\"],\n \"values\": [\"clr\", \"bg\", \"lbl\", \"desc\"], \"as\": [\"clr\", \"bg\", \"lbl\", \"desc\"],\n \"default\": \"#78909c\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.clr || '#78909c'\"},\n {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.bg || '#78909c18'\"},\n {\"type\": \"formula\", \"as\": \"lbl\", \"expr\": \"datum.lbl || datum.k\"},\n {\"type\": \"formula\", \"as\": \"desc\", \"expr\": \"datum.desc || 'Unrecognized key algorithm'\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 70 + 52\"},\n {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"},\n {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"},\n {\"type\": \"formula\", \"as\": \"bw\", \"expr\": \"width * 0.58 - 110\"}\n ]\n },\n {\n \"name\": \"mx\",\n \"source\": \"rows\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"KEY ALGORITHM\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"PUBLIC KEY TYPE — click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 64},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n\u003e0 ? '#161622' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 64},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 63\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.4\"},\n \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 40\"},\n \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.56\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\"},\n \"height\": {\"value\": 10}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.clr + '88'\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 50\"},\n \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.algorithm': datum.k}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"by_algo\": {\"terms\": {\"field\": \"certificate.subject_public_key_info.algorithm\", \"size\": 10}}, \"total\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.by_algo.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}]}, {\"name\": \"tot\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"palette\", \"values\": [{\"k\": \"RSA\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"lbl\": \"RSA\", \"desc\": \"Rivest\\u2013Shamir\\u2013Adleman \\u2014 quantum-vulnerable via Shor's algorithm\"}, {\"k\": \"ECDSA\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"lbl\": \"ECDSA\", \"desc\": \"Elliptic curve \\u2014 quantum-vulnerable, efficient on classical hardware\"}, {\"k\": \"DSA\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"lbl\": \"DSA\", \"desc\": \"Digital Signature Algorithm \\u2014 deprecated, should not be in new certs\"}, {\"k\": \"unknown_der\", \"clr\": \"#78909c\", \"bg\": \"#78909c18\", \"lbl\": \"Unknown DER\", \"desc\": \"DER-encoded cert with unrecognized key OID\"}, {\"k\": \"unknown_pem\", \"clr\": \"#78909c\", \"bg\": \"#78909c18\", \"lbl\": \"Unknown PEM\", \"desc\": \"PEM-encoded cert with unrecognized key OID\"}, {\"k\": \"ML-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"ML-DSA\", \"desc\": \"Lattice-based PQC signature \\u2014 CNSA 2.0 quantum-resistant\"}, {\"k\": \"SLH-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"SLH-DSA\", \"desc\": \"Hash-based PQC signature \\u2014 CNSA 2.0 quantum-resistant\"}, {\"k\": \"FN-DSA\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"lbl\": \"FN-DSA\", \"desc\": \"Falcon lattice signature \\u2014 CNSA 2.0 quantum-resistant\"}]}, {\"name\": \"rows\", \"source\": \"raw\", \"transform\": [{\"type\": \"lookup\", \"from\": \"palette\", \"key\": \"k\", \"fields\": [\"k\"], \"values\": [\"clr\", \"bg\", \"lbl\", \"desc\"], \"as\": [\"clr\", \"bg\", \"lbl\", \"desc\"], \"default\": \"#78909c\"}, {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.clr || '#78909c'\"}, {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.bg || '#78909c18'\"}, {\"type\": \"formula\", \"as\": \"lbl\", \"expr\": \"datum.lbl || datum.k\"}, {\"type\": \"formula\", \"as\": \"desc\", \"expr\": \"datum.desc || 'Unrecognized key algorithm'\"}, {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}}, {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 70 + 52\"}, {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))>0 ? data('tot')[0].n : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot > 0 ? datum.n / datum.tot : 0\"}, {\"type\": \"formula\", \"as\": \"bw\", \"expr\": \"width * 0.58 - 110\"}]}, {\"name\": \"mx\", \"source\": \"rows\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"KEY ALGORITHM\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"PUBLIC KEY TYPE \\u2014 click to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 64}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161622' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 64}, \"fill\": {\"field\": \"clr\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 63\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.4\"}, \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.56\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 22\"}, \"width\": {\"signal\": \"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * (width * 0.30) : 0\"}, \"height\": {\"value\": 10}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.clr + '88'\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"}, \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 50\"}, \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "CERT OPS — Key Algorithm", "type": "vega", @@ -370,7 +370,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_size\": {\"terms\": {\"field\": \"certificate.subject_public_key_info.bit_size\", \"size\": 15, \"order\": {\"_count\": \"desc\"}}},\n \"total\": {\"value_count\": {\"field\": \"id\"}}\n }}},\n \"format\": {\"property\": \"aggregations.by_size.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"sz\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"toString(datum.key) + '-bit'\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.key \u003c= 1024 ? '#ef5350' : datum.key \u003c= 2048 ? '#ffa726' : datum.key \u003c= 3072 ? '#448aff' : '#00c853'\"},\n {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.key \u003c= 1024 ? '#ef535018' : datum.key \u003c= 2048 ? '#ffa72618' : datum.key \u003c= 3072 ? '#448aff18' : '#00c85318'\"},\n {\"type\": \"formula\", \"as\": \"tier\",\"expr\": \"datum.key \u003c= 512 ? 'CRITICAL' : datum.key \u003c= 1024 ? 'WEAK' : datum.key \u003c= 2048 ? 'CLASSICAL' : datum.key \u003c= 3072 ? 'STRONG' : 'CNSA 2.0'\"},\n {\"type\": \"formula\", \"as\": \"desc\",\"expr\": \"datum.key \u003c= 512 ? 'Trivially breakable — remove immediately' : datum.key \u003c= 1024 ? 'Below NIST minimum — must be replaced' : datum.key === 2048 ? 'RSA-2048 / ECDSA-P256 — classical standard, quantum-vulnerable' : datum.key === 3072 ? 'RSA-3072 — transitional strength, quantum-vulnerable' : datum.key === 4096 ? 'RSA-4096 — strong classical, quantum-vulnerable' : datum.key === 256 ? 'ECDSA-P256 — modern elliptic curve' : datum.key === 384 ? 'ECDSA-P384 — strong elliptic curve (CNSA 1.0)' : 'Key size ' + datum.key\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 70 + 52\"}\n ]\n },\n {\n \"name\": \"tot\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"},\n {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"KEY SIZE DISTRIBUTION\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"BIT STRENGTH — click to filter · CNSA 2.0 requires RSA ≥3072 or ECDSA P-384\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 64},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 64},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 63\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"},\n \"text\": {\"field\": \"k\"},\n \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 40\"},\n \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 7\"},\n \"width\": {\"value\": 64}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"field\": \"bg\"},\n \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58 + 32\"}, \"y\": {\"signal\": \"datum.y + 19\"},\n \"text\": {\"field\": \"tier\"},\n \"fill\": {\"field\": \"clr\"},\n \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 27\"},\n \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * 64 : 0\"},\n \"height\": {\"value\": 12}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"signal\": \"datum.clr + '55'\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 50\"},\n \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}}) : kibanaAddFilter({'match_phrase': {'certificate.subject_public_key_info.bit_size': datum.sz}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"by_size\": {\"terms\": {\"field\": \"certificate.subject_public_key_info.bit_size\", \"size\": 15, \"order\": {\"_count\": \"desc\"}}}, \"total\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.by_size.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"sz\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"toString(datum.key) + '-bit'\"}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}, {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.key <= 1024 ? '#ef5350' : datum.key <= 2048 ? '#ffa726' : datum.key <= 3072 ? '#448aff' : '#00c853'\"}, {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.key <= 1024 ? '#ef535018' : datum.key <= 2048 ? '#ffa72618' : datum.key <= 3072 ? '#448aff18' : '#00c85318'\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.key <= 512 ? 'CRITICAL' : datum.key <= 1024 ? 'WEAK' : datum.key <= 2048 ? 'CLASSICAL' : datum.key <= 3072 ? 'STRONG' : 'CNSA 2.0'\"}, {\"type\": \"formula\", \"as\": \"desc\", \"expr\": \"datum.key <= 512 ? 'Trivially breakable \\u2014 remove immediately' : datum.key <= 1024 ? 'Below NIST minimum \\u2014 must be replaced' : datum.key === 2048 ? 'RSA-2048 / ECDSA-P256 \\u2014 classical standard, quantum-vulnerable' : datum.key === 3072 ? 'RSA-3072 \\u2014 transitional strength, quantum-vulnerable' : datum.key === 4096 ? 'RSA-4096 \\u2014 strong classical, quantum-vulnerable' : datum.key === 256 ? 'ECDSA-P256 \\u2014 modern elliptic curve' : datum.key === 384 ? 'ECDSA-P384 \\u2014 strong elliptic curve (CNSA 1.0)' : 'Key size ' + datum.key\"}, {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}}, {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 70 + 52\"}]}, {\"name\": \"tot\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"mx\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"source\": \"raw\", \"transform\": [{\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))>0 ? data('tot')[0].n : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot > 0 ? datum.n / datum.tot : 0\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"KEY SIZE DISTRIBUTION\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"BIT STRENGTH \\u2014 click to filter \\u00b7 CNSA 2.0 requires RSA \\u22653072 or ECDSA P-384\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 64}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 64}, \"fill\": {\"field\": \"clr\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 63\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"k\"}, \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 40\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 7\"}, \"width\": {\"value\": 64}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"field\": \"bg\"}, \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.58 + 32\"}, \"y\": {\"signal\": \"datum.y + 19\"}, \"text\": {\"field\": \"tier\"}, \"fill\": {\"field\": \"clr\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.58\"}, \"y\": {\"signal\": \"datum.y + 27\"}, \"width\": {\"signal\": \"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 64 : 0\"}, \"height\": {\"value\": 12}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.clr + '55'\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"}, \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 50\"}, \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "CERT OPS — Key Size Distribution", "type": "vega", @@ -426,7 +426,7 @@ "description": "", "id": "", "params": { - "spec": "{\n \"$schema\": \"https://vega.github.io/schema/vega/v5.json\",\n \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0},\n \"background\": \"#111111\",\n \"signals\": [\n {\n \"name\": \"sel\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]\n },\n {\n \"name\": \"_kf\", \"value\": null,\n \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}})\", \"force\": true}]\n }\n ],\n \"data\": [\n {\n \"name\": \"raw\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\n \"by_sig\": {\"terms\": {\"field\": \"certificate.signature_algorithm\", \"size\": 15, \"order\": {\"_count\": \"desc\"}}},\n \"total\": {\"value_count\": {\"field\": \"id\"}}\n }}},\n \"format\": {\"property\": \"aggregations.by_sig.buckets\"},\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"},\n {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"},\n {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.key === 'MD5-RSA' ? '#ef5350' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef5350' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa726' : datum.key === 'N/A' || datum.key === '0' ? '#555555' : '#00c853'\"},\n {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.key === 'MD5-RSA' ? '#ef535018' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef535018' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff18' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa72618' : '#55555518'\"},\n {\"type\": \"formula\", \"as\": \"tier\",\"expr\": \"datum.key === 'MD5-RSA' ? 'BROKEN' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? 'LEGACY' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? 'MODERN' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? 'CLASSICAL' : datum.key === 'N/A' || datum.key === '0' ? 'UNKNOWN' : 'PQC READY'\"},\n {\"type\": \"formula\", \"as\": \"desc\",\"expr\": \"datum.key === 'MD5-RSA' ? 'MD5 collision attacks are trivial — critically broken' : datum.key === 'SHA1-RSA' ? 'SHA-1 deprecated — browsers reject, fails compliance' : datum.key === 'DSA-SHA1' ? 'DSA with SHA-1 — both deprecated, remove immediately' : datum.key === 'SHA256-RSA' ? 'RSA with SHA-256 — dominant classical standard' : datum.key === 'SHA384-RSA' ? 'RSA with SHA-384 — stronger hash, still quantum-vulnerable' : datum.key === 'SHA512-RSA' ? 'RSA with SHA-512 — strongest classical RSA variant' : datum.key === 'ECDSA-SHA256' ? 'ECDSA with SHA-256 — modern, efficient, quantum-vulnerable' : datum.key === 'ECDSA-SHA384' ? 'ECDSA with SHA-384 — CNSA 1.0 approved, quantum-vulnerable' : 'Signature algorithm'\"},\n {\"type\": \"filter\", \"expr\": \"datum.k !== 'N/A' \u0026\u0026 datum.k !== '0'\"},\n {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}},\n {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]},\n {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 66 + 52\"}\n ]\n },\n {\n \"name\": \"tot\",\n \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\",\n \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}},\n \"format\": {\"property\": \"aggregations.v\"},\n \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]\n },\n {\n \"name\": \"mx\",\n \"source\": \"raw\",\n \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]\n },\n {\n \"name\": \"rows\",\n \"source\": \"raw\",\n \"transform\": [\n {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"},\n {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}\n ]\n }\n ],\n \"marks\": [\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 18},\n \"text\": {\"value\": \"SIGNATURE ALGORITHM\"},\n \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}\n }}\n },\n {\n \"type\": \"text\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 14}, \"y\": {\"value\": 34},\n \"text\": {\"value\": \"HOW CERTIFICATES ARE SIGNED — click to filter\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rule\",\n \"encode\": {\"enter\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42},\n \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"rect\", \"name\": \"bg\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 60},\n \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"},\n \"cursor\": {\"value\": \"pointer\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 60},\n \"fill\": {\"field\": \"clr\"}\n }}\n },\n {\n \"type\": \"rule\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 59\"},\n \"stroke\": {\"value\": \"#222222\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 20\"},\n \"text\": {\"field\": \"k\"}, \"limit\": {\"signal\": \"width * 0.42\"},\n \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 38\"},\n \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}\n }}\n },\n {\n \"type\": \"rect\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.60\"}, \"y\": {\"signal\": \"datum.y + 6\"},\n \"width\": {\"value\": 68}, \"height\": {\"value\": 15}, \"cornerRadius\": {\"value\": 2},\n \"fill\": {\"field\": \"bg\"},\n \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width * 0.60 + 34\"}, \"y\": {\"signal\": \"datum.y + 18\"},\n \"text\": {\"field\": \"tier\"},\n \"fill\": {\"field\": \"clr\"},\n \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 32\"},\n \"text\": {\"signal\": \"datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"},\n \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"},\n \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n },\n {\n \"type\": \"text\",\n \"from\": {\"data\": \"rows\"},\n \"encode\": {\"update\": {\n \"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 47\"},\n \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"},\n \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9},\n \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}\n }}\n }\n ]\n}\n" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? kibanaRemoveFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}}) : kibanaAddFilter({'match_phrase': {'certificate.signature_algorithm': datum.k}})\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"by_sig\": {\"terms\": {\"field\": \"certificate.signature_algorithm\", \"size\": 15, \"order\": {\"_count\": \"desc\"}}}, \"total\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.by_sig.buckets\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"k\", \"expr\": \"datum.key\"}, {\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.doc_count\"}, {\"type\": \"formula\", \"as\": \"clr\", \"expr\": \"datum.key === 'MD5-RSA' ? '#ef5350' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef5350' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa726' : datum.key === 'N/A' || datum.key === '0' ? '#555555' : '#00c853'\"}, {\"type\": \"formula\", \"as\": \"bg\", \"expr\": \"datum.key === 'MD5-RSA' ? '#ef535018' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? '#ef535018' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? '#448aff18' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? '#ffa72618' : '#55555518'\"}, {\"type\": \"formula\", \"as\": \"tier\", \"expr\": \"datum.key === 'MD5-RSA' ? 'BROKEN' : datum.key === 'DSA-SHA1' || datum.key === 'SHA1-RSA' ? 'LEGACY' : datum.key === 'ECDSA-SHA256' || datum.key === 'ECDSA-SHA384' || datum.key === 'ECDSA-SHA512' ? 'MODERN' : datum.key === 'SHA256-RSA' || datum.key === 'SHA384-RSA' || datum.key === 'SHA512-RSA' ? 'CLASSICAL' : datum.key === 'N/A' || datum.key === '0' ? 'UNKNOWN' : 'PQC READY'\"}, {\"type\": \"formula\", \"as\": \"desc\", \"expr\": \"datum.key === 'MD5-RSA' ? 'MD5 collision attacks are trivial \\u2014 critically broken' : datum.key === 'SHA1-RSA' ? 'SHA-1 deprecated \\u2014 browsers reject, fails compliance' : datum.key === 'DSA-SHA1' ? 'DSA with SHA-1 \\u2014 both deprecated, remove immediately' : datum.key === 'SHA256-RSA' ? 'RSA with SHA-256 \\u2014 dominant classical standard' : datum.key === 'SHA384-RSA' ? 'RSA with SHA-384 \\u2014 stronger hash, still quantum-vulnerable' : datum.key === 'SHA512-RSA' ? 'RSA with SHA-512 \\u2014 strongest classical RSA variant' : datum.key === 'ECDSA-SHA256' ? 'ECDSA with SHA-256 \\u2014 modern, efficient, quantum-vulnerable' : datum.key === 'ECDSA-SHA384' ? 'ECDSA with SHA-384 \\u2014 CNSA 1.0 approved, quantum-vulnerable' : 'Signature algorithm'\"}, {\"type\": \"filter\", \"expr\": \"datum.k !== 'N/A' && datum.k !== '0'\"}, {\"type\": \"collect\", \"sort\": {\"field\": \"n\", \"order\": \"descending\"}}, {\"type\": \"window\", \"ops\": [\"rank\"], \"as\": [\"rnk\"]}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"(datum.rnk - 1) * 66 + 52\"}]}, {\"name\": \"tot\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"mx\", \"source\": \"raw\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}, {\"name\": \"rows\", \"source\": \"raw\", \"transform\": [{\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))>0 ? data('tot')[0].n : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot > 0 ? datum.n / datum.tot : 0\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"SIGNATURE ALGORITHM\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"HOW CERTIFICATES ARE SIGNED \\u2014 click to filter\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 60}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 60}, \"fill\": {\"field\": \"clr\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 59\"}, \"stroke\": {\"value\": \"#222222\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"field\": \"k\"}, \"limit\": {\"signal\": \"width * 0.42\"}, \"fill\": {\"value\": \"#e8e8e8\"}, \"fontSize\": {\"value\": 13}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 38\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.55\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.60\"}, \"y\": {\"signal\": \"datum.y + 6\"}, \"width\": {\"value\": 68}, \"height\": {\"value\": 15}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"field\": \"bg\"}, \"stroke\": {\"field\": \"clr\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.60 + 34\"}, \"y\": {\"signal\": \"datum.y + 18\"}, \"text\": {\"field\": \"tier\"}, \"fill\": {\"field\": \"clr\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 32\"}, \"text\": {\"signal\": \"datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : '#dddddd'\"}, \"fontSize\": {\"value\": 18}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 47\"}, \"text\": {\"signal\": \"format(datum.pct * 100, '.1f') + '%'\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "CERT OPS — Signature Algorithm", "type": "vega", @@ -446,7 +446,7 @@ }, { "embeddableConfig": { - "description": "Certificate lifetime buckets: automated (≤90d) through legacy (\u003e5yr) with key management system insight", + "description": "Certificate lifetime buckets: automated (≤90d) through legacy (>5yr) with key management system insight", "enhancements": { "dynamicActions": { "events": [ @@ -479,10 +479,10 @@ } } }, - "description": "Certificate lifetime buckets: automated (≤90d) through legacy (\u003e5yr) with key management system insight", + "description": "Certificate lifetime buckets: automated (≤90d) through legacy (>5yr) with key management system insight", "id": "", "params": { - "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.n \u003e 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"le90d\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();if(na\u003c=System.currentTimeMillis())return false;long d=(na-nb)/86400000L;return d\u003e=0\u0026\u0026d\u003c=90;\"}}}}, \"le1yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e90\u0026\u0026d\u003c=365;\"}}}}, \"le825d\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e365\u0026\u0026d\u003c=825;\"}}}}, \"le5yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e825\u0026\u0026d\u003c=1825;\"}}}}, \"gt5yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d\u003e1825;\"}}}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"le90d\", \"expr\": \"datum.le90d ? datum.le90d.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le1yr\", \"expr\": \"datum.le1yr ? datum.le1yr.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le825d\", \"expr\": \"datum.le825d ? datum.le825d.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le5yr\", \"expr\": \"datum.le5yr ? datum.le5yr.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"gt5yr\", \"expr\": \"datum.gt5yr ? datum.gt5yr.doc_count : 0\"}]}, {\"name\": \"tot\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"certificate.not_after\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"le90d\", \"lbl\": \"Automated \\u226490 days\", \"mgmt\": \"KEY MGT SYSTEM\", \"desc\": \"Almost certainly managed by ACME / Let's Encrypt / cert-manager \\u2014 short lifetime is a signature of automated issuance\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0, \"field\": \"le90d\", \"filt\": {\"range\": {\"cert_total_days\": {\"gte\": 0, \"lte\": 90}}}}, {\"k\": \"le1yr\", \"lbl\": \"Short-lived \\u22641 year\", \"mgmt\": \"LIKELY MANAGED\", \"desc\": \"Annual lifetime pattern \\u2014 may be automated renewal or disciplined manual rotation by an ops team\", \"clr\": \"#4db6ac\", \"bg\": \"#4db6ac18\", \"ord\": 1, \"field\": \"le1yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 90, \"lte\": 365}}}}, {\"k\": \"le825d\", \"lbl\": \"Modern \\u2264825 days\", \"mgmt\": \"CA ISSUED\", \"desc\": \"Within Apple / browser maximum trust limit (825 days) \\u2014 actively issued by a real CA, rotation expected\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2, \"field\": \"le825d\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 365, \"lte\": 825}}}}, {\"k\": \"le5yr\", \"lbl\": \"Long-lived \\u22645 years\", \"mgmt\": \"MANUAL\", \"desc\": \"826\\u20131825 day lifetime \\u2014 manually managed, no automated rotation, quantum risk grows over the certificate's life\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 3, \"field\": \"le5yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 825, \"lte\": 1825}}}}, {\"k\": \"gt5yr\", \"lbl\": \"Legacy \u003e 5 years\", \"mgmt\": \"LEGACY / MANUAL\", \"desc\": \"5+ year validity \\u2014 definitely manually issued; each year of remaining life increases the window for harvest-now-decrypt-later attacks\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 4, \"field\": \"gt5yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 1825}}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"length(data('raw'))\u003e0 ? (datum.field==='le90d' ? data('raw')[0].le90d : datum.field==='le1yr' ? data('raw')[0].le1yr : datum.field==='le825d' ? data('raw')[0].le825d : datum.field==='le5yr' ? data('raw')[0].le5yr : data('raw')[0].gt5yr) : 0\"}, {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))\u003e0 ? data('tot')[0].n : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot \u003e 0 ? datum.n / datum.tot : 0\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 52\"}]}, {\"name\": \"mx\", \"source\": \"rows\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE LONGEVITY\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"CERTIFICATE LIFETIME \\u2014 short = automated key management \\u00b7 long = manual / legacy\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n\u003e0 ? '#161616' : '#121212'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.52\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 42\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.74\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76 + 41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"field\": \"mgmt\"}, \"fill\": {\"signal\": \"datum.n\u003e0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76\"}, \"y\": {\"signal\": \"datum.y + 28\"}, \"width\": {\"signal\": \"length(data('mx'))\u003e0 \u0026\u0026 data('mx')[0].v \u003e 0 ? (datum.n / data('mx')[0].v) * 82 : 0\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.clr + '44'\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n \u003e 0 ? (datum.n \u003e= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.n\u003e0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 52\"}, \"text\": {\"signal\": \"datum.tot \u003e 0 \u0026\u0026 datum.n \u003e 0 ? format(datum.pct * 100, '.1f') + '%' : ''\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}]}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"bg\"}, \"update\": \"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"raw\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"le90d\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();if(na<=System.currentTimeMillis())return false;long d=(na-nb)/86400000L;return d>=0&&d<=90;\"}}}}, \"le1yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>90&&d<=365;\"}}}}, \"le825d\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>365&&d<=825;\"}}}}, \"le5yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>825&&d<=1825;\"}}}}, \"gt5yr\": {\"filter\": {\"script\": {\"script\": {\"lang\": \"painless\", \"source\": \"if(doc['certificate.not_before'].size()==0||doc['certificate.not_after'].size()==0)return false;long nb=doc['certificate.not_before'].value.toInstant().toEpochMilli();long na=doc['certificate.not_after'].value.toInstant().toEpochMilli();long d=(na-nb)/86400000L;return d>1825;\"}}}}}}}, \"format\": {\"property\": \"aggregations\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"le90d\", \"expr\": \"datum.le90d ? datum.le90d.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le1yr\", \"expr\": \"datum.le1yr ? datum.le1yr.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le825d\", \"expr\": \"datum.le825d ? datum.le825d.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"le5yr\", \"expr\": \"datum.le5yr ? datum.le5yr.doc_count : 0\"}, {\"type\": \"formula\", \"as\": \"gt5yr\", \"expr\": \"datum.gt5yr ? datum.gt5yr.doc_count : 0\"}]}, {\"name\": \"tot\", \"url\": {\"%context%\": true, \"%timefield%\": \"@timestamp\", \"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"certificate.not_after\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"le90d\", \"lbl\": \"Automated \\u226490 days\", \"mgmt\": \"KEY MGT SYSTEM\", \"desc\": \"Almost certainly managed by ACME / Let's Encrypt / cert-manager \\u2014 short lifetime is a signature of automated issuance\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"ord\": 0, \"field\": \"le90d\", \"filt\": {\"range\": {\"cert_total_days\": {\"gte\": 0, \"lte\": 90}}}}, {\"k\": \"le1yr\", \"lbl\": \"Short-lived \\u22641 year\", \"mgmt\": \"LIKELY MANAGED\", \"desc\": \"Annual lifetime pattern \\u2014 may be automated renewal or disciplined manual rotation by an ops team\", \"clr\": \"#4db6ac\", \"bg\": \"#4db6ac18\", \"ord\": 1, \"field\": \"le1yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 90, \"lte\": 365}}}}, {\"k\": \"le825d\", \"lbl\": \"Modern \\u2264825 days\", \"mgmt\": \"CA ISSUED\", \"desc\": \"Within Apple / browser maximum trust limit (825 days) \\u2014 actively issued by a real CA, rotation expected\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"ord\": 2, \"field\": \"le825d\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 365, \"lte\": 825}}}}, {\"k\": \"le5yr\", \"lbl\": \"Long-lived \\u22645 years\", \"mgmt\": \"MANUAL\", \"desc\": \"826\\u20131825 day lifetime \\u2014 manually managed, no automated rotation, quantum risk grows over the certificate's life\", \"clr\": \"#ffa726\", \"bg\": \"#ffa72618\", \"ord\": 3, \"field\": \"le5yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 825, \"lte\": 1825}}}}, {\"k\": \"gt5yr\", \"lbl\": \"Legacy > 5 years\", \"mgmt\": \"LEGACY / MANUAL\", \"desc\": \"5+ year validity \\u2014 definitely manually issued; each year of remaining life increases the window for harvest-now-decrypt-later attacks\", \"clr\": \"#ef5350\", \"bg\": \"#ef535018\", \"ord\": 4, \"field\": \"gt5yr\", \"filt\": {\"range\": {\"cert_total_days\": {\"gt\": 1825}}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"length(data('raw'))>0 ? (datum.field==='le90d' ? data('raw')[0].le90d : datum.field==='le1yr' ? data('raw')[0].le1yr : datum.field==='le825d' ? data('raw')[0].le825d : datum.field==='le5yr' ? data('raw')[0].le5yr : data('raw')[0].gt5yr) : 0\"}, {\"type\": \"formula\", \"as\": \"tot\", \"expr\": \"length(data('tot'))>0 ? data('tot')[0].n : 1\"}, {\"type\": \"formula\", \"as\": \"pct\", \"expr\": \"datum.tot > 0 ? datum.n / datum.tot : 0\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 72 + 52\"}]}, {\"name\": \"mx\", \"source\": \"rows\", \"transform\": [{\"type\": \"aggregate\", \"ops\": [\"max\"], \"fields\": [\"n\"], \"as\": [\"v\"]}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE LONGEVITY\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"CERTIFICATE LIFETIME \\u2014 short = automated key management \\u00b7 long = manual / legacy\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.k===sel ? '#1c1c2e' : datum.n>0 ? '#161616' : '#121212'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 66}, \"fill\": {\"signal\": \"datum.n>0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 65\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 22\"}, \"text\": {\"field\": \"lbl\"}, \"limit\": {\"signal\": \"width * 0.52\"}, \"fill\": {\"signal\": \"datum.n>0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 12}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 42\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.74\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76\"}, \"y\": {\"signal\": \"datum.y + 8\"}, \"width\": {\"value\": 82}, \"height\": {\"value\": 16}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n>0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n>0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76 + 41\"}, \"y\": {\"signal\": \"datum.y + 20\"}, \"text\": {\"field\": \"mgmt\"}, \"fill\": {\"signal\": \"datum.n>0 ? datum.clr : '#383838'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width * 0.76\"}, \"y\": {\"signal\": \"datum.y + 28\"}, \"width\": {\"signal\": \"length(data('mx'))>0 && data('mx')[0].v > 0 ? (datum.n / data('mx')[0].v) * 82 : 0\"}, \"height\": {\"value\": 8}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.clr + '44'\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 36\"}, \"text\": {\"signal\": \"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n,'.3~s') : format(datum.n,',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.k===sel ? datum.clr : datum.n>0 ? '#dddddd' : '#333333'\"}, \"fontSize\": {\"value\": 20}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 52\"}, \"text\": {\"signal\": \"datum.tot > 0 && datum.n > 0 ? format(datum.pct * 100, '.1f') + '%' : ''\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('raw')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "Certificate Longevity", "type": "vega", @@ -538,7 +538,7 @@ "description": "File system disk scan vs live TLS port capture — how each certificate was discovered", "id": "", "params": { - "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"row_bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"row_bg\"}, \"update\": \"datum.n \u003e 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"d_fs\", \"url\": {\"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"query\": {\"term\": {\"tychon.type\": \"filesystem\"}}, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value || 0\"}]}, {\"name\": \"d_port\", \"url\": {\"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"query\": {\"bool\": {\"must\": [{\"exists\": {\"field\": \"x509.subject.common_name\"}}, {\"term\": {\"tychon.type\": \"cipher\"}}]}}, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"tychon.type\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value || 0\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"fs\", \"ord\": 0, \"lbl\": \"File System\", \"badge\": \"DISK\", \"sub\": \"Certificates read from disk \\u2014 PEM/DER files, keystores, application bundles\", \"desc\": \"Found by crawling the local filesystem. Source path is known. These certs may not be actively serving traffic \\u2014 they could be backups, bundled CA roots, or application trust stores.\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"icon\": \"\\u2399\", \"filt\": {\"match_phrase\": {\"tychon.type\": \"filesystem\"}}}, {\"k\": \"port\", \"ord\": 1, \"lbl\": \"Port / Network\", \"badge\": \"NETWORK\", \"sub\": \"Certificates captured live from TLS handshakes on open network ports\", \"desc\": \"Captured during an active TLS scan. These certs are definitely in use serving live traffic. Quantum readiness score and cipher suite are also available for these entries.\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"icon\": \"\\u26a1\", \"filt\": {\"match_phrase\": {\"tychon.type\": \"cipher\"}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.k === 'fs' ? (length(data('d_fs'))\u003e0 ? data('d_fs')[0].n : 0) : (length(data('d_port'))\u003e0 ? data('d_port')[0].n : 0)\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 134 + 52\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SOURCE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"HOW CERTIFICATES WERE DISCOVERED \\u2014 file scan vs live TLS capture\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"row_bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 128}, \"fill\": {\"signal\": \"datum.k === sel ? '#1c1c2e' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 128}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 127\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 10\"}, \"width\": {\"value\": 56}, \"height\": {\"value\": 18}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 42}, \"y\": {\"signal\": \"datum.y + 23\"}, \"text\": {\"field\": \"badge\"}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#333333'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 78}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"field\": \"lbl\"}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"field\": \"sub\"}, \"limit\": {\"signal\": \"width * 0.82\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 64\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.64\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 70\"}, \"text\": {\"signal\": \"datum.n \u003e 0 ? (datum.n \u003e= 1000 ? format(datum.n, '.3~s') : format(datum.n, ',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.n \u003e 0 ? datum.clr : '#333333'\"}, \"fontSize\": {\"value\": 32}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 88\"}, \"text\": {\"value\": \"certificates\"}, \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}]}" + "spec": "{\"$schema\": \"https://vega.github.io/schema/vega/v5.json\", \"padding\": {\"top\": 0, \"bottom\": 0, \"left\": 0, \"right\": 0}, \"background\": \"#111111\", \"signals\": [{\"name\": \"sel\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"row_bg\"}, \"update\": \"datum.k === sel ? null : datum.k\", \"force\": true}]}, {\"name\": \"_kf\", \"value\": null, \"on\": [{\"events\": {\"type\": \"click\", \"markname\": \"row_bg\"}, \"update\": \"datum.n > 0 ? (datum.k === sel ? kibanaRemoveFilter(datum.filt) : kibanaAddFilter(datum.filt)) : null\", \"force\": true}]}], \"data\": [{\"name\": \"d_fs\", \"url\": {\"index\": \"tychon-pqc-certificates*\", \"body\": {\"size\": 0, \"query\": {\"bool\": {\"must\": [\"%dashboard_context-must_clause%\", {\"range\": {\"@timestamp\": {\"%timefilter%\": true}}}, {\"term\": {\"tychon.type\": \"filesystem\"}}], \"filter\": [\"%dashboard_context-filter_clause%\"], \"must_not\": [\"%dashboard_context-must_not_clause%\"]}}, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"id\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value || 0\"}]}, {\"name\": \"d_port\", \"url\": {\"index\": \"tychon-pqc-inventory*\", \"body\": {\"size\": 0, \"query\": {\"bool\": {\"must\": [\"%dashboard_context-must_clause%\", {\"range\": {\"@timestamp\": {\"%timefilter%\": true}}}, {\"exists\": {\"field\": \"x509.subject.common_name\"}}, {\"term\": {\"tychon.type\": \"cipher\"}}], \"filter\": [\"%dashboard_context-filter_clause%\"], \"must_not\": [\"%dashboard_context-must_not_clause%\"]}}, \"aggs\": {\"v\": {\"value_count\": {\"field\": \"tychon.type\"}}}}}, \"format\": {\"property\": \"aggregations.v\"}, \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.value || 0\"}]}, {\"name\": \"rows\", \"values\": [{\"k\": \"fs\", \"ord\": 0, \"lbl\": \"File System\", \"badge\": \"DISK\", \"sub\": \"Certificates read from disk \\u2014 PEM/DER files, keystores, application bundles\", \"desc\": \"Found by crawling the local filesystem. Source path is known. These certs may not be actively serving traffic \\u2014 they could be backups, bundled CA roots, or application trust stores.\", \"clr\": \"#448aff\", \"bg\": \"#448aff18\", \"icon\": \"\\u2399\", \"filt\": {\"match_phrase\": {\"tychon.type\": \"filesystem\"}}}, {\"k\": \"port\", \"ord\": 1, \"lbl\": \"Port / Network\", \"badge\": \"NETWORK\", \"sub\": \"Certificates captured live from TLS handshakes on open network ports\", \"desc\": \"Captured during an active TLS scan. These certs are definitely in use serving live traffic. Quantum readiness score and cipher suite are also available for these entries.\", \"clr\": \"#00c853\", \"bg\": \"#00c85318\", \"icon\": \"\\u26a1\", \"filt\": {\"match_phrase\": {\"tychon.type\": \"cipher\"}}}], \"transform\": [{\"type\": \"formula\", \"as\": \"n\", \"expr\": \"datum.k === 'fs' ? (length(data('d_fs'))>0 ? data('d_fs')[0].n : 0) : (length(data('d_port'))>0 ? data('d_port')[0].n : 0)\"}, {\"type\": \"formula\", \"as\": \"y\", \"expr\": \"datum.ord * 134 + 52\"}]}], \"marks\": [{\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 18}, \"text\": {\"value\": \"CERTIFICATE SOURCE\"}, \"fill\": {\"value\": \"#cccccc\"}, \"fontSize\": {\"value\": 10}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1.5}}}}, {\"type\": \"text\", \"encode\": {\"enter\": {\"x\": {\"value\": 14}, \"y\": {\"value\": 34}, \"text\": {\"value\": \"HOW CERTIFICATES WERE DISCOVERED \\u2014 file scan vs live TLS capture\"}, \"fill\": {\"value\": \"#555555\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"letterSpacing\": {\"value\": 1}}}}, {\"type\": \"rule\", \"encode\": {\"enter\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"value\": 42}, \"stroke\": {\"value\": \"#252525\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"rect\", \"name\": \"row_bg\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"signal\": \"width\"}, \"height\": {\"value\": 128}, \"fill\": {\"signal\": \"datum.k === sel ? '#1c1c2e' : '#161616'\"}, \"cursor\": {\"value\": \"pointer\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"y\": {\"field\": \"y\"}, \"width\": {\"value\": 4}, \"height\": {\"value\": 128}, \"fill\": {\"signal\": \"datum.n > 0 ? datum.clr : '#2a2a2a'\"}}}}, {\"type\": \"rule\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 0}, \"x2\": {\"signal\": \"width\"}, \"y\": {\"signal\": \"datum.y + 127\"}, \"stroke\": {\"value\": \"#1e1e1e\"}}}}, {\"type\": \"rect\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 10\"}, \"width\": {\"value\": 56}, \"height\": {\"value\": 18}, \"cornerRadius\": {\"value\": 2}, \"fill\": {\"signal\": \"datum.n > 0 ? datum.bg : '#1a1a1a'\"}, \"stroke\": {\"signal\": \"datum.n > 0 ? datum.clr : '#2a2a2a'\"}, \"strokeWidth\": {\"value\": 1}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 42}, \"y\": {\"signal\": \"datum.y + 23\"}, \"text\": {\"field\": \"badge\"}, \"fill\": {\"signal\": \"datum.n > 0 ? datum.clr : '#333333'\"}, \"fontSize\": {\"value\": 8}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"center\"}, \"letterSpacing\": {\"value\": 0.8}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 78}, \"y\": {\"signal\": \"datum.y + 24\"}, \"text\": {\"field\": \"lbl\"}, \"fill\": {\"signal\": \"datum.n > 0 ? '#e8e8e8' : '#444444'\"}, \"fontSize\": {\"value\": 14}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 44\"}, \"text\": {\"field\": \"sub\"}, \"limit\": {\"signal\": \"width * 0.82\"}, \"fill\": {\"value\": \"#666666\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"value\": 14}, \"y\": {\"signal\": \"datum.y + 64\"}, \"text\": {\"field\": \"desc\"}, \"limit\": {\"signal\": \"width * 0.64\"}, \"fill\": {\"value\": \"#444444\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 70\"}, \"text\": {\"signal\": \"datum.n > 0 ? (datum.n >= 1000 ? format(datum.n, '.3~s') : format(datum.n, ',')) : '\\u2014'\"}, \"fill\": {\"signal\": \"datum.n > 0 ? datum.clr : '#333333'\"}, \"fontSize\": {\"value\": 32}, \"fontWeight\": {\"value\": \"bold\"}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"from\": {\"data\": \"rows\"}, \"encode\": {\"update\": {\"x\": {\"signal\": \"width - 10\"}, \"y\": {\"signal\": \"datum.y + 88\"}, \"text\": {\"value\": \"certificates\"}, \"fill\": {\"value\": \"#3a3a3a\"}, \"fontSize\": {\"value\": 9}, \"font\": {\"value\": \"monospace\"}, \"align\": {\"value\": \"right\"}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 - 8\"}, \"text\": {\"signal\": \"length(data('d_fs')) === 0 ? 'NO DATA FOR CURRENT FILTERS / TIME RANGE' : ''\"}, \"fill\": {\"value\": \"#666666\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 11}, \"fontWeight\": {\"value\": \"bold\"}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}, {\"type\": \"text\", \"encode\": {\"update\": {\"x\": {\"signal\": \"width / 2\"}, \"y\": {\"signal\": \"height / 2 + 12\"}, \"text\": {\"signal\": \"length(data('d_fs')) === 0 ? 'Adjust dashboard filters or expand the selected time range.' : ''\"}, \"fill\": {\"value\": \"#444444\"}, \"font\": {\"value\": \"monospace\"}, \"fontSize\": {\"value\": 9}, \"align\": {\"value\": \"center\"}, \"baseline\": {\"value\": \"middle\"}, \"zindex\": {\"value\": 100}}}}]}" }, "title": "Certificate Source Type", "type": "vega", @@ -580,11 +580,11 @@ } ], "timeRestore": false, - "title": "[TYCHON Quantum Command] Certificate Operations Dashboard", + "title": "[TYCHON Quantum Command] Certificate Operations Dashboard", "version": 3 }, "coreMigrationVersion": "8.8.0", - "created_at": "2026-07-21T14:29:29.805Z", + "created_at": "2026-07-20T16:55:14.701Z", "id": "tychon_quantum_command-d0159137-9139-4a93-85bb-2ac9ddab3982-certificate-operations-dashboard", "references": [ { @@ -650,4 +650,4 @@ ], "type": "dashboard", "typeMigrationVersion": "10.3.0" -} \ No newline at end of file +} diff --git a/packages/tychon_quantum_command/manifest.yml b/packages/tychon_quantum_command/manifest.yml index f156ef41006..442ee62f8df 100644 --- a/packages/tychon_quantum_command/manifest.yml +++ b/packages/tychon_quantum_command/manifest.yml @@ -51,5 +51,5 @@ policy_templates: title: Collect TQC output description: Collect NDJSON or JSON files generated by TQC. owner: - github: tychonllc + github: elastic/security-service-integrations type: partner diff --git a/packages/tychon_quantum_command/sample_event.json b/packages/tychon_quantum_command/sample_event.json deleted file mode 100644 index 477c749dbeb..00000000000 --- a/packages/tychon_quantum_command/sample_event.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "@timestamp": "2026-06-11T12:00:00Z", - "event": { - "kind": "event", - "category": ["configuration"], - "dataset": "tychon_quantum_command.tychon_pqc" - }, - "data_stream": { - "type": "logs", - "dataset": "tychon_quantum_command.tychon_pqc", - "namespace": "default" - }, - "ecs": { - "version": "8.17.0" - }, - "host": { - "hostname": "server01" - }, - "tychon": { - "index": "applications", - "asset_type": "application", - "scan_mode": "quantum_command", - "pqc_readiness": "partial", - "quantum_risk": "medium", - "application": { - "name": "Example Service", - "port": 443, - "preferred_protocol": "TLSv1.3", - "preferred_cipher": "TLS_AES_256_GCM_SHA384", - "preferred_key_exchange": "ECDHE", - "port_quantum_grade": { - "grade": "B", - "score": 82.5 - } - } - } -}

      WZL&NM|;<3+-Kr>g%bpM9ex7-wK9{{01w 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