aws-security-mcp 0.3.0 → 0.4.0
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.
- package/README.md +118 -42
- package/dashboard/dist/assets/index-CQyERuqT.css +2 -0
- package/dashboard/dist/data.json +167 -758
- package/dashboard/dist/index.html +2 -2
- package/dist/bin/aws-security-mcp.js +2812 -3517
- package/dist/bin/aws-security-mcp.js.map +1 -1
- package/dist/src/index.d.ts +38 -1
- package/dist/src/index.js +2803 -3496
- package/dist/src/index.js.map +1 -1
- package/package.json +4 -4
- package/templates/stackset-audit-role.json +55 -0
- package/templates/stackset-audit-role.yaml +44 -0
- package/dashboard/dist/assets/index-DCplBiuM.css +0 -2
- /package/dashboard/dist/assets/{index-jFq0Af8S.js → index-BYE-UdjR.js} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# aws-security-mcp
|
|
2
2
|
|
|
3
|
-
MCP server for automated AWS security scanning —
|
|
3
|
+
MCP server for automated AWS security scanning — 14 modules, risk scoring, zero write operations.
|
|
4
4
|
|
|
5
5
|
<!-- badges -->
|
|
6
6
|

|
|
@@ -9,13 +9,15 @@ MCP server for automated AWS security scanning — 7 modules, risk scoring, zero
|
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
- **
|
|
12
|
+
- **14 Security Scan Modules** — 10 unique scanners + 4 aggregation scanners (Security Hub, GuardDuty, Inspector, Trusted Advisor)
|
|
13
13
|
- **Risk Scoring** — every finding scored 0-10 with severity (CRITICAL/HIGH/MEDIUM/LOW) and priority (P0-P3)
|
|
14
14
|
- **100% Read-Only** — uses only Describe/Get/List API calls; never modifies your AWS resources
|
|
15
|
-
- **Parallel Execution** — all
|
|
16
|
-
- **
|
|
15
|
+
- **Parallel Execution** — all modules run concurrently via `Promise.allSettled`
|
|
16
|
+
- **Report Generation** — Markdown, professional HTML, and MLPS Level 3 compliance reports
|
|
17
|
+
- **React Dashboard** — local or S3-hosted dashboard with 30-day trend charts
|
|
17
18
|
- **MCP Resources** — embedded security rules and risk scoring model documentation
|
|
18
19
|
- **MCP Prompts** — pre-built workflows for full scans and finding analysis
|
|
20
|
+
- **China Region Support** — full support for aws-cn partition
|
|
19
21
|
|
|
20
22
|
## Quick Start
|
|
21
23
|
|
|
@@ -105,16 +107,30 @@ Or use the built-in `security-scan` prompt for a guided workflow.
|
|
|
105
107
|
|
|
106
108
|
| Tool | Description |
|
|
107
109
|
|------|-------------|
|
|
108
|
-
| `scan_all` | Run all
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
110
|
+
| `scan_all` | Run all 14 security scanners in parallel |
|
|
111
|
+
| `detect_services` | Detect enabled AWS security services and assess maturity |
|
|
112
|
+
| `scan_secret_exposure` | Check Lambda env vars and EC2 userData for exposed secrets |
|
|
113
|
+
| `scan_ssl_certificate` | Check ACM certificates for expiry and failed status |
|
|
114
|
+
| `scan_dns_dangling` | Detect dangling DNS records (subdomain takeover risk) |
|
|
115
|
+
| `scan_network_reachability` | Analyze true network reachability (SG + NACL rules) |
|
|
116
|
+
| `scan_iam_privilege_escalation` | Detect IAM privilege escalation paths |
|
|
117
|
+
| `scan_public_access_verify` | Verify actual public accessibility of resources |
|
|
118
|
+
| `scan_tag_compliance` | Check resources for required tags |
|
|
119
|
+
| `scan_idle_resources` | Find unused/idle resources |
|
|
120
|
+
| `scan_disaster_recovery` | Assess disaster recovery readiness |
|
|
121
|
+
| `scan_security_hub_findings` | Aggregate findings from AWS Security Hub |
|
|
122
|
+
| `scan_guardduty_findings` | Aggregate findings from Amazon GuardDuty |
|
|
123
|
+
| `scan_inspector_findings` | Aggregate findings from Amazon Inspector |
|
|
124
|
+
| `scan_trusted_advisor_findings` | Aggregate findings from AWS Trusted Advisor |
|
|
125
|
+
| `scan_group` | Run a predefined group of scanners for a specific scenario |
|
|
126
|
+
| `list_groups` | List available scan groups |
|
|
117
127
|
| `list_modules` | List available scan modules with descriptions |
|
|
128
|
+
| `generate_report` | Generate a Markdown report from scan results |
|
|
129
|
+
| `generate_html_report` | Generate a professional HTML report |
|
|
130
|
+
| `generate_mlps3_report` | Generate a MLPS Level 3 compliance report |
|
|
131
|
+
| `generate_mlps3_html_report` | Generate a MLPS Level 3 HTML compliance report |
|
|
132
|
+
| `generate_maturity_report` | Generate a security maturity assessment |
|
|
133
|
+
| `save_results` | Save scan results for the dashboard |
|
|
118
134
|
|
|
119
135
|
All tools accept an optional `region` parameter (defaults to the server's configured region).
|
|
120
136
|
|
|
@@ -130,38 +146,64 @@ Attach this policy to the IAM user or role running the scanner. All actions are
|
|
|
130
146
|
"Sid": "SecurityScannerReadOnly",
|
|
131
147
|
"Effect": "Allow",
|
|
132
148
|
"Action": [
|
|
133
|
-
"
|
|
149
|
+
"acm:DescribeCertificate",
|
|
150
|
+
"acm:ListCertificates",
|
|
151
|
+
|
|
152
|
+
"config:DescribeConfigurationRecorders",
|
|
153
|
+
|
|
154
|
+
"ec2:DescribeAddresses",
|
|
134
155
|
"ec2:DescribeInstances",
|
|
135
|
-
"ec2:
|
|
156
|
+
"ec2:DescribeNetworkAcls",
|
|
157
|
+
"ec2:DescribeSecurityGroups",
|
|
136
158
|
"ec2:DescribeSnapshots",
|
|
137
159
|
"ec2:DescribeSnapshotAttribute",
|
|
160
|
+
"ec2:DescribeVolumes",
|
|
138
161
|
"ec2:GetEbsEncryptionByDefault",
|
|
139
|
-
"ec2:DescribeVpcs",
|
|
140
|
-
"ec2:DescribeFlowLogs",
|
|
141
162
|
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"s3:GetBucketPolicyStatus",
|
|
147
|
-
"s3:GetEncryptionConfiguration",
|
|
148
|
-
"s3:GetBucketVersioning",
|
|
163
|
+
"guardduty:GetDetector",
|
|
164
|
+
"guardduty:ListDetectors",
|
|
165
|
+
"guardduty:ListFindings",
|
|
166
|
+
"guardduty:GetFindings",
|
|
149
167
|
|
|
150
168
|
"iam:GetAccountSummary",
|
|
151
169
|
"iam:ListUsers",
|
|
170
|
+
"iam:ListRoles",
|
|
152
171
|
"iam:ListAccessKeys",
|
|
153
172
|
"iam:GetAccessKeyLastUsed",
|
|
154
173
|
"iam:ListAttachedUserPolicies",
|
|
155
|
-
"iam:
|
|
156
|
-
"iam:
|
|
174
|
+
"iam:ListAttachedRolePolicies",
|
|
175
|
+
"iam:ListUserPolicies",
|
|
176
|
+
"iam:ListRolePolicies",
|
|
177
|
+
"iam:GetUserPolicy",
|
|
178
|
+
"iam:GetRolePolicy",
|
|
179
|
+
"iam:GetPolicy",
|
|
180
|
+
"iam:GetPolicyVersion",
|
|
181
|
+
|
|
182
|
+
"inspector2:ListFindings",
|
|
183
|
+
|
|
184
|
+
"lambda:ListFunctions",
|
|
185
|
+
"lambda:GetFunction",
|
|
157
186
|
|
|
158
|
-
"
|
|
159
|
-
"cloudtrail:GetTrailStatus",
|
|
160
|
-
"cloudtrail:GetEventSelectors",
|
|
187
|
+
"macie2:GetMacieSession",
|
|
161
188
|
|
|
162
189
|
"rds:DescribeDBInstances",
|
|
163
190
|
|
|
164
|
-
"
|
|
191
|
+
"route53:ListHostedZones",
|
|
192
|
+
"route53:ListResourceRecordSets",
|
|
193
|
+
|
|
194
|
+
"s3:GetBucketPublicAccessBlock",
|
|
195
|
+
"s3:GetBucketVersioning",
|
|
196
|
+
"s3:GetBucketReplication",
|
|
197
|
+
"s3:GetBucketTagging",
|
|
198
|
+
"s3:ListAllMyBuckets",
|
|
199
|
+
|
|
200
|
+
"securityhub:DescribeHub",
|
|
201
|
+
"securityhub:GetFindings",
|
|
202
|
+
|
|
203
|
+
"sts:GetCallerIdentity",
|
|
204
|
+
|
|
205
|
+
"support:DescribeTrustedAdvisorChecks",
|
|
206
|
+
"support:DescribeTrustedAdvisorCheckResult"
|
|
165
207
|
],
|
|
166
208
|
"Resource": "*"
|
|
167
209
|
}
|
|
@@ -171,15 +213,29 @@ Attach this policy to the IAM user or role running the scanner. All actions are
|
|
|
171
213
|
|
|
172
214
|
## Scan Modules
|
|
173
215
|
|
|
216
|
+
### Unique Scanners (10)
|
|
217
|
+
|
|
174
218
|
| Module | What It Checks | Risk Score Range |
|
|
175
219
|
|--------|---------------|-----------------|
|
|
176
|
-
| **
|
|
177
|
-
| **
|
|
178
|
-
| **
|
|
179
|
-
| **
|
|
180
|
-
| **
|
|
181
|
-
| **
|
|
182
|
-
| **
|
|
220
|
+
| **Service Detection** | Enabled security services (Security Hub, GuardDuty, Inspector, Config, Macie) and maturity level | 5.0 - 7.5 |
|
|
221
|
+
| **Secret Exposure** | Lambda env vars and EC2 userData for exposed secrets (AWS keys, private keys, passwords) | 7.0 - 9.5 |
|
|
222
|
+
| **SSL Certificate** | ACM certificate expiry, failed status, upcoming renewals | 5.5 - 9.0 |
|
|
223
|
+
| **Dangling DNS** | Route53 CNAME records pointing to non-existent resources (subdomain takeover) | 7.0 - 8.5 |
|
|
224
|
+
| **Network Reachability** | True network reachability combining Security Group + NACL rules for public EC2 instances | 5.5 - 9.5 |
|
|
225
|
+
| **IAM Privilege Escalation** | Privilege escalation paths via policy manipulation, role creation, or service abuse | 7.0 - 9.5 |
|
|
226
|
+
| **Public Access Verify** | Actual public accessibility of resources marked as public (S3 HTTP, RDS DNS) | 7.0 - 9.0 |
|
|
227
|
+
| **Tag Compliance** | Required tags (Environment, Project, Owner) on EC2, RDS, S3 resources | 3.0 - 5.0 |
|
|
228
|
+
| **Idle Resources** | Unused resources (unattached EBS, unused EIPs, stopped instances, unused SGs) | 3.0 - 5.0 |
|
|
229
|
+
| **Disaster Recovery** | RDS Multi-AZ & backups, EBS snapshot coverage, S3 versioning & replication | 4.0 - 7.5 |
|
|
230
|
+
|
|
231
|
+
### Aggregation Scanners (4)
|
|
232
|
+
|
|
233
|
+
| Module | Source Service | Risk Score Range |
|
|
234
|
+
|--------|---------------|-----------------|
|
|
235
|
+
| **Security Hub Findings** | AWS Security Hub (FSBP, CIS, PCI DSS) | 3.0 - 9.5 |
|
|
236
|
+
| **GuardDuty Findings** | Amazon GuardDuty threat detection | 3.0 - 9.5 |
|
|
237
|
+
| **Inspector Findings** | Amazon Inspector vulnerability scanning | 3.0 - 9.5 |
|
|
238
|
+
| **Trusted Advisor Findings** | AWS Trusted Advisor security checks (requires Business/Enterprise Support) | 5.5 - 8.0 |
|
|
183
239
|
|
|
184
240
|
### Risk Scoring
|
|
185
241
|
|
|
@@ -190,6 +246,26 @@ Attach this policy to the IAM user or role running the scanner. All actions are
|
|
|
190
246
|
| 4.0 - 6.9 | MEDIUM | P2 |
|
|
191
247
|
| 0.0 - 3.9 | LOW | P3 |
|
|
192
248
|
|
|
249
|
+
## Scan Groups
|
|
250
|
+
|
|
251
|
+
Pre-defined scanner groupings for common scenarios:
|
|
252
|
+
|
|
253
|
+
| Group | Description | Modules |
|
|
254
|
+
|-------|-------------|---------|
|
|
255
|
+
| `mlps3_precheck` | GB/T 22239-2019 等保三级预检 | 12 modules |
|
|
256
|
+
| `hw_defense` | 护网蓝队加固 | 7 modules |
|
|
257
|
+
| `exposure` | 公网暴露面评估 | 5 modules |
|
|
258
|
+
| `pre_launch` | 生产上线前检查 | ALL modules |
|
|
259
|
+
| `aggregation` | 安全服务聚合 | 4 modules |
|
|
260
|
+
| `new_account_baseline` | 新账户基线检查 | 5 modules |
|
|
261
|
+
| `disaster_recovery` | 灾备评估 | 2 modules |
|
|
262
|
+
| `least_privilege` | 最小权限审计 | 2 modules |
|
|
263
|
+
| `idle_resources` | 闲置资源清理 | 2 modules |
|
|
264
|
+
| `tag_compliance` | 资源标签合规 | 1 module |
|
|
265
|
+
| `public_access_verify` | 公网可达性验证 | 1 module |
|
|
266
|
+
|
|
267
|
+
Use `list_groups` to see all available groups with their module lists.
|
|
268
|
+
|
|
193
269
|
## Output Format
|
|
194
270
|
|
|
195
271
|
### Scan Results (JSON)
|
|
@@ -198,7 +274,7 @@ Each scan tool returns structured JSON:
|
|
|
198
274
|
|
|
199
275
|
```json
|
|
200
276
|
{
|
|
201
|
-
"module": "
|
|
277
|
+
"module": "network_reachability",
|
|
202
278
|
"status": "success",
|
|
203
279
|
"resourcesScanned": 12,
|
|
204
280
|
"findingsCount": 3,
|
|
@@ -206,10 +282,10 @@ Each scan tool returns structured JSON:
|
|
|
206
282
|
"findings": [
|
|
207
283
|
{
|
|
208
284
|
"severity": "CRITICAL",
|
|
209
|
-
"title": "
|
|
210
|
-
"resourceType": "AWS::EC2::
|
|
211
|
-
"resourceId": "
|
|
212
|
-
"resourceArn": "arn:aws:ec2:ap-northeast-1:123456789012:
|
|
285
|
+
"title": "EC2 instance i-abc123 has SSH (22) reachable from 0.0.0.0/0",
|
|
286
|
+
"resourceType": "AWS::EC2::Instance",
|
|
287
|
+
"resourceId": "i-abc123",
|
|
288
|
+
"resourceArn": "arn:aws:ec2:ap-northeast-1:123456789012:instance/i-abc123",
|
|
213
289
|
"region": "ap-northeast-1",
|
|
214
290
|
"description": "...",
|
|
215
291
|
"impact": "...",
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-tight:1.25;--radius-lg:.5rem;--ease-in:cubic-bezier(.4, 0, 1, 1);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}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;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.right-0{right:calc(var(--spacing) * 0)}.left-0{left:calc(var(--spacing) * 0)}.z-10{z-index:10}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-16{margin-top:calc(var(--spacing) * 16)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.table{display:table}.h-\[300px\]{height:300px}.h-screen{height:100vh}.min-h-screen{min-height:100vh}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.flex-1{flex:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-blue-500\/30{border-color:#3080ff4d}@supports (color:color-mix(in lab, red, red)){.border-blue-500\/30{border-color:color-mix(in oklab, var(--color-blue-500) 30%, transparent)}}.border-current{border-color:currentColor}.border-green-500\/30{border-color:#00c7584d}@supports (color:color-mix(in lab, red, red)){.border-green-500\/30{border-color:color-mix(in oklab, var(--color-green-500) 30%, transparent)}}.border-orange-500\/30{border-color:#fe6e004d}@supports (color:color-mix(in lab, red, red)){.border-orange-500\/30{border-color:color-mix(in oklab, var(--color-orange-500) 30%, transparent)}}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.border-red-500\/30{border-color:color-mix(in oklab, var(--color-red-500) 30%, transparent)}}.border-slate-700{border-color:var(--color-slate-700)}.border-yellow-500\/30{border-color:#edb2004d}@supports (color:color-mix(in lab, red, red)){.border-yellow-500\/30{border-color:color-mix(in oklab, var(--color-yellow-500) 30%, transparent)}}.bg-blue-500\/20{background-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\/20{background-color:color-mix(in oklab, var(--color-blue-500) 20%, transparent)}}.bg-green-500\/20{background-color:#00c75833}@supports (color:color-mix(in lab, red, red)){.bg-green-500\/20{background-color:color-mix(in oklab, var(--color-green-500) 20%, transparent)}}.bg-orange-500\/20{background-color:#fe6e0033}@supports (color:color-mix(in lab, red, red)){.bg-orange-500\/20{background-color:color-mix(in oklab, var(--color-orange-500) 20%, transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/20{background-color:color-mix(in oklab, var(--color-red-500) 20%, transparent)}}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-800\/30{background-color:#1d293d4d}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/30{background-color:color-mix(in oklab, var(--color-slate-800) 30%, transparent)}}.bg-slate-800\/50{background-color:#1d293d80}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/50{background-color:color-mix(in oklab, var(--color-slate-800) 50%, transparent)}}.bg-slate-800\/80{background-color:#1d293dcc}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/80{background-color:color-mix(in oklab, var(--color-slate-800) 80%, transparent)}}.bg-slate-900{background-color:var(--color-slate-900)}.bg-yellow-500\/20{background-color:#edb20033}@supports (color:color-mix(in lab, red, red)){.bg-yellow-500\/20{background-color:color-mix(in oklab, var(--color-yellow-500) 20%, transparent)}}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-blue-400{color:var(--color-blue-400)}.text-green-400{color:var(--color-green-400)}.text-orange-400{color:var(--color-orange-400)}.text-red-400{color:var(--color-red-400)}.text-slate-50{color:var(--color-slate-50)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-yellow-400{color:var(--color-yellow-400)}.capitalize{text-transform:capitalize}.italic{font-style:italic}.blur{--tw-blur:blur(8px);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,)}.invert{--tw-invert:invert(100%);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,)}.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,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:border-slate-500:hover{border-color:var(--color-slate-500)}.hover\:bg-slate-700\/50:hover{background-color:#31415880}@supports (color:color-mix(in lab, red, red)){.hover\:bg-slate-700\/50:hover{background-color:color-mix(in oklab, var(--color-slate-700) 50%, transparent)}}.hover\:text-slate-200:hover{color:var(--color-slate-200)}}@media (width>=40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width>=48rem){.md\:col-span-2{grid-column:span 2/span 2}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width>=64rem){.lg\:mt-0{margin-top:calc(var(--spacing) * 0)}.lg\:ml-64{margin-left:calc(var(--spacing) * 64)}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}}body{color:#f8fafc;background-color:#0f172a;margin:0;font-family:Inter,system-ui,-apple-system,sans-serif}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#1e293b}::-webkit-scrollbar-thumb{background:#475569;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#64748b}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|