cloudwire 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&display=swap";.cloudwire-page{height:100vh;display:grid;grid-template-rows:auto minmax(0,1fr);gap:10px;padding:10px;overflow:hidden;background:radial-gradient(circle at top,rgba(255,153,0,.08),transparent 26%),radial-gradient(circle at 80% 18%,rgba(0,231,255,.08),transparent 18%),#05080d;color:#d6e3ef}.topbar-shell,.sidebar-shell,.inspector-shell,.graph-stage-shell{background:#070d14;border:1px solid #0f1e2a;box-shadow:none}.topbar-shell{border-radius:0;padding:0 24px;height:52px;overflow:visible;display:flex;align-items:center;justify-content:space-between;position:relative;z-index:100}.topbar-left,.topbar-right{display:flex;align-items:center;gap:12px}.topbar-right{min-width:0}.topbar-mark{display:flex;align-items:center;gap:8px}.topbar-mark-dot{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px}.topbar-brand{font-size:15px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:#e8c888}.topbar-divider{width:1px;height:20px;background:#1a2a38}.topbar-kicker,.sidebar-section-title,.inspector-kicker{color:#2a4a5a;font-size:11px;letter-spacing:.2em;text-transform:uppercase}.topbar-compact-select,.topbar-services-inline{height:32px;border:1px solid #1a2a38;background:#0c1820;color:#c8d8e8;padding:0 10px;font:inherit;font-size:12px}.topbar-region-select{color:#3a5a6a}.topbar-services-inline{width:260px}.topbar-scan-inline{display:flex;align-items:center;gap:8px;color:#f90;font-size:12px}.topbar-inline-progress-track{width:120px;height:3px;background:#0c1a24;border-radius:2px;overflow:hidden}.topbar-inline-progress-fill{height:100%;background:linear-gradient(90deg,#f60,#f90);transition:width .3s}.topbar-done{font-size:12px;color:#0f8;letter-spacing:.12em}.topbar-primary-btn,.topbar-secondary-btn,.sidebar-pill,.sidebar-control-list button,.inspector-header button,.graph-stage-toggle,.canvas-controls-panel button{font:inherit;cursor:pointer}.topbar-primary-btn,.topbar-secondary-btn{padding:8px 18px;font-size:13px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;border:none;clip-path:polygon(6px 0%,100% 0%,calc(100% - 6px) 100%,0% 100%)}.topbar-primary-btn{background:linear-gradient(135deg,#f90,#f60);color:#060a0f}.topbar-secondary-btn{background:transparent;border:1px solid #1a2a38;color:#3a5a70;clip-path:none}.topbar-primary-btn:disabled,.topbar-secondary-btn:disabled,.canvas-controls-panel button:disabled,.graph-stage-toggle:disabled{cursor:not-allowed;opacity:.45}.cloudwire-layout{display:flex;min-height:0;height:100%;overflow:hidden}.sidebar-shell,.inspector-shell{border-radius:0;padding:16px 0;overflow:hidden;display:flex;flex-direction:column;gap:16px;min-height:0;flex-shrink:0}.sidebar-shell{width:200px;border-right:1px solid #0f1e2a}.sidebar-block{padding-bottom:0;border-bottom:none}.sidebar-block-grow{min-height:0;flex:1 1 auto;display:flex;flex-direction:column}.sidebar-block+.sidebar-block{padding-top:14px;border-top:1px solid #0f1e2a}.inspector-shell{width:300px;padding:16px 18px 18px;border-left:1px solid #0f1e2a;background:#07090d}.sidebar-shell section{padding:0 14px}.sidebar-section-title{margin-bottom:10px}.sidebar-services-list,.sidebar-results-list,.inspector-meta-list,.inspector-connection-list{display:flex;flex-direction:column;gap:0;overflow:auto;min-height:0}.sidebar-service-main{display:inline-flex;align-items:center;gap:6px}.sidebar-filter-pill{background:transparent;border:1px solid #1e3040;color:#5a7a90;font-family:inherit;font-size:12px;letter-spacing:.1em;padding:4px 10px;cursor:pointer;transition:all .15s;display:flex;justify-content:space-between;align-items:center;width:calc(100% + -0px);margin:2px 0;border-radius:2px}.sidebar-filter-pill.active,.sidebar-filter-pill:hover{background:#0d2030;border-color:#f90;color:#f90}.sidebar-filter-pill:not(.active) .sidebar-row-count{opacity:.6}.sidebar-row-count{font-size:11px;opacity:.6}.sidebar-service-icon,.inspector-icon{display:inline-flex;align-items:center;justify-content:center}.sidebar-service-icon svg{width:13px;height:13px}.sidebar-stats-list{display:flex;flex-direction:column;gap:0}.sidebar-stat-row{display:flex;justify-content:space-between;font-size:12px;color:#3a6a80;margin-bottom:6px}.sidebar-stat-row strong,.sidebar-empty-state,.inspector-empty,.inspector-id,.graph-stage-error{color:#3a6a80;font-size:12px}.sidebar-stat-row strong{color:#c8a860;font-weight:500}.sidebar-control-list{display:flex;flex-direction:column;gap:0}.sidebar-control-link{font-family:inherit;font-size:12px;color:#3a6080;padding:5px 8px;cursor:pointer;border-left:2px solid transparent;transition:all .15s;text-align:left;background:transparent;border-top:none;border-right:none;border-bottom:none}.sidebar-control-link:hover{color:#c8a860;border-left-color:#f90}.sidebar-search-input{font-family:inherit;font-size:12px;border-bottom:1px solid #1a2a38;margin-bottom:8px;padding-left:0;padding-right:0;border-top:none;border-left:none;border-right:none;background:transparent;color:#c8d8e8}.sidebar-search-input::-moz-placeholder{color:#294355}.sidebar-search-input::placeholder{color:#294355}.sidebar-search-section{min-height:0;display:flex;flex-direction:column;overflow:hidden}.sidebar-results-list{min-height:0;flex:1 1 auto}.sidebar-result-row{width:100%;display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:6px 0;border:none;background:transparent;color:#8aacbe;text-align:left;cursor:pointer}.sidebar-result-row:hover,.sidebar-result-row.active{color:#f90}.sidebar-result-row strong{font-size:12px;font-weight:400;color:inherit}.sidebar-result-row span{font-size:11px;color:#3a5a70;text-transform:uppercase;letter-spacing:.1em;opacity:.7}.sidebar-empty-state{padding:6px 0;color:#3a6a80;font-size:12px}.graph-stage-shell{flex:1 1 auto;border-radius:0;padding:0;display:block;min-height:0;overflow:hidden;border-left:none;border-right:none;position:relative}.graph-stage-error{position:absolute;bottom:48px;left:16px;z-index:5;max-width:420px;padding:7px 12px;background:#ff3c3c1a;border:1px solid rgba(255,60,60,.3);color:#f88;font-size:12px;letter-spacing:.03em;border-radius:2px}.graph-stage-error--resource{bottom:92px;background:#ffa0001a;border-color:#ffa0004d;color:#ffb84d}.graph-stage-error--info{bottom:92px;background:#00b4e01a;border-color:#00b4e04d;color:#00b4e0}.graph-canvas{position:relative;min-height:0;height:100%;overflow:hidden;border-radius:0;border:none;background:#060a0f}.graph-canvas-backdrop,.graph-canvas-grid{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.graph-canvas-backdrop{background:radial-gradient(circle at 18% 18%,rgba(255,153,0,.09),transparent 22%),radial-gradient(circle at 72% 28%,rgba(0,231,255,.08),transparent 19%),radial-gradient(circle at 46% 72%,rgba(123,45,139,.08),transparent 16%),linear-gradient(180deg,#070a0ff5,#04070b)}.graph-canvas-grid{background-image:linear-gradient(rgba(18,28,36,.55) 1px,transparent 1px),linear-gradient(90deg,rgba(18,28,36,.55) 1px,transparent 1px),linear-gradient(rgba(23,35,44,.74) 1px,transparent 1px),linear-gradient(90deg,rgba(23,35,44,.74) 1px,transparent 1px);background-size:20px 20px,20px 20px,100px 100px,100px 100px}.graph-canvas-header,.graph-canvas-corner,.graph-canvas-footer{position:absolute;z-index:2}.graph-canvas-footer{left:12px;bottom:12px;font-size:11px;color:#2a4a5a;letter-spacing:.1em;text-transform:uppercase}.graph-canvas-corner{right:12px;bottom:12px;display:flex;gap:8px;flex-wrap:wrap}.graph-svg{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%}.graph-annotation rect{fill:#060a0f8c;stroke:#0f2030;stroke-width:1}.graph-annotation text{fill:#294355;font-size:10px;letter-spacing:.12em;text-transform:uppercase}.graph-annotation-subtitle{fill:#213849;font-size:9px}.graph-legend{display:flex;gap:8px;flex-wrap:wrap;max-width:280px;justify-content:flex-end}.graph-legend-item{display:inline-flex;align-items:center;gap:4px;padding:0;border:none;background:transparent;font-size:11px;color:#3a5a70}.graph-legend-dot{width:8px;height:8px;border-radius:999px}.graph-legend-icon{display:inline-flex;align-items:center;justify-content:center}.graph-legend-icon svg{width:11px;height:11px}.graph-edge-path{filter:none}.graph-node-center-icon{width:24px;height:24px;display:flex;align-items:center;justify-content:center}.graph-node-label{fill:#8aacbe;font-size:11px}.graph-node-kind{font-size:10px;opacity:.7}.inspector-shell{min-height:0;overflow:hidden}.inspector-meta-list,.inspector-connection-list{max-height:none}.inspector-header{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}.inspector-header button{background:transparent;border:1px solid #1a2a38;color:#3a5a70;font-size:12px;padding:4px 8px}.inspector-header h2{margin:4px 0 0;color:#e8d8b8;font-size:17px;line-height:1.2}.inspector-identity{display:flex;align-items:center;margin-top:10px;gap:6px}.inspector-status-row{margin-top:10px}.inspector-status-pill{display:inline-flex;align-items:center;gap:5px;background:#0a1820;padding:4px 8px;border:1px solid;font-size:11px;letter-spacing:.1em}.inspector-status-dot{width:5px;height:5px;border-radius:50%;display:inline-block}.inspector-icon{width:auto;height:auto;padding:2px 8px;font-size:11px;background:#0c1820;border:1px solid;color:#2a4a5a}.inspector-chip-row{margin-top:10px;display:flex;gap:6px;flex-wrap:wrap}.inspector-chip{font-size:11px;color:#2a4a5a;background:#0c1820;padding:2px 8px;border:1px solid #1a2a38}.inspector-accent{height:2px;margin:12px -18px}.inspector-meta-row{display:flex;gap:8px;justify-content:space-between;padding:5px 0;border-bottom:1px solid #0d2030;font-size:13px}.inspector-meta-row span{color:#3a6a80;padding-right:10px}.inspector-meta-row strong{color:#c8b880;text-align:right;font-weight:500;word-break:break-word}.inspector-connection-row{justify-content:flex-start;width:100%;display:flex;align-items:center;gap:8px;padding:6px 0;cursor:pointer;border:none;background:transparent;border-bottom:1px solid #0a1420;text-align:left}.inspector-connection-row div{display:flex;flex-direction:column;gap:4px}.inspector-connection-arrow{font-size:12px;min-width:16px}.inspector-connection-row strong{color:#8aacbe;font-size:12px;font-weight:400}.inspector-connection-row span{color:#3a5a70;font-size:12px;text-transform:uppercase;letter-spacing:.1em}@media(max-width:1440px){.cloudwire-layout{gap:0}}@media(max-width:1200px){.cloudwire-layout{display:grid;grid-template-columns:200px minmax(0,1fr);position:relative}.inspector-shell{position:absolute;right:0;top:0;bottom:0;z-index:20;border-left:1px solid #1a2a38;box-shadow:-8px 0 24px #00000080}}.graph-stage-warnings{position:absolute;bottom:48px;left:16px;right:16px;z-index:5;background:#b478001f;border:1px solid rgba(255,153,0,.3);color:#c80;font-size:11px;letter-spacing:.08em;padding:5px 10px;border-radius:2px}.graph-stage-loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#3a5a70;font-size:13px;letter-spacing:.15em;text-transform:uppercase}.graph-empty-state{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;max-width:360px;pointer-events:none}.graph-empty-title{font-size:14px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:#3a5a70;margin-bottom:10px}.graph-empty-hint{font-size:12px;color:#2a3f4f;line-height:1.6;letter-spacing:.03em}.graph-empty-hint strong{color:#4a7a90;font-weight:600}.layout-select-wrap{position:relative;flex-shrink:0}.layout-select-trigger{display:flex;align-items:center;gap:7px;height:32px;padding:0 10px 0 12px;background:#0c1820;border:1px solid #1a2a38;color:#4a7a90;font:inherit;font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;transition:border-color .15s,color .15s,background .15s;white-space:nowrap}.layout-select-trigger:hover,.layout-select-trigger.open{border-color:#f90;color:#f90;background:#0f1e28}.layout-select-trigger-icon{font-size:13px;line-height:1}.layout-select-caret{font-size:8px;opacity:.55;margin-left:2px}.layout-select-panel{position:absolute;top:calc(100% + 5px);right:0;z-index:300;width:180px;background:#070d14;border:1px solid #1a2a38;box-shadow:0 12px 40px #000000b3,0 0 0 1px #ff990012,inset 0 1px #ffffff08;padding:4px 0}.layout-select-item{display:flex;align-items:center;gap:10px;padding:8px 14px;cursor:pointer;font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:#5a7a8a;transition:background .1s,color .1s;-webkit-user-select:none;-moz-user-select:none;user-select:none}.layout-select-item:hover{background:#ffffff08;color:#a0c0d0}.layout-select-item.active{color:#f90;background:#ff99000f}.layout-select-item-icon{font-size:14px;line-height:1;flex-shrink:0}.layout-select-item-check{margin-left:auto;font-size:10px;color:#f90}.topbar-force-refresh-label{display:flex;align-items:center;gap:5px;font-size:12px;color:#3a5a70;cursor:pointer;white-space:nowrap}.topbar-force-refresh-label input[type=checkbox]{accent-color:#ff9900;cursor:pointer}.topbar-warn-count{color:#c80}.svc-select-wrap{position:relative;flex-shrink:0}.svc-select-trigger{display:flex;align-items:center;gap:8px;height:32px;padding:0 10px 0 12px;background:#0c1820;border:1px solid #1a2a38;color:#4a7a90;font:inherit;font-size:12px;font-weight:600;letter-spacing:.06em;cursor:pointer;transition:border-color .15s,color .15s,background .15s;white-space:nowrap;min-width:148px;max-width:220px}.svc-select-trigger:hover,.svc-select-trigger.open{border-color:#f90;color:#f90;background:#0f1e28}.svc-select-trigger-dots{display:flex;align-items:center;gap:3px;flex-shrink:0}.svc-select-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.svc-select-label{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis}.svc-select-caret{font-size:8px;opacity:.55;flex-shrink:0;margin-left:2px}.svc-select-panel{position:absolute;top:calc(100% + 5px);right:0;z-index:300;width:270px;background:#070d14;border:1px solid #1a2a38;box-shadow:0 12px 40px #000000b3,0 0 0 1px #ff990012,inset 0 1px #ffffff08;display:flex;flex-direction:column}.svc-select-actions{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid #0f1e2a}.svc-select-action-btn{height:22px;padding:0 10px;background:transparent;border:1px solid #1a2a38;color:#f90;font:inherit;font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;cursor:pointer;transition:background .12s,border-color .12s}.svc-select-action-btn:hover{background:#ff99001a;border-color:#ff990073}.svc-select-count{margin-left:auto;font-size:10px;color:#2a4a5a;letter-spacing:.1em;white-space:nowrap}.svc-select-list{overflow-y:auto;max-height:340px;padding:4px 0 8px;scrollbar-width:thin;scrollbar-color:#1a2a38 transparent}.svc-select-list::-webkit-scrollbar{width:4px}.svc-select-list::-webkit-scrollbar-track{background:transparent}.svc-select-list::-webkit-scrollbar-thumb{background:#1a2a38;border-radius:2px}.svc-select-group{padding:8px 0 2px}.svc-select-group+.svc-select-group{border-top:1px solid #0a1520}.svc-select-group-label{display:flex;align-items:center;gap:6px;padding:0 12px 5px;font-size:9px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:#2a4a5a}.svc-select-group-label:after{content:"";flex:1;height:1px;background:linear-gradient(90deg,#0f1e2a,transparent)}.svc-select-item{display:flex;align-items:center;gap:9px;padding:5px 12px 5px 14px;cursor:pointer;font-size:12px;color:#5a7a8a;letter-spacing:.03em;transition:background .1s,color .1s;-webkit-user-select:none;-moz-user-select:none;user-select:none}.svc-select-item:hover{background:#ffffff08;color:#a0c0d0}.svc-select-item.checked{color:#c8d8e8}.svc-select-item.checked:hover{background:#ff99000f}.svc-select-item-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;opacity:.5;transition:opacity .1s}.svc-select-item.checked .svc-select-item-dot{opacity:1}.svc-select-checkbox{display:none}.svc-select-item-check{width:14px;height:14px;flex-shrink:0;border:1px solid #1a3040;background:#0a1520;border-radius:2px;display:flex;align-items:center;justify-content:center;transition:background .12s,border-color .12s}.svc-select-item.checked .svc-select-item-check{background:#ff990026;border-color:#f90}.svc-select-item-checkmark{display:none;width:8px;height:8px}.svc-select-item.checked .svc-select-item-checkmark{display:block}.sidebar-search-note{font-size:11px;color:#3a5a6a;margin-bottom:4px;letter-spacing:.05em}.error-boundary-shell{height:100vh;display:flex;align-items:center;justify-content:center;background:#05080d;color:#d6e3ef}.error-boundary-inner{text-align:center;max-width:400px;padding:32px;border:1px solid #1a2a38;background:#070d14}.error-boundary-title{font-size:18px;font-weight:600;color:#e8c888;margin-bottom:12px;letter-spacing:.1em;text-transform:uppercase}.error-boundary-message{font-size:14px;color:#5a8a9a;margin-bottom:20px;word-break:break-word}.error-boundary-reset{font:inherit;font-size:13px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;padding:8px 20px;background:linear-gradient(135deg,#f90,#f60);color:#060a0f;border:none;cursor:pointer;clip-path:polygon(6px 0%,100% 0%,calc(100% - 6px) 100%,0% 100%)}.minimap-shell{background:#05080de0;border:1px solid #0f1e2a;padding:4px 6px 6px;display:flex;flex-direction:column;gap:2px}.minimap-label{font-size:9px;color:#2a4a5a;letter-spacing:.18em;text-transform:uppercase}.minimap-svg{display:block;cursor:crosshair}.focus-mode-bar{position:absolute;top:8px;left:50%;transform:translate(-50%);z-index:10;display:flex;align-items:center;gap:8px;background:#05080deb;border:1px solid #1a2a38;padding:5px 12px;white-space:nowrap}.focus-mode-label{font-size:11px;color:#3a6a80;letter-spacing:.1em;text-transform:uppercase}.focus-mode-controls{display:flex;align-items:center;gap:4px}.focus-depth-btn{font:inherit;font-size:11px;letter-spacing:.08em;background:transparent;border:1px solid #1a2a38;color:#3a6a80;padding:3px 8px;cursor:pointer;transition:all .12s}.focus-depth-btn.active,.focus-depth-btn:hover{border-color:#f90;color:#f90}.focus-toggle-btn{font:inherit;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;background:transparent;border:1px solid #2a4a5a;color:#4a8a9a;padding:3px 10px;cursor:pointer;transition:all .12s}.focus-toggle-btn.active{background:#ff99001f;border-color:#f90;color:#f90}.focus-toggle-btn:hover{border-color:#f90;color:#f90}.graph-cluster-count{fill:#e8c888;font-size:17px;font-weight:700;dominant-baseline:middle;text-anchor:middle}.graph-cluster-label{fill:#5a8a9a;font-size:10px;letter-spacing:.12em;text-transform:uppercase;dominant-baseline:middle;text-anchor:middle}.sidebar-pill-row{display:flex;align-items:center;gap:2px}.sidebar-filter-pill-inline{flex:1 1 auto;width:auto}.sidebar-cluster-btn{font:inherit;font-size:13px;background:transparent;border:1px solid #1a2a38;color:#3a5a70;padding:2px 5px;cursor:pointer;transition:all .12s;flex-shrink:0;line-height:1}.sidebar-cluster-btn:hover,.sidebar-cluster-btn.active{border-color:#f90;color:#f90}.sidebar-isolated-toggle{width:100%;display:flex;justify-content:space-between;align-items:center;font:inherit;font-size:12px;letter-spacing:.08em;background:transparent;border:1px solid #1a2a38;color:#3a6a80;padding:5px 10px;cursor:pointer;transition:all .12s}.sidebar-isolated-toggle.active{border-color:#2a5a6a;color:#5a9aaa;background:#2a5a6a1a}.sidebar-isolated-toggle:hover{border-color:#f90;color:#f90}.graph-annotation.lane-trigger rect{fill:#ff99000a;stroke:#ff99002e}.graph-annotation.lane-trigger text{fill:#ff990073}.graph-annotation.lane-queue rect{fill:#ff4f8b0a;stroke:#ff4f8b2e}.graph-annotation.lane-queue text{fill:#ff4f8b73}.graph-annotation.lane-processor rect{fill:#00e7ff0a;stroke:#00e7ff2e}.graph-annotation.lane-processor text{fill:#00e7ff73}.graph-annotation.lane-storage rect{fill:#7b2d8b0d;stroke:#7b2d8b33}.graph-annotation.lane-storage text{fill:#7b2d8b99}.graph-annotation.lane-unknown rect{fill:#6f859608;stroke:#6f85961f}.graph-annotation.lane-unknown text{fill:#6f859659}.graph-toolbar{position:absolute;top:10px;right:12px;z-index:10;display:flex;gap:6px}.graph-toolbar-btn{font:inherit;font-size:10px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;background:#05080de0;border:1px solid #1a2a38;color:#3a6a80;padding:5px 12px;cursor:pointer;transition:all .12s}.graph-toolbar-btn:hover,.graph-toolbar-btn.active{border-color:#f90;color:#f90;background:#ff990014}.summary-panel{position:absolute;top:48px;right:12px;z-index:15;width:340px;background:#05080df5;border:1px solid #1a2a38;padding:14px 16px 16px;box-shadow:0 8px 32px #0009}.summary-panel-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.summary-panel-title{font-size:10px;font-weight:700;letter-spacing:.18em;color:#c8a860;text-transform:uppercase}.summary-panel-close{font:inherit;font-size:12px;background:transparent;border:none;color:#3a6a80;cursor:pointer;padding:2px 6px}.summary-panel-close:hover{color:#f90}.summary-panel-text{font-size:12px;color:#7aacbe;line-height:1.65;margin:0 0 12px}.summary-patterns{border-top:1px solid #0f1e2a;padding-top:10px}.summary-patterns-title{font-size:10px;letter-spacing:.15em;color:#2a4a5a;text-transform:uppercase;margin-bottom:8px}.summary-pattern-row{display:flex;flex-direction:column;gap:2px;padding:6px 0;border-bottom:1px solid #0a1420}.summary-pattern-name{font-size:11px;font-weight:600;color:#f90;letter-spacing:.05em}.summary-pattern-desc{font-size:10px;color:#4a7a8a}.layout-loading-overlay{position:absolute;top:0;right:0;bottom:0;left:0;z-index:20;background:#05080db8;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;color:#4a8a9a;font-size:12px;letter-spacing:.18em;text-transform:uppercase;pointer-events:none}.layout-loading-spinner{width:28px;height:28px;border:2px solid #1a2a38;border-top-color:#f90;border-radius:50%;animation:layout-spin .75s linear infinite}@keyframes layout-spin{to{transform:rotate(360deg)}}.focus-mode-bar .focus-toggle-btn.path-active{background:#00e7ff1a;border-color:#00e7ff;color:#00e7ff}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:IBM Plex Mono,ui-monospace,SFMono-Regular,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.visible{visibility:visible}.static{position:static}.flex{display:flex}.hidden{display:none}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}*{box-sizing:border-box}html,body,#root{width:100%;height:100%;margin:0;font-family:IBM Plex Mono,ui-monospace,SFMono-Regular,monospace;background:#05080d;color:#d6e3ef}button,input,select{font:inherit}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:#04080cf5}::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#ff99006b,#00e7ff57);border-radius:999px}
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>CloudWire</title>
7
+ <script type="module" crossorigin src="./assets/index-CByMF4j6.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/index-lik1Sxh5.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,186 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloudwire
3
+ Version: 0.1.0
4
+ Summary: Scan and visualize your AWS infrastructure as an interactive graph
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/hisingh_gwre/cloudwire
7
+ Project-URL: Issues, https://github.com/hisingh_gwre/cloudwire/issues
8
+ Keywords: aws,cloud,visualization,graph,infrastructure
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Console
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Internet :: WWW/HTTP
20
+ Classifier: Topic :: System :: Systems Administration
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: fastapi>=0.115
24
+ Requires-Dist: uvicorn[standard]>=0.34
25
+ Requires-Dist: boto3>=1.37
26
+ Requires-Dist: botocore>=1.37
27
+ Requires-Dist: networkx>=3.4
28
+ Requires-Dist: pydantic>=2.11
29
+ Requires-Dist: click>=8.1
30
+
31
+ # cloudwire
32
+
33
+ Scan your AWS account and visualize resource dependencies as an interactive graph — directly in your browser, running entirely on your local machine.
34
+
35
+ No data leaves your system. AWS credentials never leave your terminal. The graph is built locally using your existing credential chain (`~/.aws/credentials`, `aws sso login`, `saml2aws`, `aws-vault` — all work out of the box).
36
+
37
+ ---
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ pip install cloudwire
43
+ cloudwire
44
+ ```
45
+
46
+ That's it. The browser opens automatically at `http://localhost:8080`.
47
+
48
+ > **Requirements:** Python 3.9+ and valid AWS credentials configured locally.
49
+
50
+ ---
51
+
52
+ ## What it looks like
53
+
54
+ - Dark hacker-aesthetic graph canvas
55
+ - Nodes represent AWS resources — Lambda functions, SQS queues, API Gateways, RDS instances, S3 buckets, and more
56
+ - Edges represent relationships and data flow between resources
57
+ - Click any node to inspect its attributes and connected resources
58
+ - Search, filter by service, highlight upstream/downstream blast radius
59
+
60
+ ---
61
+
62
+ ## Supported services
63
+
64
+ | Service | Scanner |
65
+ |---------|---------|
66
+ | API Gateway | Dedicated |
67
+ | Lambda | Dedicated (with state) |
68
+ | SQS | Dedicated |
69
+ | SNS | Dedicated |
70
+ | EventBridge | Dedicated |
71
+ | DynamoDB | Dedicated (with state) |
72
+ | EC2 | Dedicated (with state) |
73
+ | ECS | Dedicated |
74
+ | S3 | Dedicated |
75
+ | RDS | Dedicated (with state) |
76
+ | Step Functions | Dedicated |
77
+ | Kinesis | Dedicated |
78
+ | IAM | Dedicated |
79
+ | Cognito | Dedicated |
80
+ | CloudFront | Dedicated (with state) |
81
+ | ElastiCache | Dedicated (with state) |
82
+ | Glue | Dedicated |
83
+ | AppSync | Dedicated |
84
+ | Everything else | Generic (tagged resources only) |
85
+
86
+ ---
87
+
88
+ ## Project structure
89
+
90
+ ```
91
+ cloudwire/ # Python package (the distributable unit)
92
+ ├── __init__.py # Package version
93
+ ├── cli.py # `cloudwire` CLI entry point (click)
94
+ ├── static/ # Built React app (populated by `make build`)
95
+ │ ├── index.html
96
+ │ └── assets/
97
+ └── app/ # FastAPI backend
98
+ ├── main.py # App factory, API routes (/api/*), static serving
99
+ ├── models.py # Pydantic request/response models
100
+ ├── scanner.py # boto3 AWS scanner — one function per service
101
+ ├── scan_jobs.py # Async job store with progress tracking
102
+ └── graph_store.py # networkx graph with thread-safe mutations
103
+
104
+ frontend/ # React + Vite source (compiled into cloudwire/static/)
105
+ ├── src/
106
+ │ ├── pages/CloudWirePage.jsx # Main page — orchestrates all state
107
+ │ ├── components/
108
+ │ │ ├── graph/ # GraphCanvas, GraphNode, GraphEdge, Minimap, Legend
109
+ │ │ └── layout/ # TopBar, ServiceSidebar, InspectorPanel
110
+ │ ├── hooks/
111
+ │ │ ├── useScanPolling.js # Scan lifecycle, polling, graph data state
112
+ │ │ └── useGraphViewport.js # Pan/zoom viewport state
113
+ │ ├── lib/
114
+ │ │ ├── graphTransforms.js # Layout algorithms (circular, flow, swimlane)
115
+ │ │ ├── serviceVisuals.jsx # Service icon + color map
116
+ │ │ └── awsRegions.js # AWS region list
117
+ │ └── styles/graph.css # All UI styles
118
+ ├── vite.config.js # base: "./", outDir: ../cloudwire/static, dev proxy
119
+ └── package.json
120
+
121
+ .github/workflows/publish.yml # CI: build + publish to PyPI on version tag push
122
+ pyproject.toml # Package metadata, dependencies, entry point
123
+ Makefile # make build / make dev / make clean
124
+ .python-version # Pins Python 3.11 for consistent builds
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Contributing
130
+
131
+ ### Prerequisites
132
+
133
+ - Python 3.9+ (3.11 recommended)
134
+ - Node.js 18+
135
+ - AWS credentials configured (any method)
136
+
137
+ ### Set up the dev environment
138
+
139
+ ```bash
140
+ git clone https://github.com/hisingh_gwre/cloudwire
141
+ cd cloudwire
142
+
143
+ # Python
144
+ python3 -m venv .venv
145
+ source .venv/bin/activate
146
+ pip install -e .
147
+
148
+ # Frontend
149
+ cd frontend && npm install
150
+ ```
151
+
152
+ ### Run in development mode
153
+
154
+ ```bash
155
+ make dev
156
+ ```
157
+
158
+ This starts the FastAPI backend on `:8000` (with `--reload`) and the Vite dev server on `:5173` concurrently. The Vite dev server proxies all `/api/*` requests to the backend — no CORS config needed.
159
+
160
+ ### Making changes
161
+
162
+ | Area | Where to edit |
163
+ |------|--------------|
164
+ | Add a new AWS service scanner | `cloudwire/app/scanner.py` → add a `_scan_<service>` method and register it in `self.service_scanners` |
165
+ | Change graph layout | `frontend/src/lib/graphTransforms.js` |
166
+ | Add a new UI component | `frontend/src/components/` |
167
+ | Change API routes | `cloudwire/app/main.py` — all routes are under the `/api` prefix |
168
+ | Change CLI options | `cloudwire/cli.py` |
169
+
170
+ ### Before opening a PR
171
+
172
+ - Run a scan against a real (or mocked) AWS account and confirm the graph renders
173
+ - Make sure `make build` completes without errors
174
+ - Keep PRs focused — one feature or fix per PR
175
+
176
+ ### Code style
177
+
178
+ - Python: standard library imports first, then third-party, then local. No formatter enforced yet.
179
+ - JavaScript: no linter enforced yet. Match the style of the surrounding file.
180
+
181
+ ---
182
+
183
+ ## Links
184
+
185
+ - [Usage & setup guide](docs/USAGE.md)
186
+ - [Release guide for maintainers](docs/RELEASING.md)
@@ -0,0 +1,16 @@
1
+ cloudwire/__init__.py,sha256=apOVKn2E4dUxBuPEBOyPEtx-Qo-VVEv1J1p0Mhr-6i8,87
2
+ cloudwire/cli.py,sha256=XeYvcL367LPgqLg46RnFT1wBLyDRd9zbcJl5hiGzQNU,3233
3
+ cloudwire/app/__init__.py,sha256=wNbizpJ_aRNo8vwKB66gymXbKAGFIKHGMosStf9Q15g,33
4
+ cloudwire/app/graph_store.py,sha256=NK69-qYuJ8PKMJ3IKEvakJ5d6TeKwOHwonr8ZcM_DEw,3382
5
+ cloudwire/app/main.py,sha256=0b-avcw10d0renEVz2UXsnD-UyDkjdRTm3GE1IuxDiw,15533
6
+ cloudwire/app/models.py,sha256=PbFnqn_MNVxGZh2hDPIIHiqlF9AjAAdFixYfUzw9Arg,2211
7
+ cloudwire/app/scan_jobs.py,sha256=YYemUXi5BZvR8sBfuEAkjIjfOvHAs-FjourSYTA1blg,13282
8
+ cloudwire/app/scanner.py,sha256=SEWMacilf0C_mHPwEXCNKS9pSgdX3O62TZTxa-EPv8A,51634
9
+ cloudwire/static/index.html,sha256=Zs3sPTNTMni6ex9lrGhnvaQwN30ZmaDf0apCMX-2rTI,396
10
+ cloudwire/static/assets/index-CByMF4j6.js,sha256=t7kxbGuF8e_2M-rxSPzojpEiWU9sGazuUP-1g4EW_aw,204498
11
+ cloudwire/static/assets/index-lik1Sxh5.css,sha256=A7n6DGiw2AVOBGmYpgOspBbhNnOEaAOcXLJGYCapuQk,28572
12
+ cloudwire-0.1.0.dist-info/METADATA,sha256=mlWX4nJjM-o1D6aMTjLPDbBqTY8J5sK8pC_cmWAED4Q,6514
13
+ cloudwire-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
14
+ cloudwire-0.1.0.dist-info/entry_points.txt,sha256=pVoiRkRueQLNFlIeImNIWKfhVSo3j9TEn0y2UWlsbN8,49
15
+ cloudwire-0.1.0.dist-info/top_level.txt,sha256=aDxE_-CdonPoAamgrbCUhQ3sQ3tfI_VAJJN1dBsA4QU,10
16
+ cloudwire-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cloudwire = cloudwire.cli:main
@@ -0,0 +1 @@
1
+ cloudwire