Initial Phoenix Sankofa Cloud setup

- Complete project structure with Next.js frontend
- GraphQL API backend with Apollo Server
- Portal application with NextAuth
- Crossplane Proxmox provider
- GitOps configurations
- CI/CD pipelines
- Testing infrastructure (Vitest, Jest, Go tests)
- Error handling and monitoring
- Security hardening
- UI component library
- Documentation
This commit is contained in:
defiQUG
2025-11-28 12:54:33 -08:00
commit 6f28146ac3
229 changed files with 43136 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# Architecture Diagrams
This directory contains comprehensive architecture diagrams for the Hybrid Cloud Control Plane system.
## Diagrams
### 1. System Overview (`system-overview.svg`)
High-level view of all system components and their relationships:
- Cloudflare Zero Trust Layer
- Custom Portal (Next.js)
- Kubernetes Control Plane
- Observability Stack
- Identity Management (Keycloak)
- GitOps (ArgoCD)
- Proxmox Edge Sites
### 2. Data Flow (`data-flow.svg`)
Detailed data flow diagrams showing:
- **Authentication Flow**: User → Cloudflare Access → Portal → Keycloak
- **VM Provisioning Flow**: User → Portal → Crossplane → ArgoCD → Proxmox Provider → Proxmox Site
- **Monitoring Flow**: Proxmox Node → pve-exporter → Prometheus → Grafana → Portal
- **Log Aggregation Flow**: Services → Promtail → Loki → Portal
- **GitOps Deployment Flow**: Developer → Git Repo → ArgoCD → Kubernetes → Crossplane → Infrastructure
### 3. Network Topology (`network-topology.svg`)
Network architecture showing:
- Internet connectivity
- Cloudflare Global Network (200+ edge locations)
- Control Plane site with all services
- Three Proxmox sites (US-East, EU-West, APAC)
- Cloudflare Tunnels connecting all sites
- Local network addressing (10.0.0.0/16, 10.1.0.0/16, etc.)
- Security features (Zero Trust, no public IPs, encrypted tunnels)
### 4. Deployment Diagram (`deployment-diagram.svg`)
Infrastructure layout showing:
- **Control Plane Cluster**: 3 master nodes, 3 worker nodes, shared storage
- **Proxmox Site 1**: 3 nodes with Ceph storage cluster (200TB)
- **Proxmox Site 2**: 3 nodes with ZFS storage pools (80TB)
- **Proxmox Site 3**: 2 nodes with local storage (40TB)
- **Network Infrastructure**: Load balancers, routers, DNS, NTP, monitoring, backup
- **Cloudflare Tunnel Agents**: Per-site tunnel configurations
## Viewing the Diagrams
These SVG files can be viewed in:
- Web browsers (Chrome, Firefox, Safari, Edge)
- Vector graphics editors (Inkscape, Adobe Illustrator)
- Documentation tools (GitHub, GitLab, Confluence)
- VS Code with SVG preview extensions
## Generating PNG Versions
To convert SVG to PNG for presentations:
```bash
# Using Inkscape
inkscape --export-type=png --export-width=2400 system-overview.svg
# Using ImageMagick
convert -density 300 system-overview.svg system-overview.png
# Using rsvg-convert
rsvg-convert -w 2400 system-overview.svg > system-overview.png
```
## Diagram Maintenance
When updating diagrams:
1. Maintain consistent color scheme
2. Update component labels when architecture changes
3. Keep network addresses and IPs accurate
4. Document new components in this README
5. Export PNG versions for presentations if needed
## Color Scheme
- **Blue (#326CE5)**: Kubernetes components
- **Orange (#F38020)**: Cloudflare services
- **Orange (#E57000)**: Proxmox infrastructure
- **Teal (#00D4AA)**: Portal and UI components
- **Red (#E74C3C)**: Authentication/Identity
- **Gray (#34495E)**: Servers and infrastructure
- **Light Gray (#ECF0F1)**: Network segments

View File

@@ -0,0 +1,225 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 900">
<defs>
<style>
.user { fill: #9B59B6; stroke: #7D3C98; stroke-width: 2; }
.cloudflare { fill: #F38020; stroke: #C85F00; }
.portal { fill: #00D4AA; stroke: #00A888; }
.auth { fill: #E74C3C; stroke: #C0392B; }
.k8s { fill: #326CE5; stroke: #1E4A8A; }
.proxmox { fill: #E57000; stroke: #B85900; }
.text { font-family: Arial, sans-serif; font-size: 11px; fill: #333; }
.title { font-size: 14px; font-weight: bold; }
.arrow { stroke: #333; stroke-width: 2; fill: none; marker-end: url(#arrowhead); }
.flow-label { font-size: 10px; fill: #666; }
</style>
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
<polygon points="0 0, 10 3, 0 6" fill="#333" />
</marker>
</defs>
<text x="700" y="30" text-anchor="middle" class="text title">Data Flow Diagrams - Authentication & Provisioning</text>
<!-- Authentication Flow Section -->
<text x="350" y="70" text-anchor="middle" class="text title">1. Authentication Flow</text>
<!-- User -->
<circle cx="100" cy="150" r="40" class="user"/>
<text x="100" y="155" text-anchor="middle" class="text" fill="white">User</text>
<!-- Cloudflare Access -->
<rect x="200" y="120" width="120" height="60" class="cloudflare" rx="5"/>
<text x="260" y="145" text-anchor="middle" class="text" fill="white">Cloudflare</text>
<text x="260" y="165" text-anchor="middle" class="text" fill="white">Access</text>
<!-- Portal -->
<rect x="380" y="120" width="120" height="60" class="portal" rx="5"/>
<text x="440" y="145" text-anchor="middle" class="text" fill="white">Portal</text>
<text x="440" y="165" text-anchor="middle" class="text" fill="white">(Next.js)</text>
<!-- Keycloak -->
<rect x="560" y="120" width="120" height="60" class="auth" rx="5"/>
<text x="620" y="145" text-anchor="middle" class="text" fill="white">Keycloak</text>
<text x="620" y="165" text-anchor="middle" class="text" fill="white">OIDC</text>
<!-- Auth Flow Arrows -->
<line x1="140" y1="150" x2="200" y2="150" class="arrow"/>
<text x="170" y="145" class="flow-label">1. Request</text>
<line x1="320" y1="150" x2="380" y2="150" class="arrow"/>
<text x="350" y="145" class="flow-label">2. Redirect</text>
<line x1="500" y1="150" x2="560" y2="150" class="arrow"/>
<text x="530" y="145" class="flow-label">3. Auth</text>
<line x1="560" y1="180" x2="500" y2="180" class="arrow"/>
<text x="530" y="185" class="flow-label">4. JWT</text>
<line x1="380" y1="180" x2="320" y2="180" class="arrow"/>
<text x="350" y="185" class="flow-label">5. Token</text>
<line x1="200" y1="180" x2="140" y2="180" class="arrow"/>
<text x="170" y="185" class="flow-label">6. Session</text>
<!-- Provisioning Flow Section -->
<text x="1050" y="70" text-anchor="middle" class="text title">2. VM Provisioning Flow</text>
<!-- User Action -->
<circle cx="900" cy="150" r="40" class="user"/>
<text x="900" y="155" text-anchor="middle" class="text" fill="white">User</text>
<!-- Portal -->
<rect x="1000" y="120" width="120" height="60" class="portal" rx="5"/>
<text x="1060" y="145" text-anchor="middle" class="text" fill="white">Portal</text>
<text x="1060" y="165" text-anchor="middle" class="text" fill="white">UI</text>
<!-- Crossplane -->
<rect x="1180" y="120" width="120" height="60" class="k8s" rx="5"/>
<text x="1240" y="145" text-anchor="middle" class="text" fill="white">Crossplane</text>
<text x="1240" y="165" text-anchor="middle" class="text" fill="white">API</text>
<!-- ArgoCD -->
<rect x="1360" y="120" width="120" height="60" class="k8s" rx="5"/>
<text x="1420" y="145" text-anchor="middle" class="text" fill="white">ArgoCD</text>
<text x="1420" y="165" text-anchor="middle" class="text" fill="white">GitOps</text>
<!-- Provisioning Flow Arrows -->
<line x1="940" y1="150" x2="1000" y2="150" class="arrow"/>
<text x="970" y="145" class="flow-label">1. Create VM</text>
<line x1="1120" y1="150" x2="1180" y2="150" class="arrow"/>
<text x="1150" y="145" class="flow-label">2. CRD</text>
<line x1="1300" y1="150" x2="1360" y2="150" class="arrow"/>
<text x="1330" y="145" class="flow-label">3. Sync</text>
<!-- Proxmox Provider -->
<rect x="1180" y="250" width="120" height="60" class="proxmox" rx="5"/>
<text x="1240" y="275" text-anchor="middle" class="text" fill="white">Proxmox</text>
<text x="1240" y="295" text-anchor="middle" class="text" fill="white">Provider</text>
<!-- Proxmox Site -->
<rect x="1360" y="250" width="120" height="60" class="proxmox" rx="5"/>
<text x="1420" y="275" text-anchor="middle" class="text" fill="white">Proxmox</text>
<text x="1420" y="295" text-anchor="middle" class="text" fill="white">Site</text>
<line x1="1240" y1="250" x2="1240" y2="220" class="arrow"/>
<text x="1270" y="235" class="flow-label">4. Reconcile</text>
<line x1="1300" y1="280" x2="1360" y2="280" class="arrow"/>
<text x="1330" y="275" class="flow-label">5. API Call</text>
<line x1="1360" y1="310" x2="1300" y2="310" class="arrow"/>
<text x="1330" y="315" class="flow-label">6. Status</text>
<!-- Monitoring Flow Section -->
<text x="350" y="400" text-anchor="middle" class="text title">3. Monitoring & Observability Flow</text>
<!-- Proxmox Node -->
<rect x="50" y="450" width="120" height="60" class="proxmox" rx="5"/>
<text x="110" y="475" text-anchor="middle" class="text" fill="white">Proxmox</text>
<text x="110" y="495" text-anchor="middle" class="text" fill="white">Node</text>
<!-- Exporter -->
<rect x="220" y="450" width="120" height="60" class="k8s" rx="5"/>
<text x="280" y="475" text-anchor="middle" class="text" fill="white">pve-exporter</text>
<text x="280" y="495" text-anchor="middle" class="text" fill="white">Prometheus</text>
<!-- Prometheus -->
<rect x="390" y="450" width="120" height="60" class="k8s" rx="5"/>
<text x="450" y="475" text-anchor="middle" class="text" fill="white">Prometheus</text>
<text x="450" y="495" text-anchor="middle" class="text" fill="white">Metrics DB</text>
<!-- Grafana -->
<rect x="560" y="450" width="120" height="60" class="portal" rx="5"/>
<text x="620" y="475" text-anchor="middle" class="text" fill="white">Grafana</text>
<text x="620" y="495" text-anchor="middle" class="text" fill="white">Dashboards</text>
<!-- Portal -->
<rect x="730" y="450" width="120" height="60" class="portal" rx="5"/>
<text x="790" y="475" text-anchor="middle" class="text" fill="white">Portal</text>
<text x="790" y="495" text-anchor="middle" class="text" fill="white">Embed</text>
<!-- Monitoring Flow Arrows -->
<line x1="170" y1="480" x2="220" y2="480" class="arrow"/>
<text x="195" y="475" class="flow-label">1. Metrics</text>
<line x1="340" y1="480" x2="390" y2="480" class="arrow"/>
<text x="365" y="475" class="flow-label">2. Scrape</text>
<line x1="510" y1="480" x2="560" y2="480" class="arrow"/>
<text x="535" y="475" class="flow-label">3. Query</text>
<line x1="680" y1="480" x2="730" y2="480" class="arrow"/>
<text x="705" y="475" class="flow-label">4. Display</text>
<!-- Log Flow Section -->
<text x="1050" y="400" text-anchor="middle" class="text title">4. Log Aggregation Flow</text>
<!-- Services -->
<rect x="900" y="450" width="120" height="60" class="k8s" rx="5"/>
<text x="960" y="475" text-anchor="middle" class="text" fill="white">Services</text>
<text x="960" y="495" text-anchor="middle" class="text" fill="white">(K8s/VMs)</text>
<!-- Promtail -->
<rect x="1070" y="450" width="120" height="60" class="k8s" rx="5"/>
<text x="1130" y="475" text-anchor="middle" class="text" fill="white">Promtail</text>
<text x="1130" y="495" text-anchor="middle" class="text" fill="white">Collector</text>
<!-- Loki -->
<rect x="1240" y="450" width="120" height="60" class="k8s" rx="5"/>
<text x="1300" y="475" text-anchor="middle" class="text" fill="white">Loki</text>
<text x="1300" y="495" text-anchor="middle" class="text" fill="white">Log Store</text>
<!-- Portal -->
<rect x="1410" y="450" width="120" height="60" class="portal" rx="5"/>
<text x="1470" y="475" text-anchor="middle" class="text" fill="white">Portal</text>
<text x="1470" y="495" text-anchor="middle" class="text" fill="white">Viewer</text>
<!-- Log Flow Arrows -->
<line x1="1020" y1="480" x2="1070" y2="480" class="arrow"/>
<text x="1045" y="475" class="flow-label">1. Logs</text>
<line x1="1190" y1="480" x2="1240" y2="480" class="arrow"/>
<text x="1215" y="475" class="flow-label">2. Ship</text>
<line x1="1360" y1="480" x2="1410" y2="480" class="arrow"/>
<text x="1385" y="475" class="flow-label">3. Query</text>
<!-- GitOps Flow Section -->
<text x="700" y="600" text-anchor="middle" class="text title">5. GitOps Deployment Flow</text>
<!-- Developer -->
<circle cx="200" cy="700" r="40" class="user"/>
<text x="200" y="705" text-anchor="middle" class="text" fill="white">Dev</text>
<!-- Git Repo -->
<rect x="300" y="670" width="120" height="60" class="k8s" rx="5"/>
<text x="360" y="695" text-anchor="middle" class="text" fill="white">Git Repo</text>
<text x="360" y="715" text-anchor="middle" class="text" fill="white">(Manifests)</text>
<!-- ArgoCD -->
<rect x="480" y="670" width="120" height="60" class="k8s" rx="5"/>
<text x="540" y="695" text-anchor="middle" class="text" fill="white">ArgoCD</text>
<text x="540" y="715" text-anchor="middle" class="text" fill="white">Controller</text>
<!-- Kubernetes -->
<rect x="660" y="670" width="120" height="60" class="k8s" rx="5"/>
<text x="720" y="695" text-anchor="middle" class="text" fill="white">Kubernetes</text>
<text x="720" y="715" text-anchor="middle" class="text" fill="white">API Server</text>
<!-- Crossplane -->
<rect x="840" y="670" width="120" height="60" class="k8s" rx="5"/>
<text x="900" y="695" text-anchor="middle" class="text" fill="white">Crossplane</text>
<text x="900" y="715" text-anchor="middle" class="text" fill="white">Providers</text>
<!-- Infrastructure -->
<rect x="1020" y="670" width="120" height="60" class="proxmox" rx="5"/>
<text x="1080" y="695" text-anchor="middle" class="text" fill="white">Infra</text>
<text x="1080" y="715" text-anchor="middle" class="text" fill="white">(Proxmox)</text>
<!-- GitOps Flow Arrows -->
<line x1="240" y1="700" x2="300" y2="700" class="arrow"/>
<text x="270" y="695" class="flow-label">1. Commit</text>
<line x1="420" y1="700" x2="480" y2="700" class="arrow"/>
<text x="450" y="695" class="flow-label">2. Poll</text>
<line x1="600" y1="700" x2="660" y2="700" class="arrow"/>
<text x="630" y="695" class="flow-label">3. Apply</text>
<line x1="780" y1="700" x2="840" y2="700" class="arrow"/>
<text x="810" y="695" class="flow-label">4. Reconcile</text>
<line x1="960" y1="700" x2="1020" y2="700" class="arrow"/>
<text x="990" y="695" class="flow-label">5. Provision</text>
<!-- Status Feedback -->
<line x1="1020" y1="730" x2="960" y2="730" class="arrow" stroke-dasharray="3,3"/>
<text x="990" y="735" class="flow-label">6. Status</text>
<line x1="840" y1="730" x2="780" y2="730" class="arrow" stroke-dasharray="3,3"/>
<line x1="660" y1="730" x2="600" y2="730" class="arrow" stroke-dasharray="3,3"/>
<line x1="480" y1="730" x2="420" y2="730" class="arrow" stroke-dasharray="3,3"/>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,638 @@
# Phoenix Sankofa Cloud: Data Model & GraphQL Schema
## Overview
The data model for **Phoenix Sankofa Cloud** is designed as a **graph-oriented structure** that represents:
* Infrastructure resources (regions, clusters, nodes, services)
* Relationships between resources (networks, dependencies, policies)
* Metrics and telemetry (performance, health, cost)
* Well-Architected Framework assessments
* Identity and access management
* Cultural intelligence and regional context
---
## Core GraphQL Schema
### Resource Types
```graphql
# Base resource interface
interface Resource {
id: ID!
name: String!
type: ResourceType!
region: Region
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
}
enum ResourceType {
REGION
SITE
CLUSTER
NODE
VM
POD
SERVICE
NETWORK
STORAGE
TUNNEL
POLICY
}
# Region - Top-level geographic location
type Region implements Resource {
id: ID!
name: String!
type: ResourceType!
code: String! # e.g., "us-east-1"
country: String
coordinates: Coordinates
sites: [Site!]!
clusters: [Cluster!]!
networks: [Network!]!
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
culturalContext: CulturalContext
}
# Site - Physical or logical location within a region
type Site implements Resource {
id: ID!
name: String!
type: ResourceType!
region: Region!
clusters: [Cluster!]!
networks: [Network!]!
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
}
# Cluster - Compute cluster (Kubernetes, Proxmox, etc.)
type Cluster implements Resource {
id: ID!
name: String!
type: ResourceType!
region: Region
site: Site
nodes: [Node!]!
services: [Service!]!
provider: ProviderType
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
health: HealthStatus!
metrics: ClusterMetrics
}
# Node - Individual compute node
type Node implements Resource {
id: ID!
name: String!
type: ResourceType!
cluster: Cluster!
vms: [VM!]!
pods: [Pod!]!
provider: ProviderType
specs: NodeSpecs
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
health: HealthStatus!
metrics: NodeMetrics
}
# Service - Application service
type Service implements Resource {
id: ID!
name: String!
type: ResourceType!
cluster: Cluster
pods: [Pod!]!
dependencies: [Service!]! # Services this depends on
dependents: [Service!]! # Services that depend on this
networks: [Network!]!
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
health: HealthStatus!
metrics: ServiceMetrics
}
# Network - Network resource (VPC, subnet, tunnel, etc.)
type Network implements Resource {
id: ID!
name: String!
type: ResourceType!
region: Region
cidr: String
connections: [NetworkConnection!]!
services: [Service!]!
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
}
# Network Connection - Edge between networks
type NetworkConnection {
id: ID!
from: Network!
to: Network!
type: ConnectionType!
latency: Float
bandwidth: Float
status: ConnectionStatus!
createdAt: DateTime!
updatedAt: DateTime!
}
enum ConnectionType {
PEERING
VPN
TUNNEL
DIRECT
}
enum ConnectionStatus {
ACTIVE
INACTIVE
DEGRADED
FAILED
}
# Storage - Storage resource
type Storage implements Resource {
id: ID!
name: String!
type: ResourceType!
region: Region
cluster: Cluster
size: Float!
used: Float!
createdAt: DateTime!
updatedAt: DateTime!
metadata: JSON
tags: [Tag!]!
metrics: StorageMetrics
}
```
### Well-Architected Framework
```graphql
# Well-Architected Framework Pillar
type Pillar {
id: ID!
name: String!
code: PillarCode!
description: String
controls: [Control!]!
resources: [Resource!]!
}
enum PillarCode {
SECURITY
RELIABILITY
COST_OPTIMIZATION
PERFORMANCE_EFFICIENCY
OPERATIONAL_EXCELLENCE
SUSTAINABILITY
}
# Control - Specific control within a pillar
type Control {
id: ID!
name: String!
code: String!
pillar: Pillar!
description: String
findings: [Finding!]!
resources: [Resource!]!
}
# Finding - Assessment finding for a control
type Finding {
id: ID!
control: Control!
resource: Resource!
status: FindingStatus!
severity: Severity!
title: String!
description: String
recommendation: String
createdAt: DateTime!
updatedAt: DateTime!
}
enum FindingStatus {
PASS
FAIL
WARNING
INFO
NOT_APPLICABLE
}
enum Severity {
CRITICAL
HIGH
MEDIUM
LOW
INFO
}
# Risk - Risk associated with a resource
type Risk {
id: ID!
resource: Resource!
pillar: Pillar
severity: Severity!
title: String!
description: String
mitigation: String
createdAt: DateTime!
updatedAt: DateTime!
}
```
### Metrics & Telemetry
```graphql
# Metrics - Time-series metrics
type Metrics {
resource: Resource!
metricType: MetricType!
values: [MetricValue!]!
timeRange: TimeRange!
}
enum MetricType {
CPU_USAGE
MEMORY_USAGE
NETWORK_THROUGHPUT
NETWORK_LATENCY
STORAGE_IOPS
REQUEST_RATE
ERROR_RATE
COST
HEALTH_SCORE
}
type MetricValue {
timestamp: DateTime!
value: Float!
labels: JSON
}
type TimeRange {
start: DateTime!
end: DateTime!
}
# Health Status
enum HealthStatus {
HEALTHY
DEGRADED
UNHEALTHY
UNKNOWN
}
# Cluster Metrics
type ClusterMetrics {
cpuUsage: Float!
memoryUsage: Float!
nodeCount: Int!
healthyNodes: Int!
unhealthyNodes: Int!
totalCost: Float!
healthScore: Float!
}
# Node Metrics
type NodeMetrics {
cpuUsage: Float!
memoryUsage: Float!
diskUsage: Float!
networkThroughput: Float!
healthScore: Float!
}
# Service Metrics
type ServiceMetrics {
requestRate: Float!
errorRate: Float!
latency: Float!
availability: Float!
healthScore: Float!
}
# Storage Metrics
type StorageMetrics {
used: Float!
available: Float!
iops: Float!
throughput: Float!
}
```
### Cultural Intelligence
```graphql
# Cultural Context - Cultural information for a region
type CulturalContext {
region: Region!
language: String
timezone: String
culturalNorms: JSON
complianceRequirements: [ComplianceRequirement!]!
dataResidency: DataResidency
}
# Data Residency
type DataResidency {
region: Region!
requirements: [String!]!
compliance: [ComplianceRequirement!]!
}
```
### Identity & Access
```graphql
# Identity - User or service identity
type Identity {
id: ID!
type: IdentityType!
name: String!
email: String
roles: [Role!]!
permissions: [Permission!]!
createdAt: DateTime!
updatedAt: DateTime!
}
enum IdentityType {
USER
SERVICE
SYSTEM
}
# Role - Access role
type Role {
id: ID!
name: String!
permissions: [Permission!]!
resources: [Resource!]!
}
# Permission - Access permission
type Permission {
id: ID!
action: Action!
resource: Resource
conditions: JSON
}
enum Action {
READ
WRITE
DELETE
ADMIN
}
```
### Queries
```graphql
type Query {
# Resource queries
resource(id: ID!): Resource
resources(filter: ResourceFilter): [Resource!]!
region(id: ID!): Region
regions: [Region!]!
cluster(id: ID!): Cluster
clusters(filter: ClusterFilter): [Cluster!]!
# Network queries
network(id: ID!): Network
networks(filter: NetworkFilter): [Network!]!
networkTopology(regionId: ID): NetworkTopology!
# Service queries
service(id: ID!): Service
services(filter: ServiceFilter): [Service!]!
serviceDependencies(serviceId: ID!): [Service!]!
# Well-Architected Framework
pillar(code: PillarCode!): Pillar
pillars: [Pillar!]!
findings(filter: FindingFilter): [Finding!]!
risks(resourceId: ID): [Risk!]!
# Metrics
metrics(resourceId: ID!, metricType: MetricType!, timeRange: TimeRange!): Metrics!
# Health
health(resourceId: ID!): HealthStatus!
# Cultural context
culturalContext(regionId: ID!): CulturalContext
}
```
### Mutations
```graphql
type Mutation {
# Resource mutations
createResource(input: CreateResourceInput!): Resource!
updateResource(id: ID!, input: UpdateResourceInput!): Resource!
deleteResource(id: ID!): Boolean!
# Finding mutations
createFinding(input: CreateFindingInput!): Finding!
updateFinding(id: ID!, input: UpdateFindingInput!): Finding!
# Risk mutations
createRisk(input: CreateRiskInput!): Risk!
updateRisk(id: ID!, input: UpdateRiskInput!): Risk!
}
```
### Subscriptions
```graphql
type Subscription {
# Real-time updates
resourceUpdated(resourceId: ID!): Resource!
metricsUpdated(resourceId: ID!, metricType: MetricType!): MetricValue!
healthChanged(resourceId: ID!): HealthStatus!
findingCreated(controlId: ID): Finding!
riskCreated(resourceId: ID): Risk!
}
```
---
## Database Schema (PostgreSQL)
### Core Tables
```sql
-- Regions
CREATE TABLE regions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
code VARCHAR(50) UNIQUE NOT NULL,
country VARCHAR(100),
latitude DECIMAL(10, 8),
longitude DECIMAL(11, 8),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
metadata JSONB
);
-- Resources (polymorphic)
CREATE TABLE resources (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
type VARCHAR(50) NOT NULL,
region_id UUID REFERENCES regions(id),
site_id UUID,
cluster_id UUID,
parent_id UUID REFERENCES resources(id),
provider VARCHAR(50),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
metadata JSONB
);
-- Resource relationships (graph edges)
CREATE TABLE resource_relationships (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
from_resource_id UUID NOT NULL REFERENCES resources(id),
to_resource_id UUID NOT NULL REFERENCES resources(id),
relationship_type VARCHAR(50) NOT NULL,
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(from_resource_id, to_resource_id, relationship_type)
);
-- Metrics (time-series)
CREATE TABLE metrics (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
resource_id UUID NOT NULL REFERENCES resources(id),
metric_type VARCHAR(50) NOT NULL,
value DECIMAL(20, 4) NOT NULL,
timestamp TIMESTAMP NOT NULL,
labels JSONB,
PRIMARY KEY (resource_id, metric_type, timestamp)
);
-- Well-Architected Framework
CREATE TABLE pillars (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
code VARCHAR(50) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT
);
CREATE TABLE controls (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
pillar_id UUID NOT NULL REFERENCES pillars(id),
code VARCHAR(50) NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
UNIQUE(pillar_id, code)
);
CREATE TABLE findings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
control_id UUID NOT NULL REFERENCES controls(id),
resource_id UUID NOT NULL REFERENCES resources(id),
status VARCHAR(50) NOT NULL,
severity VARCHAR(50) NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
recommendation TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Indexes for performance
CREATE INDEX idx_resources_type ON resources(type);
CREATE INDEX idx_resources_region ON resources(region_id);
CREATE INDEX idx_metrics_resource_time ON metrics(resource_id, timestamp DESC);
CREATE INDEX idx_findings_resource ON findings(resource_id);
CREATE INDEX idx_findings_control ON findings(control_id);
```
---
## Neo4j Graph Schema (Optional)
For complex graph queries, Neo4j can be used:
```cypher
// Node labels
(:Region)
(:Site)
(:Cluster)
(:Node)
(:Service)
(:Network)
(:Storage)
// Relationships
(:Region)-[:CONTAINS]->(:Site)
(:Site)-[:CONTAINS]->(:Cluster)
(:Cluster)-[:CONTAINS]->(:Node)
(:Service)-[:DEPENDS_ON]->(:Service)
(:Network)-[:CONNECTS_TO]->(:Network)
(:Resource)-[:AFFECTS_PILLAR]->(:Pillar)
```
---
## Integration Points
### Control Plane Adapters
The data model integrates with:
1. **Proxmox**: Cluster, VM, storage data
2. **Kubernetes/Crossplane**: Pod, service, network data
3. **Cloudflare**: Tunnel, DNS, network data
4. **Prometheus**: Metrics and telemetry
5. **Custom APIs**: Additional infrastructure sources
### Normalization
All control plane data is normalized into the unified graph model, allowing:
* Single source of truth
* Consistent query interface
* Cross-platform relationships
* Unified visualization
---
## Future Enhancements
1. **AI/ML Integration**: Model predictions and recommendations
2. **Cost Optimization**: Cost tracking and optimization recommendations
3. **Security Posture**: Security assessments and threat intelligence
4. **Compliance**: Compliance tracking and reporting
5. **Cultural Intelligence**: Enhanced cultural context and adaptation

View File

@@ -0,0 +1,244 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1100">
<defs>
<style>
.server { fill: #34495E; stroke: #2C3E50; stroke-width: 2; }
.k8s-node { fill: #326CE5; stroke: #1E4A8A; stroke-width: 2; }
.proxmox-node { fill: #E57000; stroke: #B85900; stroke-width: 2; }
.storage { fill: #95A5A6; stroke: #7F8C8D; stroke-width: 2; }
.network { fill: #3498DB; stroke: #2980B9; stroke-width: 1; }
.text { font-family: Arial, sans-serif; font-size: 11px; fill: #333; }
.title { font-size: 14px; font-weight: bold; }
.label { font-size: 9px; fill: #666; }
</style>
</defs>
<text x="800" y="30" text-anchor="middle" class="text title">Deployment Architecture - Infrastructure Layout</text>
<!-- Control Plane Cluster -->
<text x="400" y="70" text-anchor="middle" class="text title">Control Plane Cluster (Primary Site)</text>
<!-- K8s Master Nodes -->
<rect x="50" y="100" width="200" height="120" class="k8s-node" rx="5"/>
<text x="150" y="125" text-anchor="middle" class="text" fill="white">K8s Master 1</text>
<text x="150" y="145" text-anchor="middle" class="text" fill="white">etcd, API Server</text>
<text x="150" y="165" text-anchor="middle" class="text" fill="white">Scheduler, Controller</text>
<text x="150" y="185" text-anchor="middle" class="label" fill="white">CPU: 8 cores</text>
<text x="150" y="200" text-anchor="middle" class="label" fill="white">RAM: 32GB</text>
<text x="150" y="215" text-anchor="middle" class="label" fill="white">Disk: 500GB SSD</text>
<rect x="300" y="100" width="200" height="120" class="k8s-node" rx="5"/>
<text x="400" y="125" text-anchor="middle" class="text" fill="white">K8s Master 2</text>
<text x="400" y="145" text-anchor="middle" class="text" fill="white">etcd, API Server</text>
<text x="400" y="165" text-anchor="middle" class="text" fill="white">Scheduler, Controller</text>
<text x="400" y="185" text-anchor="middle" class="label" fill="white">CPU: 8 cores</text>
<text x="400" y="200" text-anchor="middle" class="label" fill="white">RAM: 32GB</text>
<text x="400" y="215" text-anchor="middle" class="label" fill="white">Disk: 500GB SSD</text>
<rect x="550" y="100" width="200" height="120" class="k8s-node" rx="5"/>
<text x="650" y="125" text-anchor="middle" class="text" fill="white">K8s Master 3</text>
<text x="650" y="145" text-anchor="middle" class="text" fill="white">etcd, API Server</text>
<text x="650" y="165" text-anchor="middle" class="text" fill="white">Scheduler, Controller</text>
<text x="650" y="185" text-anchor="middle" class="label" fill="white">CPU: 8 cores</text>
<text x="650" y="200" text-anchor="middle" class="label" fill="white">RAM: 32GB</text>
<text x="650" y="215" text-anchor="middle" class="label" fill="white">Disk: 500GB SSD</text>
<!-- K8s Worker Nodes -->
<rect x="100" y="260" width="180" height="100" class="k8s-node" rx="5"/>
<text x="190" y="285" text-anchor="middle" class="text" fill="white">Worker 1</text>
<text x="190" y="305" text-anchor="middle" class="text" fill="white">Rancher, Crossplane</text>
<text x="190" y="325" text-anchor="middle" class="text" fill="white">ArgoCD, Vault</text>
<text x="190" y="345" text-anchor="middle" class="label" fill="white">CPU: 16 cores, RAM: 64GB</text>
<rect x="320" y="260" width="180" height="100" class="k8s-node" rx="5"/>
<text x="410" y="285" text-anchor="middle" class="text" fill="white">Worker 2</text>
<text x="410" y="305" text-anchor="middle" class="text" fill="white">Portal (Next.js)</text>
<text x="410" y="325" text-anchor="middle" class="text" fill="white">Keycloak</text>
<text x="410" y="345" text-anchor="middle" class="label" fill="white">CPU: 16 cores, RAM: 64GB</text>
<rect x="540" y="260" width="180" height="100" class="k8s-node" rx="5"/>
<text x="630" y="285" text-anchor="middle" class="text" fill="white">Worker 3</text>
<text x="630" y="305" text-anchor="middle" class="text" fill="white">Prometheus, Grafana</text>
<text x="630" y="325" text-anchor="middle" class="text" fill="white">Loki, Tempo</text>
<text x="630" y="345" text-anchor="middle" class="label" fill="white">CPU: 16 cores, RAM: 64GB</text>
<!-- Storage for Control Plane -->
<rect x="750" y="100" width="150" height="260" class="storage" rx="5"/>
<text x="825" y="125" text-anchor="middle" class="text" fill="white">Shared Storage</text>
<text x="825" y="150" text-anchor="middle" class="text" fill="white">(NFS/Ceph)</text>
<text x="825" y="180" text-anchor="middle" class="label" fill="white">• ETCD Backups</text>
<text x="825" y="200" text-anchor="middle" class="label" fill="white">• PVC Storage</text>
<text x="825" y="220" text-anchor="middle" class="label" fill="white">• Log Archives</text>
<text x="825" y="240" text-anchor="middle" class="label" fill="white">• Metrics Data</text>
<text x="825" y="260" text-anchor="middle" class="label" fill="white">• Config Backups</text>
<text x="825" y="280" text-anchor="middle" class="label" fill="white">Capacity: 10TB</text>
<text x="825" y="300" text-anchor="middle" class="label" fill="white">Replication: 3x</text>
<text x="825" y="320" text-anchor="middle" class="label" fill="white">Type: Ceph RBD</text>
<text x="825" y="340" text-anchor="middle" class="label" fill="white">Performance: NVMe</text>
<!-- Proxmox Site 1 -->
<text x="1200" y="70" text-anchor="middle" class="text title">Proxmox Site 1 - US-East</text>
<rect x="950" y="100" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="1050" y="125" text-anchor="middle" class="text" fill="white">PVE Node 1</text>
<text x="1050" y="145" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="1050" y="165" text-anchor="middle" class="label" fill="white">CPU: 32 cores</text>
<text x="1050" y="180" text-anchor="middle" class="label" fill="white">RAM: 256GB</text>
<text x="1050" y="195" text-anchor="middle" class="label" fill="white">VMs: 20</text>
<text x="1050" y="210" text-anchor="middle" class="label" fill="white">Storage: Ceph OSD</text>
<rect x="1200" y="100" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="1300" y="125" text-anchor="middle" class="text" fill="white">PVE Node 2</text>
<text x="1300" y="145" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="1300" y="165" text-anchor="middle" class="label" fill="white">CPU: 32 cores</text>
<text x="1300" y="180" text-anchor="middle" class="label" fill="white">RAM: 256GB</text>
<text x="1300" y="195" text-anchor="middle" class="label" fill="white">VMs: 18</text>
<text x="1300" y="210" text-anchor="middle" class="label" fill="white">Storage: Ceph OSD</text>
<rect x="1450" y="100" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="1550" y="125" text-anchor="middle" class="text" fill="white">PVE Node 3</text>
<text x="1550" y="145" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="1550" y="165" text-anchor="middle" class="label" fill="white">CPU: 32 cores</text>
<text x="1550" y="180" text-anchor="middle" class="label" fill="white">RAM: 256GB</text>
<text x="1550" y="195" text-anchor="middle" class="label" fill="white">VMs: 15</text>
<text x="1550" y="210" text-anchor="middle" class="label" fill="white">Storage: Ceph OSD</text>
<!-- Ceph Storage Cluster -->
<rect x="1000" y="260" width="500" height="100" class="storage" rx="5"/>
<text x="1250" y="285" text-anchor="middle" class="text" fill="white">Ceph Storage Cluster</text>
<text x="1100" y="310" text-anchor="middle" class="label" fill="white">MON: 3 nodes</text>
<text x="1250" y="310" text-anchor="middle" class="label" fill="white">OSD: 9 nodes</text>
<text x="1400" y="310" text-anchor="middle" class="label" fill="white">MDS: 2 nodes</text>
<text x="1250" y="330" text-anchor="middle" class="label" fill="white">Total: 200TB, Replication: 3x</text>
<!-- Proxmox Site 2 -->
<text x="400" y="420" text-anchor="middle" class="text title">Proxmox Site 2 - EU-West</text>
<rect x="50" y="450" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="150" y="475" text-anchor="middle" class="text" fill="white">PVE Node 1</text>
<text x="150" y="495" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="150" y="515" text-anchor="middle" class="label" fill="white">CPU: 24 cores</text>
<text x="150" y="530" text-anchor="middle" class="label" fill="white">RAM: 192GB</text>
<text x="150" y="545" text-anchor="middle" class="label" fill="white">VMs: 15</text>
<text x="150" y="560" text-anchor="middle" class="label" fill="white">Storage: ZFS</text>
<rect x="300" y="450" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="400" y="475" text-anchor="middle" class="text" fill="white">PVE Node 2</text>
<text x="400" y="495" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="400" y="515" text-anchor="middle" class="label" fill="white">CPU: 24 cores</text>
<text x="400" y="530" text-anchor="middle" class="label" fill="white">RAM: 192GB</text>
<text x="400" y="545" text-anchor="middle" class="label" fill="white">VMs: 12</text>
<text x="400" y="560" text-anchor="middle" class="label" fill="white">Storage: ZFS</text>
<rect x="550" y="450" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="650" y="475" text-anchor="middle" class="text" fill="white">PVE Node 3</text>
<text x="650" y="495" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="650" y="515" text-anchor="middle" class="label" fill="white">CPU: 24 cores</text>
<text x="650" y="530" text-anchor="middle" class="label" fill="white">RAM: 192GB</text>
<text x="650" y="545" text-anchor="middle" class="label" fill="white">VMs: 10</text>
<text x="650" y="560" text-anchor="middle" class="label" fill="white">Storage: ZFS</text>
<!-- ZFS Storage -->
<rect x="100" y="610" width="500" height="80" class="storage" rx="5"/>
<text x="350" y="635" text-anchor="middle" class="text" fill="white">ZFS Storage Pools</text>
<text x="250" y="660" text-anchor="middle" class="label" fill="white">Pool 1: 50TB (RAID-Z2)</text>
<text x="450" y="660" text-anchor="middle" class="label" fill="white">Pool 2: 30TB (RAID-Z1)</text>
<text x="350" y="680" text-anchor="middle" class="label" fill="white">Replication: Async to Site 1</text>
<!-- Proxmox Site 3 -->
<text x="1200" y="420" text-anchor="middle" class="text title">Proxmox Site 3 - APAC</text>
<rect x="950" y="450" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="1050" y="475" text-anchor="middle" class="text" fill="white">PVE Node 1</text>
<text x="1050" y="495" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="1050" y="515" text-anchor="middle" class="label" fill="white">CPU: 16 cores</text>
<text x="1050" y="530" text-anchor="middle" class="label" fill="white">RAM: 128GB</text>
<text x="1050" y="545" text-anchor="middle" class="label" fill="white">VMs: 10</text>
<text x="1050" y="560" text-anchor="middle" class="label" fill="white">Storage: Local</text>
<rect x="1200" y="450" width="200" height="120" class="proxmox-node" rx="5"/>
<text x="1300" y="475" text-anchor="middle" class="text" fill="white">PVE Node 2</text>
<text x="1300" y="495" text-anchor="middle" class="text" fill="white">Hypervisor</text>
<text x="1300" y="515" text-anchor="middle" class="label" fill="white">CPU: 16 cores</text>
<text x="1300" y="530" text-anchor="middle" class="label" fill="white">RAM: 128GB</text>
<text x="1300" y="545" text-anchor="middle" class="label" fill="white">VMs: 8</text>
<text x="1300" y="560" text-anchor="middle" class="label" fill="white">Storage: Local</text>
<!-- Local Storage -->
<rect x="1000" y="610" width="400" height="80" class="storage" rx="5"/>
<text x="1200" y="635" text-anchor="middle" class="text" fill="white">Local Storage</text>
<text x="1100" y="660" text-anchor="middle" class="label" fill="white">Node 1: 20TB SSD</text>
<text x="1300" y="660" text-anchor="middle" class="label" fill="white">Node 2: 20TB SSD</text>
<text x="1200" y="680" text-anchor="middle" class="label" fill="white">Backup: Daily to Site 1</text>
<!-- Network Infrastructure -->
<rect x="50" y="730" width="1500" height="120" class="network" rx="5"/>
<text x="800" y="755" text-anchor="middle" class="text title">Network Infrastructure</text>
<rect x="100" y="770" width="200" height="60" class="server" rx="3"/>
<text x="200" y="790" text-anchor="middle" class="text" fill="white">Load Balancer</text>
<text x="200" y="810" text-anchor="middle" class="label" fill="white">HAProxy / MetalLB</text>
<text x="200" y="825" text-anchor="middle" class="label" fill="white">VIP: 10.0.0.10</text>
<rect x="350" y="770" width="200" height="60" class="server" rx="3"/>
<text x="450" y="790" text-anchor="middle" class="text" fill="white">Gateway Router</text>
<text x="450" y="810" text-anchor="middle" class="label" fill="white">BGP / OSPF</text>
<text x="450" y="825" text-anchor="middle" class="label" fill="white">10.0.0.1</text>
<rect x="600" y="770" width="200" height="60" class="server" rx="3"/>
<text x="700" y="790" text-anchor="middle" class="text" fill="white">DNS Server</text>
<text x="700" y="810" text-anchor="middle" class="label" fill="white">CoreDNS / BIND</text>
<text x="700" y="825" text-anchor="middle" class="label" fill="white">10.0.0.53</text>
<rect x="850" y="770" width="200" height="60" class="server" rx="3"/>
<text x="950" y="790" text-anchor="middle" class="text" fill="white">NTP Server</text>
<text x="950" y="810" text-anchor="middle" class="label" fill="white">Chrony / NTPd</text>
<text x="950" y="825" text-anchor="middle" class="label" fill="white">Time Sync</text>
<rect x="1100" y="770" width="200" height="60" class="server" rx="3"/>
<text x="1200" y="790" text-anchor="middle" class="text" fill="white">Monitoring Node</text>
<text x="1200" y="810" text-anchor="middle" class="label" fill="white">Prometheus Exporter</text>
<text x="1200" y="825" text-anchor="middle" class="label" fill="white">10.0.0.100</text>
<rect x="1350" y="770" width="200" height="60" class="server" rx="3"/>
<text x="1450" y="790" text-anchor="middle" class="text" fill="white">Backup Server</text>
<text x="1450" y="810" text-anchor="middle" class="label" fill="white">Proxmox Backup</text>
<text x="1450" y="825" text-anchor="middle" class="label" fill="white">10.0.0.200</text>
<!-- Cloudflare Tunnels -->
<rect x="50" y="890" width="1500" height="80" class="network" rx="5" fill="#F38020" opacity="0.3"/>
<text x="800" y="915" text-anchor="middle" class="text title">Cloudflare Tunnel Agents</text>
<rect x="100" y="930" width="150" height="30" class="server" rx="3"/>
<text x="175" y="948" text-anchor="middle" class="label">Control Plane Tunnel</text>
<rect x="300" y="930" width="150" height="30" class="server" rx="3"/>
<text x="375" y="948" text-anchor="middle" class="label">Site 1 Tunnel</text>
<rect x="500" y="930" width="150" height="30" class="server" rx="3"/>
<text x="575" y="948" text-anchor="middle" class="label">Site 2 Tunnel</text>
<rect x="700" y="930" width="150" height="30" class="server" rx="3"/>
<text x="775" y="948" text-anchor="middle" class="label">Site 3 Tunnel</text>
<rect x="900" y="930" width="150" height="30" class="server" rx="3"/>
<text x="975" y="948" text-anchor="middle" class="label">Portal Tunnel</text>
<rect x="1100" y="930" width="150" height="30" class="server" rx="3"/>
<text x="1175" y="948" text-anchor="middle" class="label">API Tunnel</text>
<rect x="1300" y="930" width="150" height="30" class="server" rx="3"/>
<text x="1375" y="948" text-anchor="middle" class="label">Monitoring Tunnel</text>
<!-- Legend -->
<rect x="50" y="1000" width="300" height="80" class="network" rx="5"/>
<text x="200" y="1020" text-anchor="middle" class="text title">Legend</text>
<rect x="70" y="1030" width="30" height="20" class="k8s-node" rx="2"/>
<text x="110" y="1045" class="label">Kubernetes Node</text>
<rect x="70" y="1055" width="30" height="20" class="proxmox-node" rx="2"/>
<text x="110" y="1070" class="label">Proxmox Node</text>
<rect x="200" y="1030" width="30" height="20" class="storage" rx="2"/>
<text x="240" y="1045" class="label">Storage</text>
<rect x="200" y="1055" width="30" height="20" class="network" rx="2"/>
<text x="240" y="1070" class="label">Network/Service</text>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,162 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1000">
<defs>
<style>
.internet { fill: #3498DB; stroke: #2980B9; stroke-width: 2; }
.cloudflare { fill: #F38020; stroke: #C85F00; stroke-width: 2; }
.control-plane { fill: #326CE5; stroke: #1E4A8A; stroke-width: 2; }
.proxmox { fill: #E57000; stroke: #B85900; stroke-width: 2; }
.tunnel { stroke: #F38020; stroke-width: 3; stroke-dasharray: 10,5; fill: none; }
.network { stroke: #7F8C8D; stroke-width: 1; fill: #ECF0F1; }
.text { font-family: Arial, sans-serif; font-size: 12px; fill: #333; }
.title { font-size: 16px; font-weight: bold; }
.label { font-size: 10px; fill: #666; }
</style>
</defs>
<text x="800" y="30" text-anchor="middle" class="text title">Network Topology - Global Hybrid Cloud</text>
<!-- Internet Cloud -->
<ellipse cx="800" cy="100" rx="200" ry="40" class="internet"/>
<text x="800" y="105" text-anchor="middle" class="text" fill="white">Internet</text>
<!-- Cloudflare Global Network -->
<rect x="200" y="180" width="1200" height="120" class="cloudflare" rx="10"/>
<text x="800" y="210" text-anchor="middle" class="text title" fill="white">Cloudflare Global Network</text>
<text x="400" y="240" text-anchor="middle" class="text" fill="white">Edge Locations (200+ cities)</text>
<text x="800" y="240" text-anchor="middle" class="text" fill="white">Zero Trust Gateway</text>
<text x="1200" y="240" text-anchor="middle" class="text" fill="white">DNS + DDoS Protection</text>
<!-- Control Plane Site -->
<rect x="600" y="350" width="400" height="200" class="control-plane" rx="10"/>
<text x="800" y="380" text-anchor="middle" class="text title" fill="white">Control Plane (Primary Site)</text>
<!-- Control Plane Components -->
<rect x="630" y="400" width="100" height="60" class="network" rx="5"/>
<text x="680" y="425" text-anchor="middle" class="text">K8s API</text>
<text x="680" y="445" text-anchor="middle" class="text">Server</text>
<rect x="750" y="400" width="100" height="60" class="network" rx="5"/>
<text x="800" y="425" text-anchor="middle" class="text">Rancher</text>
<text x="800" y="445" text-anchor="middle" class="text">UI</text>
<rect x="870" y="400" width="100" height="60" class="network" rx="5"/>
<text x="920" y="425" text-anchor="middle" class="text">Crossplane</text>
<text x="920" y="445" text-anchor="middle" class="text">API</text>
<rect x="630" y="480" width="100" height="60" class="network" rx="5"/>
<text x="680" y="505" text-anchor="middle" class="text">ArgoCD</text>
<text x="680" y="525" text-anchor="middle" class="text">GitOps</text>
<rect x="750" y="480" width="100" height="60" class="network" rx="5"/>
<text x="800" y="505" text-anchor="middle" class="text">Portal</text>
<text x="800" y="525" text-anchor="middle" class="text">(Next.js)</text>
<rect x="870" y="480" width="100" height="60" class="network" rx="5"/>
<text x="920" y="505" text-anchor="middle" class="text">Keycloak</text>
<text x="920" y="525" text-anchor="middle" class="text">Auth</text>
<!-- Cloudflare Tunnel to Control Plane -->
<path d="M 800 350 Q 800 280 800 300" class="tunnel"/>
<text x="820" y="320" class="label">Tunnel 1</text>
<!-- Proxmox Site 1 (US-East) -->
<rect x="100" y="650" width="350" height="300" class="proxmox" rx="10"/>
<text x="275" y="680" text-anchor="middle" class="text title" fill="white">Proxmox Site 1 - US-East</text>
<!-- Site 1 Nodes -->
<rect x="130" y="710" width="120" height="100" class="network" rx="5"/>
<text x="190" y="735" text-anchor="middle" class="text">Node 1</text>
<text x="190" y="755" text-anchor="middle" class="text">pve1.example.com</text>
<text x="190" y="775" text-anchor="middle" class="text">VMs: 20</text>
<text x="190" y="795" text-anchor="middle" class="text">Storage: Ceph</text>
<rect x="280" y="710" width="120" height="100" class="network" rx="5"/>
<text x="340" y="735" text-anchor="middle" class="text">Node 2</text>
<text x="340" y="755" text-anchor="middle" class="text">pve2.example.com</text>
<text x="340" y="775" text-anchor="middle" class="text">VMs: 18</text>
<text x="340" y="795" text-anchor="middle" class="text">Storage: Ceph</text>
<!-- Site 1 Tunnel -->
<rect x="130" y="830" width="120" height="60" class="cloudflare" rx="5"/>
<text x="190" y="855" text-anchor="middle" class="text" fill="white">cloudflared</text>
<text x="190" y="875" text-anchor="middle" class="text" fill="white">Agent</text>
<path d="M 190 830 Q 190 500 400 300" class="tunnel"/>
<text x="250" y="550" class="label">Tunnel 2</text>
<!-- Proxmox Site 2 (EU-West) -->
<rect x="550" y="650" width="350" height="300" class="proxmox" rx="10"/>
<text x="725" y="680" text-anchor="middle" class="text title" fill="white">Proxmox Site 2 - EU-West</text>
<!-- Site 2 Nodes -->
<rect x="580" y="710" width="120" height="100" class="network" rx="5"/>
<text x="640" y="735" text-anchor="middle" class="text">Node 1</text>
<text x="640" y="755" text-anchor="middle" class="text">pve3.example.com</text>
<text x="640" y="775" text-anchor="middle" class="text">VMs: 15</text>
<text x="640" y="795" text-anchor="middle" class="text">Storage: ZFS</text>
<rect x="730" y="710" width="120" height="100" class="network" rx="5"/>
<text x="790" y="735" text-anchor="middle" class="text">Node 2</text>
<text x="790" y="755" text-anchor="middle" class="text">pve4.example.com</text>
<text x="790" y="775" text-anchor="middle" class="text">VMs: 12</text>
<text x="790" y="795" text-anchor="middle" class="text">Storage: ZFS</text>
<!-- Site 2 Tunnel -->
<rect x="580" y="830" width="120" height="60" class="cloudflare" rx="5"/>
<text x="640" y="855" text-anchor="middle" class="text" fill="white">cloudflared</text>
<text x="640" y="875" text-anchor="middle" class="text" fill="white">Agent</text>
<path d="M 640 830 Q 640 500 800 300" class="tunnel"/>
<text x="700" y="550" class="label">Tunnel 3</text>
<!-- Proxmox Site 3 (APAC) -->
<rect x="1000" y="650" width="350" height="300" class="proxmox" rx="10"/>
<text x="1175" y="680" text-anchor="middle" class="text title" fill="white">Proxmox Site 3 - APAC</text>
<!-- Site 3 Nodes -->
<rect x="1030" y="710" width="120" height="100" class="network" rx="5"/>
<text x="1090" y="735" text-anchor="middle" class="text">Node 1</text>
<text x="1090" y="755" text-anchor="middle" class="text">pve5.example.com</text>
<text x="1090" y="775" text-anchor="middle" class="text">VMs: 10</text>
<text x="1090" y="795" text-anchor="middle" class="text">Storage: Local</text>
<rect x="1180" y="710" width="120" height="100" class="network" rx="5"/>
<text x="1240" y="735" text-anchor="middle" class="text">Node 2</text>
<text x="1240" y="755" text-anchor="middle" class="text">pve6.example.com</text>
<text x="1240" y="775" text-anchor="middle" class="text">VMs: 8</text>
<text x="1240" y="795" text-anchor="middle" class="text">Storage: Local</text>
<!-- Site 3 Tunnel -->
<rect x="1030" y="830" width="120" height="60" class="cloudflare" rx="5"/>
<text x="1090" y="855" text-anchor="middle" class="text" fill="white">cloudflared</text>
<text x="1090" y="875" text-anchor="middle" class="text" fill="white">Agent</text>
<path d="M 1090 830 Q 1090 500 1000 300" class="tunnel"/>
<text x="1050" y="550" class="label">Tunnel 4</text>
<!-- Local Networks -->
<rect x="130" y="920" width="270" height="20" class="network" rx="3"/>
<text x="265" y="933" text-anchor="middle" class="label">Site 1 LAN: 10.1.0.0/16</text>
<rect x="580" y="920" width="270" height="20" class="network" rx="3"/>
<text x="715" y="933" text-anchor="middle" class="label">Site 2 LAN: 10.2.0.0/16</text>
<rect x="1030" y="920" width="270" height="20" class="network" rx="3"/>
<text x="1165" y="933" text-anchor="middle" class="label">Site 3 LAN: 10.3.0.0/16</text>
<!-- Control Plane Network -->
<rect x="630" y="570" width="340" height="20" class="network" rx="3"/>
<text x="800" y="583" text-anchor="middle" class="label">Control Plane LAN: 10.0.0.0/16</text>
<!-- Connection Labels -->
<text x="200" y="150" class="label">HTTPS (443)</text>
<text x="1400" y="150" class="label">HTTPS (443)</text>
<!-- Security Notes -->
<rect x="50" y="50" width="200" height="80" class="network" rx="5"/>
<text x="150" y="70" text-anchor="middle" class="text title">Security Features</text>
<text x="150" y="90" text-anchor="middle" class="label">• Zero Trust Access</text>
<text x="150" y="105" text-anchor="middle" class="label">• No Public IPs</text>
<text x="150" y="120" text-anchor="middle" class="label">• Encrypted Tunnels</text>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -0,0 +1,134 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<defs>
<style>
.component { fill: #4A90E2; stroke: #2E5C8A; stroke-width: 2; }
.cloudflare { fill: #F38020; stroke: #C85F00; }
.proxmox { fill: #E57000; stroke: #B85900; }
.k8s { fill: #326CE5; stroke: #1E4A8A; }
.portal { fill: #00D4AA; stroke: #00A888; }
.text { font-family: Arial, sans-serif; font-size: 12px; fill: #333; }
.title { font-size: 16px; font-weight: bold; }
.arrow { stroke: #666; stroke-width: 2; fill: none; marker-end: url(#arrowhead); }
</style>
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
<polygon points="0 0, 10 3, 0 6" fill="#666" />
</marker>
</defs>
<!-- Title -->
<text x="600" y="30" text-anchor="middle" class="text title">Hybrid Cloud Control Plane - System Overview</text>
<!-- Cloudflare Layer -->
<rect x="50" y="60" width="1100" height="100" class="cloudflare" rx="5"/>
<text x="600" y="85" text-anchor="middle" class="text title" fill="white">Cloudflare Zero Trust Layer</text>
<text x="200" y="110" text-anchor="middle" class="text" fill="white">Access Policies</text>
<text x="400" y="110" text-anchor="middle" class="text" fill="white">Tunnels</text>
<text x="600" y="110" text-anchor="middle" class="text" fill="white">Gateway</text>
<text x="800" y="110" text-anchor="middle" class="text" fill="white">WARP</text>
<text x="1000" y="110" text-anchor="middle" class="text" fill="white">DNS</text>
<!-- Portal Layer -->
<rect x="50" y="200" width="300" height="120" class="portal" rx="5"/>
<text x="200" y="230" text-anchor="middle" class="text title" fill="white">Custom Portal</text>
<text x="200" y="250" text-anchor="middle" class="text" fill="white">Next.js + React</text>
<text x="200" y="270" text-anchor="middle" class="text" fill="white">Keycloak Auth</text>
<text x="200" y="290" text-anchor="middle" class="text" fill="white">RBAC UI</text>
<!-- Control Plane -->
<rect x="400" y="200" width="750" height="120" class="k8s" rx="5"/>
<text x="775" y="230" text-anchor="middle" class="text title" fill="white">Kubernetes Control Plane (RKE2/k3s)</text>
<rect x="420" y="240" width="140" height="60" class="component" rx="3"/>
<text x="490" y="265" text-anchor="middle" class="text" fill="white">Rancher</text>
<rect x="580" y="240" width="140" height="60" class="component" rx="3"/>
<text x="650" y="265" text-anchor="middle" class="text" fill="white">Crossplane</text>
<rect x="740" y="240" width="140" height="60" class="component" rx="3"/>
<text x="810" y="265" text-anchor="middle" class="text" fill="white">ArgoCD</text>
<rect x="900" y="240" width="140" height="60" class="component" rx="3"/>
<text x="970" y="265" text-anchor="middle" class="text" fill="white">Vault</text>
<!-- Observability -->
<rect x="50" y="360" width="300" height="100" class="component" rx="5"/>
<text x="200" y="385" text-anchor="middle" class="text title" fill="white">Observability Stack</text>
<text x="200" y="410" text-anchor="middle" class="text" fill="white">Prometheus</text>
<text x="200" y="430" text-anchor="middle" class="text" fill="white">Grafana</text>
<text x="200" y="450" text-anchor="middle" class="text" fill="white">Loki</text>
<!-- Identity -->
<rect x="400" y="360" width="200" height="100" class="component" rx="5"/>
<text x="500" y="385" text-anchor="middle" class="text title" fill="white">Identity</text>
<text x="500" y="410" text-anchor="middle" class="text" fill="white">Keycloak</text>
<text x="500" y="430" text-anchor="middle" class="text" fill="white">OIDC Provider</text>
<text x="500" y="450" text-anchor="middle" class="text" fill="white">MFA + SSO</text>
<!-- GitOps -->
<rect x="650" y="360" width="200" height="100" class="component" rx="5"/>
<text x="750" y="385" text-anchor="middle" class="text title" fill="white">GitOps</text>
<text x="750" y="410" text-anchor="middle" class="text" fill="white">ArgoCD</text>
<text x="750" y="430" text-anchor="middle" class="text" fill="white">Git Repository</text>
<text x="750" y="450" text-anchor="middle" class="text" fill="white">Kustomize</text>
<!-- Proxmox Sites -->
<rect x="900" y="360" width="250" height="100" class="proxmox" rx="5"/>
<text x="1025" y="385" text-anchor="middle" class="text title" fill="white">Proxmox Sites</text>
<text x="1025" y="410" text-anchor="middle" class="text" fill="white">Site 1 (US-East)</text>
<text x="1025" y="430" text-anchor="middle" class="text" fill="white">Site 2 (EU-West)</text>
<text x="1025" y="450" text-anchor="middle" class="text" fill="white">Site N (Global)</text>
<!-- Edge Infrastructure -->
<rect x="50" y="500" width="1100" height="250" class="proxmox" rx="5"/>
<text x="600" y="530" text-anchor="middle" class="text title" fill="white">Edge Infrastructure - Proxmox VE Clusters</text>
<!-- Site 1 -->
<rect x="100" y="560" width="300" height="160" class="component" rx="5"/>
<text x="250" y="585" text-anchor="middle" class="text title" fill="white">Proxmox Site 1</text>
<rect x="120" y="600" width="120" height="100" class="k8s" rx="3"/>
<text x="180" y="630" text-anchor="middle" class="text" fill="white">Node 1</text>
<text x="180" y="650" text-anchor="middle" class="text" fill="white">VMs</text>
<text x="180" y="670" text-anchor="middle" class="text" fill="white">Ceph</text>
<rect x="260" y="600" width="120" height="100" class="k8s" rx="3"/>
<text x="320" y="630" text-anchor="middle" class="text" fill="white">Node 2</text>
<text x="320" y="650" text-anchor="middle" class="text" fill="white">VMs</text>
<text x="320" y="670" text-anchor="middle" class="text" fill="white">Ceph</text>
<!-- Site 2 -->
<rect x="450" y="560" width="300" height="160" class="component" rx="5"/>
<text x="600" y="585" text-anchor="middle" class="text title" fill="white">Proxmox Site 2</text>
<rect x="470" y="600" width="120" height="100" class="k8s" rx="3"/>
<text x="530" y="630" text-anchor="middle" class="text" fill="white">Node 1</text>
<text x="530" y="650" text-anchor="middle" class="text" fill="white">VMs</text>
<text x="530" y="670" text-anchor="middle" class="text" fill="white">ZFS</text>
<rect x="610" y="600" width="120" height="100" class="k8s" rx="3"/>
<text x="670" y="630" text-anchor="middle" class="text" fill="white">Node 2</text>
<text x="670" y="650" text-anchor="middle" class="text" fill="white">VMs</text>
<text x="670" y="670" text-anchor="middle" class="text" fill="white">ZFS</text>
<!-- Site 3 -->
<rect x="800" y="560" width="300" height="160" class="component" rx="5"/>
<text x="950" y="585" text-anchor="middle" class="text title" fill="white">Proxmox Site 3</text>
<rect x="820" y="600" width="120" height="100" class="k8s" rx="3"/>
<text x="880" y="630" text-anchor="middle" class="text" fill="white">Node 1</text>
<text x="880" y="650" text-anchor="middle" class="text" fill="white">VMs</text>
<text x="880" y="670" text-anchor="middle" class="text" fill="white">Storage</text>
<rect x="960" y="600" width="120" height="100" class="k8s" rx="3"/>
<text x="1020" y="630" text-anchor="middle" class="text" fill="white">Node 2</text>
<text x="1020" y="650" text-anchor="middle" class="text" fill="white">VMs</text>
<text x="1020" y="670" text-anchor="middle" class="text" fill="white">Storage</text>
<!-- Arrows -->
<line x1="200" y1="200" x2="200" y2="160" class="arrow"/>
<line x1="400" y1="260" x2="350" y2="260" class="arrow"/>
<line x1="775" y1="200" x2="775" y2="160" class="arrow"/>
<line x1="200" y1="320" x2="200" y2="360" class="arrow"/>
<line x1="500" y1="320" x2="500" y2="360" class="arrow"/>
<line x1="750" y1="320" x2="750" y2="360" class="arrow"/>
<line x1="1025" y1="360" x2="1025" y2="560" class="arrow"/>
<line x1="250" y1="560" x2="250" y2="500" class="arrow"/>
<line x1="600" y1="560" x2="600" y2="500" class="arrow"/>
<line x1="950" y1="560" x2="950" y2="500" class="arrow"/>
<!-- Cloudflare Tunnel Connections -->
<line x1="400" y1="110" x2="250" y2="560" class="arrow" stroke-dasharray="5,5" stroke="#F38020"/>
<line x1="400" y1="110" x2="600" y2="560" class="arrow" stroke-dasharray="5,5" stroke="#F38020"/>
<line x1="400" y1="110" x2="950" y2="560" class="arrow" stroke-dasharray="5,5" stroke="#F38020"/>
</svg>

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -0,0 +1,342 @@
# Phoenix Sankofa Cloud: Technology Stack
## Overview
**Phoenix Sankofa Cloud** is built on a modern, scalable technology stack designed for:
* **Dashboards** → fast, reactive, drill-down, cross-filtering
* **Drag-n-drop & node graph editing** → workflows, network topologies, app maps
* **3D visualizations** → network and architecture in 3D, interactive camera, labels, layers
* **"Studio quality" visuals** → film/AAA-game-adjacent look, not BI chart boilerplate
* **Future-proof** → typed, testable, driven by existing control plane (Proxmox, Crossplane, Cloudflare, etc.)
---
## Front-End Stack
### Core Framework
**Next.js 14+ (React + TypeScript)**
- App Router for modern routing
- SSR/ISR for performance and SEO
- API routes for light backend glue
- Excellent DX, file-based routing, easy deployment
### Language
**TypeScript**
- Strong typing for complex graph interactions
- Type safety for 3D scenes and data structures
- Better IDE support and developer experience
### Styling & Layout
**TailwindCSS + shadcn/ui**
- Modern, dark-mode-friendly design system
- Dense "studio dashboard" aesthetic
- Full control over styling and theming
- Component-based UI library
**Framer Motion**
- Smooth animations and transitions
- Panel transitions, node selection, drag-n-drop feedback
- Mode transitions (2D <-> 3D)
### State Management
**Zustand / Jotai**
- Local UI state management
- Lightweight and performant
**React Query (TanStack Query)**
- Server state management
- GraphQL client integration
- Caching and synchronization
---
## Dashboards & Analytics
### Charts / Dashboards
**ECharts** (via React wrappers)
- Complex, animated dashboards
- High performance
- Extensive customization options
- Studio-quality visuals
**Alternative: visx / Recharts**
- More React-native feel
- Good for design-system-driven visuals
### Tables & Data Grids
**TanStack Table (React Table)**
- Advanced, virtualized tables
- Custom cell renders (status pills, spark-lines, tags)
- Excellent performance for large datasets
### Maps / Geo
**Mapbox GL JS** or **deck.gl**
- Plotting regions, edge locations, tunnel endpoints
- Interactive geographic visualizations
---
## Drag-n-Drop and Visual Editors
### Graph/Node-Based Editing
**React Flow**
- Excellent for node/edge editors
- Built-in zoom/pan, minimap
- Custom node/edge renderers
- Perfect for L2 "Well-Architected Framework" diagrams
- Logical views of architecture
### General Drag-n-Drop
**@dnd-kit** or **react-beautiful-dnd**
- List/board/kitchen-sink DnD
- Building component palettes
- Dashboard layout editors
### Canvas 2D
**Konva.js / react-konva**
- Highly interactive 2D diagrams
- Annotations and overlays
- High-performance 2D rendering
**Pattern:**
- L2 / logical diagrams → React Flow / Konva
- L3 / detailed visuals → 3D WebGL (see 3D section)
---
## 3D Visualizations
### 3D Engine
**three.js**
- WebGL engine for 3D graphics
- Industry standard for web 3D
**react-three-fiber (R3F)**
- Declarative three.js in React
- Component-based 3D scene management
**@react-three/drei**
- Camera controls, orbits, gizmos
- Text rendering, environment setup
- Helper components for common 3D patterns
**postprocessing** (R3F plugin)
- Bloom effects
- SSAO (Screen-Space Ambient Occlusion)
- Depth of field
- Color grading
- Cinematic visual quality
### Graph & Network Visuals in 3D
**3D Graph Layout**
- **d3-force-3d** or **ngraph.forcelayout3d**
- Position nodes in 3D space
- Feed positions into R3F meshes (spheres, cubes, capsules)
- Connect with lines or tubes
**Topologies**
- Each **node** = service, region, cluster, VPC, etc.
- Each **edge** = peering, VPN, Cloudflare tunnel, dependency
- Layers for:
* Regions (325 global nodes)
* Availability zones / sites
* Services running
* Health & risk overlays (color, size, pulsing)
**Interactions**
- Orbital camera (drei's `<OrbitControls />`)
- Click nodes → open side panel with metrics
- Hover edges → show latency, bandwidth, status
- Use **instanced meshes** for performance with many nodes
---
## Back-End & Data Model
### API Layer
**GraphQL**
- **Option A**: Hasura on Postgres (auto GraphQL)
- **Option B**: Apollo Server / NestJS GraphQL over Postgres/Neo4j
- Perfect fit for graph-like data:
* regions
* clusters
* networks
* services
* dependencies
### Data Store
**Relational + Graph Hybrid**
**Option A (Pragmatic):**
- **PostgreSQL** with:
* Topology tables (resources, relations, metrics)
* JSONB for flexible metadata
* Materialized views for dashboards
**Option B (More "Native"):**
- **Neo4j** or another graph DB for relationships
* Natural for queries like:
* "Show all paths from this service to this edge"
* "Which nodes share a risk factor?"
**Hybrid Approach:**
- Start with Postgres
- Move hot graph queries to Neo4j later
- Best of both worlds
### Real-Time
**Real-Time Pipeline**
- **Metrics**: Prometheus → push to TSDB (Prometheus / Timescale)
- **Events**: Kafka/Redpanda or NATS for events (state changes, incidents)
- **UI**: WebSockets / GraphQL Subscriptions to push updates
**Examples:**
- Node changes color when health crosses threshold
- Edge animates when traffic spikes
- New region lights up when provisioned via Crossplane
---
## Integration with Infrastructure
### Control-Plane Adapters (Backend Services)
Services that:
- Call **Proxmox APIs** (cluster, VM, storage)
- Call **Cloudflare APIs** (tunnels, Zero Trust configs, DNS)
- Query **Crossplane/Kubernetes** (CRDs representing resources)
### Normalize into "Resource Graph"
Everything becomes a node in graph DB or Postgres schema:
- Region
- Site
- Cluster
- Node
- VM/Pod/Service
- Tunnel
- Policy
**UI reads this graph, not raw cloud APIs.**
This enables Azure-Graph-like behavior without Azure.
---
## Tooling, DevOps, and Quality
### Dev Environment
- **Package Manager**: pnpm / yarn
- **Linting**: ESLint
- **Formatting**: Prettier
- **Component Development**: Storybook (for UI components & visual system)
- **Testing**: Vitest / Jest + React Testing Library
### Build & Deploy
**Docker Images** for:
- Front-end (Next.js)
- API (GraphQL servers)
- Graph DB / Postgres
**Deploy on:**
- Kubernetes control cluster (part of architecture)
- Traefik or NGINX Ingress behind Cloudflare
### Observability
- **Logs**: Loki / ELK
- **Metrics**: Prometheus + Grafana
- **Traces**: OpenTelemetry / Tempo
---
## Well-Architected Framework Visualizations
### Pillar Views
- Security
- Reliability
- Cost Optimization
- Performance Efficiency
- Operational Excellence
- Sustainability
### Layered Views
- **Physical** (Proxmox nodes, racks)
- **Network** (subnets, tunnels, regions)
- **Application** (services, workloads, dependencies)
- **Governance** (policies, SLAs, compliance)
### Implementation Pattern
1. **Model pillars & controls in backend**
- GraphQL types: Pillar, Control, Finding, Risk, Recommendation
2. **Bind each resource node** to:
- Which pillar(s) it affects
- Score/health for each pillar
3. **In UI:**
- Use **React Flow** 2D diagrams for pillar-specific overlays
- Use **R3F 3D** to show structural/physical layout, colored by pillar health
- Provide **"Lens" switch** (Performance lens, Security lens, Cost lens) that:
* Changes color mapping & overlays
* Toggles visibility of certain node types
* Animates transitions with Framer Motion / R3F
This delivers **studio-quality, cinematic, but cognitively useful** Well-Architected views.
---
## Recommended Stack Summary (Opinionated)
### Front-End
* Next.js (React, TypeScript)
* TailwindCSS + shadcn/ui
* React Query / Apollo Client
* Framer Motion
* React Flow + @dnd-kit
* react-three-fiber + drei + postprocessing
* ECharts / visx for charts
* TanStack Table for data grids
### Back-End
* GraphQL API (NestJS + Apollo OR Hasura + Postgres)
* Postgres (core data) + optional Neo4j for complex graph queries
* WebSockets / GraphQL Subscriptions for real-time
### Infra
* K8s on existing clusters
* Traefik/NGINX ingress behind Cloudflare
* Prometheus, Loki, Grafana, OpenTelemetry
---
## Next Steps
1. Design the **actual data model** (tables/graph schema)
2. Sketch the **component structure** of the UI (pages, editors, 3D views)
3. Write **starter Next.js project structure** with key libraries wired together

View File

@@ -0,0 +1,450 @@
# Phoenix Sankofa Cloud: Well-Architected Framework Visualization
## Overview
**Phoenix Sankofa Cloud** implements a comprehensive Well-Architected Framework (WAF) visualization system that provides:
* **Studio-quality visuals** with cinematic aesthetics
* **Multi-layered views** of the same architecture
* **Pillar-specific lenses** for focused analysis
* **Interactive 3D and 2D visualizations**
* **Real-time health and risk overlays**
---
## Well-Architected Framework Pillars
### 1. Security
**Focus**: Protecting information, systems, and assets
**Key Areas:**
- Identity and access management
- Threat detection and response
- Data protection
- Infrastructure security
- Compliance and governance
**Visual Indicators:**
- Color: Red/Amber for risks, Green for secure
- Icons: Shield, lock, key symbols
- Overlays: Security zones, access boundaries
### 2. Reliability
**Focus**: Ability to recover from failures and meet demand
**Key Areas:**
- Fault tolerance
- Disaster recovery
- High availability
- Capacity planning
- Change management
**Visual Indicators:**
- Color: Green for healthy, Red for failures
- Icons: Checkmark, warning, error symbols
- Overlays: Availability zones, redundancy paths
### 3. Cost Optimization
**Focus**: Achieving the lowest price point
**Key Areas:**
- Right-sizing resources
- Reserved capacity
- Cost monitoring
- Eliminating waste
- Pricing models
**Visual Indicators:**
- Color: Green for optimized, Red for high cost
- Icons: Dollar, chart, trend symbols
- Overlays: Cost heatmaps, spending trends
### 4. Performance Efficiency
**Focus**: Using computing resources efficiently
**Key Areas:**
- Compute optimization
- Storage optimization
- Network optimization
- Database optimization
- Caching strategies
**Visual Indicators:**
- Color: Green for efficient, Red for bottlenecks
- Icons: Speed, performance, optimization symbols
- Overlays: Performance metrics, bottlenecks
### 5. Operational Excellence
**Focus**: Running and monitoring systems
**Key Areas:**
- Automation
- Change management
- Monitoring and observability
- Incident response
- Documentation
**Visual Indicators:**
- Color: Blue for operational, Amber for issues
- Icons: Gear, monitor, alert symbols
- Overlays: Operational status, automation flows
### 6. Sustainability
**Focus**: Environmental impact and efficiency
**Key Areas:**
- Energy efficiency
- Resource optimization
- Carbon footprint
- Renewable energy
- Waste reduction
**Visual Indicators:**
- Color: Green for sustainable, Red for impact
- Icons: Leaf, energy, environment symbols
- Overlays: Energy consumption, carbon footprint
---
## Visualization Architecture
### Layered Views
The same infrastructure can be viewed through different layers:
#### 1. Physical Layer
- **Shows**: Proxmox nodes, racks, physical infrastructure
- **Use Case**: Physical topology, hardware health
- **Visualization**: 3D physical layout, node positions
#### 2. Network Layer
- **Shows**: Subnets, tunnels, regions, network connections
- **Use Case**: Network topology, connectivity, routing
- **Visualization**: 3D network graph, connection flows
#### 3. Application Layer
- **Shows**: Services, workloads, dependencies
- **Use Case**: Application architecture, service dependencies
- **Visualization**: 2D/3D service graph, dependency trees
#### 4. Governance Layer
- **Shows**: Policies, SLAs, compliance, access controls
- **Use Case**: Governance, compliance, policy enforcement
- **Visualization**: Policy overlays, compliance status
---
## Implementation Pattern
### Backend Model
```graphql
# Pillar definition
type Pillar {
id: ID!
code: PillarCode!
name: String!
controls: [Control!]!
}
# Control definition
type Control {
id: ID!
pillar: Pillar!
code: String!
name: String!
findings: [Finding!]!
}
# Finding for a resource
type Finding {
id: ID!
control: Control!
resource: Resource!
status: FindingStatus!
severity: Severity!
recommendation: String
}
# Risk associated with resource
type Risk {
id: ID!
resource: Resource!
pillar: Pillar
severity: Severity!
title: String!
mitigation: String
}
```
### Resource Binding
Each resource node is bound to:
1. **Pillar Affiliations**: Which pillars affect this resource
2. **Health Scores**: Score (0-100) for each pillar
3. **Findings**: Specific findings for this resource
4. **Risks**: Risks associated with this resource
### UI Implementation
#### 2D Diagrams (React Flow)
**Pillar-Specific Overlays:**
- Security lens: Show security zones, access boundaries
- Reliability lens: Show redundancy, failover paths
- Cost lens: Show cost heatmaps, spending trends
- Performance lens: Show bottlenecks, optimization opportunities
- Operations lens: Show automation, monitoring coverage
- Sustainability lens: Show energy consumption, carbon footprint
**Features:**
- Custom node renderers based on pillar health
- Color coding by pillar score
- Overlay toggles for different aspects
- Interactive drill-down
#### 3D Visualizations (react-three-fiber)
**Structural/Physical Layout:**
- 3D representation of infrastructure
- Nodes colored by pillar health
- Edges showing relationships
- Layers for different resource types
**Pillar Lenses:**
- Switch between pillar views
- Color mapping changes based on selected pillar
- Node size/glow based on health score
- Animated transitions between lenses
**Features:**
- Orbital camera controls
- Click nodes for details
- Hover for quick info
- Layer visibility toggles
- Smooth animations
---
## Lens Switching System
### Lens Types
1. **Security Lens**
- Color: Red/Amber/Green based on security posture
- Overlays: Security zones, access boundaries, threat indicators
- Filters: Show only security-relevant resources
2. **Reliability Lens**
- Color: Green/Amber/Red based on availability
- Overlays: Redundancy paths, failover capabilities
- Filters: Show reliability-critical resources
3. **Cost Lens**
- Color: Green/Amber/Red based on cost efficiency
- Overlays: Cost heatmaps, spending trends
- Filters: Show high-cost resources
4. **Performance Lens**
- Color: Green/Amber/Red based on performance
- Overlays: Bottlenecks, optimization opportunities
- Filters: Show performance-critical resources
5. **Operations Lens**
- Color: Blue/Amber based on operational status
- Overlays: Automation coverage, monitoring
- Filters: Show operational resources
6. **Sustainability Lens**
- Color: Green/Amber/Red based on environmental impact
- Overlays: Energy consumption, carbon footprint
- Filters: Show high-impact resources
### Lens Switching UI
```typescript
// Lens selector component
<LensSelector
currentLens={selectedLens}
onLensChange={handleLensChange}
pillars={pillars}
/>
// Animated transition
<AnimatePresence mode="wait">
<motion.div
key={selectedLens}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<Visualization lens={selectedLens} />
</motion.div>
</AnimatePresence>
```
---
## Visual Design Principles
### Studio Quality Aesthetic
* **Dark Theme**: Near-black backgrounds (`#0A0A0A`)
* **Neon Accents**: Teal, magenta, cyan, amber for status
* **Glow Effects**: Subtle glow around important nodes
* **Layered Depth**: Multiple layers for visual hierarchy
* **Smooth Animations**: 200-300ms transitions
### Color Coding
**Health Scores:**
- **90-100**: Bright Green (`#00FF88`)
- **70-89**: Amber (`#FFB800`)
- **50-69**: Orange (`#FF8C00`)
- **0-49**: Red (`#FF0040`)
**Pillar-Specific:**
- **Security**: Red spectrum
- **Reliability**: Green spectrum
- **Cost**: Blue spectrum
- **Performance**: Cyan spectrum
- **Operations**: Purple spectrum
- **Sustainability**: Green spectrum
### Typography
* **Headings**: Inter/Satoshi, bold
* **Metrics**: Monospace for numbers
* **Labels**: Inter, regular
* **Consistent Scale**: 12px, 14px, 16px, 18px, 24px, 32px, 48px
---
## Interactive Features
### Node Interactions
1. **Click**: Open side panel with:
- Resource details
- Pillar scores
- Findings and risks
- Recommendations
- Metrics
2. **Hover**: Show tooltip with:
- Resource name
- Health score
- Quick metrics
- Status
3. **Select**: Highlight and show:
- Related resources
- Dependencies
- Affected pillars
### Edge Interactions
1. **Hover**: Show:
- Connection type
- Latency
- Bandwidth
- Status
2. **Click**: Show:
- Connection details
- Metrics
- Health
### View Controls
1. **Zoom/Pan**: Navigate the visualization
2. **Filter**: Show/hide resource types
3. **Search**: Find specific resources
4. **Time Range**: View historical states
5. **Export**: Export visualization as image/PDF
---
## Real-Time Updates
### WebSocket Subscriptions
```graphql
subscription {
healthChanged(resourceId: $resourceId) {
resourceId
healthStatus
pillarScores
}
findingCreated(controlId: $controlId) {
id
resource
status
severity
}
riskCreated(resourceId: $resourceId) {
id
resource
severity
title
}
}
```
### Update Behavior
1. **Node Color**: Updates when health score changes
2. **Node Size**: Updates when metrics change
3. **Edge Animation**: Pulses when traffic spikes
4. **Overlay Refresh**: Updates when findings change
5. **Smooth Transitions**: Animated updates, not jarring
---
## Component Structure
```
src/components/well-architected/
├── LensSelector.tsx # Pillar lens selector
├── PillarView.tsx # Pillar-specific view
├── ResourceNode.tsx # Resource node component
├── FindingOverlay.tsx # Findings overlay
├── RiskIndicator.tsx # Risk indicators
├── HealthScore.tsx # Health score display
├── WAFDashboard.tsx # Main WAF dashboard
├── WAF3DView.tsx # 3D WAF visualization
└── WAF2DView.tsx # 2D WAF visualization
```
---
## Future Enhancements
1. **AI Recommendations**: ML-powered optimization suggestions
2. **Predictive Analytics**: Forecast future issues
3. **Automated Remediation**: Auto-fix common issues
4. **Custom Pillars**: User-defined assessment pillars
5. **Compliance Mapping**: Map to specific compliance frameworks
6. **Cost Forecasting**: Predict future costs
7. **Sustainability Metrics**: Enhanced environmental tracking
---
## Best Practices
1. **Start with Overview**: Show high-level health across all pillars
2. **Drill Down Gradually**: Allow users to explore details
3. **Provide Context**: Always show what pillar/lens is active
4. **Make Actions Clear**: Show what can be done with findings
5. **Prioritize**: Highlight critical issues first
6. **Keep It Visual**: Use visuals over text when possible
7. **Enable Comparison**: Compare resources side-by-side
8. **Track Progress**: Show improvement over time