diff --git a/.gitignore b/.gitignore index 8e017c3..28f6844 100644 --- a/.gitignore +++ b/.gitignore @@ -140,3 +140,4 @@ vite.config.ts.timestamp-* /.astro /.vscode .claude/settings.local.json +.mcp.json diff --git a/src/assets/images/architecture/cli/backend-dev-mode.png b/src/assets/images/architecture/cli/backend-dev-mode.png new file mode 100644 index 0000000..585a371 Binary files /dev/null and b/src/assets/images/architecture/cli/backend-dev-mode.png differ diff --git a/src/assets/images/architecture/cli/frontend-dev-mode.png b/src/assets/images/architecture/cli/frontend-dev-mode.png new file mode 100644 index 0000000..da1fc5b Binary files /dev/null and b/src/assets/images/architecture/cli/frontend-dev-mode.png differ diff --git a/src/assets/images/architecture/cli/full-dev-mode.png b/src/assets/images/architecture/cli/full-dev-mode.png new file mode 100644 index 0000000..169a2c3 Binary files /dev/null and b/src/assets/images/architecture/cli/full-dev-mode.png differ diff --git a/src/assets/images/architecture/cli/production-mode.png b/src/assets/images/architecture/cli/production-mode.png new file mode 100644 index 0000000..baf68ad Binary files /dev/null and b/src/assets/images/architecture/cli/production-mode.png differ diff --git a/src/assets/images/architecture/core-backend/layered-architecture.png b/src/assets/images/architecture/core-backend/layered-architecture.png new file mode 100644 index 0000000..fb32604 Binary files /dev/null and b/src/assets/images/architecture/core-backend/layered-architecture.png differ diff --git a/src/assets/images/architecture/data-flow/container-build.png b/src/assets/images/architecture/data-flow/container-build.png new file mode 100644 index 0000000..dc031c9 Binary files /dev/null and b/src/assets/images/architecture/data-flow/container-build.png differ diff --git a/src/assets/images/architecture/data-flow/docker-compose-import.png b/src/assets/images/architecture/data-flow/docker-compose-import.png new file mode 100644 index 0000000..c621202 Binary files /dev/null and b/src/assets/images/architecture/data-flow/docker-compose-import.png differ diff --git a/src/assets/images/architecture/data-flow/node-to-manifest.png b/src/assets/images/architecture/data-flow/node-to-manifest.png new file mode 100644 index 0000000..26969e6 Binary files /dev/null and b/src/assets/images/architecture/data-flow/node-to-manifest.png differ diff --git a/src/assets/images/architecture/data-flow/realtime-monitoring.png b/src/assets/images/architecture/data-flow/realtime-monitoring.png new file mode 100644 index 0000000..b78f2b6 Binary files /dev/null and b/src/assets/images/architecture/data-flow/realtime-monitoring.png differ diff --git a/src/assets/images/architecture/data-flow/workflow-creation.png b/src/assets/images/architecture/data-flow/workflow-creation.png new file mode 100644 index 0000000..bd3ade6 Binary files /dev/null and b/src/assets/images/architecture/data-flow/workflow-creation.png differ diff --git a/src/assets/images/architecture/data-flow/workflow-deployment.png b/src/assets/images/architecture/data-flow/workflow-deployment.png new file mode 100644 index 0000000..fc917b5 Binary files /dev/null and b/src/assets/images/architecture/data-flow/workflow-deployment.png differ diff --git a/src/assets/images/architecture/ecosystem-overview/system-architecture.png b/src/assets/images/architecture/ecosystem-overview/system-architecture.png new file mode 100644 index 0000000..61b99be Binary files /dev/null and b/src/assets/images/architecture/ecosystem-overview/system-architecture.png differ diff --git a/src/assets/images/guides/workflow-lifecycle/state-machine.png b/src/assets/images/guides/workflow-lifecycle/state-machine.png new file mode 100644 index 0000000..7b76209 Binary files /dev/null and b/src/assets/images/guides/workflow-lifecycle/state-machine.png differ diff --git a/src/content/docs/architecture/cli.md b/src/content/docs/architecture/cli.md index e1588fd..8861a1c 100644 --- a/src/content/docs/architecture/cli.md +++ b/src/content/docs/architecture/cli.md @@ -99,16 +99,7 @@ OrchCLI automatically selects the correct Docker Compose file based on which rep All three services run inside Docker using pre-built images from GHCR. -``` -┌───────────────── Docker Network ─────────────────┐ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ MongoDB │◄──│ Core │◄──│ UI │ │ -│ │ :27017 │ │ :3000 │ │ :3001 │ │ -│ └──────────┘ └──────────┘ └──────────┘ │ -│ mongo:8.0 ghcr.io/... ghcr.io/... │ -└──────────────────────────────────────────────────┘ -``` +![Production Mode Architecture](../../../assets/images/architecture/cli/production-mode.png) ### Full Development Mode @@ -117,16 +108,7 @@ All three services run inside Docker using pre-built images from GHCR. Only MongoDB runs in Docker. UI and Core run on the host with hot reload. -``` -┌──────── Host Machine ────────┐ ┌── Docker ──┐ -│ │ │ │ -│ ┌────────┐ ┌────────┐ │ │ ┌────────┐│ -│ │ UI │───►│ Core │───┼──►│ │MongoDB ││ -│ │ :3001 │ │ :3000 │ │ │ │ :27017 ││ -│ └────────┘ └────────┘ │ │ └────────┘│ -│ npm run dev air │ │ │ -└──────────────────────────────┘ └────────────┘ -``` +![Full Development Mode Architecture](../../../assets/images/architecture/cli/full-dev-mode.png) ### Frontend-Only Development @@ -135,16 +117,7 @@ Only MongoDB runs in Docker. UI and Core run on the host with hot reload. UI runs on host, backend services in Docker. Frontend devs don't need Go. -``` -┌─── Host ───┐ ┌────────── Docker Network ──────────┐ -│ │ │ │ -│ ┌────────┐ │ │ ┌──────────┐ ┌──────────┐ │ -│ │ UI │─┼──►│ │ Core │◄──│ MongoDB │ │ -│ │ :3001 │ │ │ │ :3000 │ │ :27017 │ │ -│ └────────┘ │ │ └──────────┘ └──────────┘ │ -│ npm run dev│ │ ghcr.io/... mongo:8.0 │ -└────────────┘ └─────────────────────────────────────┘ -``` +![Frontend-Only Development Mode](../../../assets/images/architecture/cli/frontend-dev-mode.png) ### Backend-Only Development @@ -153,22 +126,7 @@ UI runs on host, backend services in Docker. Frontend devs don't need Go. Everything runs in Docker, but the Core source code is volume-mounted for hot reload via Air. Backend devs don't need Go installed locally. -``` -┌────────────────── Docker Network ──────────────────┐ -│ │ -│ ┌──────────┐ ┌───────────────┐ ┌──────────┐ │ -│ │ MongoDB │◄─│ Core │◄─│ UI │ │ -│ │ :27017 │ │ :3000 │ │ :3001 │ │ -│ └──────────┘ │ (mounted vol) │ └──────────┘ │ -│ │ cosmtrek/air │ ghcr.io/... │ -│ └───────┬───────┘ │ -└────────────────────────┼───────────────────────────┘ - │ volume mount - ┌────┴────┐ - │ Host │ - │ ./core/ │ - └─────────┘ -``` +![Backend-Only Development Mode](../../../assets/images/architecture/cli/backend-dev-mode.png) ## Configuration System diff --git a/src/content/docs/architecture/core-backend.md b/src/content/docs/architecture/core-backend.md index 0026f67..4ae5a43 100644 --- a/src/content/docs/architecture/core-backend.md +++ b/src/content/docs/architecture/core-backend.md @@ -131,30 +131,7 @@ core/ ## Layered Architecture -``` -┌──────────────────────────────────────────────────┐ -│ HTTP Layer │ -│ routes/routes.go → handlers/*_handler.go │ -│ (Gin router) (request/response) │ -├──────────────────────────────────────────────────┤ -│ Middleware Layer │ -│ auth_middleware.go workflow_middleware.go │ -│ (JWT validation) (ownership checks) │ -├──────────────────────────────────────────────────┤ -│ Service Layer │ -│ services/*_service.go │ -│ (Business logic, orchestration) │ -├──────────────────────────────────────────────────┤ -│ Repository Layer │ -│ repositories/*_repository.go │ -│ (MongoDB CRUD operations) │ -├──────────────────────────────────────────────────┤ -│ Infrastructure Layer │ -│ database/mongodb.go pkg/kubernetes/* │ -│ pkg/encryption/* pkg/template/* │ -│ (DB, K8s, crypto) (Template engine) │ -└──────────────────────────────────────────────────┘ -``` +![Layered Backend Architecture](../../../assets/images/architecture/core-backend/layered-architecture.png) ## Key Design Patterns diff --git a/src/content/docs/architecture/data-flow.md b/src/content/docs/architecture/data-flow.md index 5adcfb2..abe78e5 100644 --- a/src/content/docs/architecture/data-flow.md +++ b/src/content/docs/architecture/data-flow.md @@ -11,108 +11,23 @@ This is the primary flow -- a user creates a visual workflow and deploys it to K ### Phase 1: Design -``` -┌─────────┐ ┌────────────────────┐ ┌──────────────┐ -│ User │ │ UI (Canvas) │ │ Core API │ -│ │ │ │ │ │ -│ 1. Create│────►│ POST /workflows │────►│ Save to │ -│ workflow │ │ { name, cluster_id }│ │ MongoDB │ -│ │◄────│ { id, status:draft }│◄────│ │ -│ │ │ │ │ │ -│ 2. Drag │────►│ Add node to React │ │ │ -│ nodes │ │ Flow canvas (local) │ │ │ -│ │ │ │ │ │ -│ 3. Draw │────►│ Add edge between │ │ │ -│ edges │ │ nodes (local) │ │ │ -│ │ │ │ │ │ -│ 4. Edit │────►│ NodeSettingsPanel │ │ │ -│ settings │ │ updates node.data │ │ │ -│ │ │ │ │ │ -│ 5. Save │────►│ POST /workflows/:id │────►│ Update nodes, │ -│ │ │ /save { nodes,edges}│ │ edges in DB │ -└─────────┘ └────────────────────┘ └──────────────┘ -``` +![Workflow Creation - Design Phase](../../../assets/images/architecture/data-flow/workflow-creation.png) ### Phase 2: Deploy -``` -┌─────────┐ ┌──────────────┐ ┌───────────────────┐ ┌──────────┐ -│ User │ │ UI │ │ Core │ │ K8s │ -│ │ │ │ │ │ │ Cluster │ -│ Click │────►│ POST │────►│ 1. Create version │ │ │ -│ "Run" │ │ /workflows/ │ │ snapshot │ │ │ -│ │ │ :id/run │ │ │ │ │ -│ │ │ │ │ 2. For each node: │ │ │ -│ │ │ │ │ a. Load template │ │ │ -│ │ │ │ │ b. Merge data │ │ │ -│ │ │ │ │ c. Render YAML │ │ │ -│ │ │ │ │ d. Apply to K8s ─┼────►│ Create │ -│ │ │ │ │ │ │ resource │ -│ │ │ │ │ 3. Start watchers │◄────┤ Status │ -│ │ │ │ │ for resources │ │ events │ -│ │ │ │ │ │ │ │ -│ See live │◄────│ SSE stream │◄────│ 4. Publish status │ │ │ -│ updates │ │ node_update │ │ via SSE │ │ │ -│ │ │ events │ │ broadcaster │ │ │ -└─────────┘ └──────────────┘ └───────────────────┘ └──────────┘ -``` +![Workflow Deployment Phase](../../../assets/images/architecture/data-flow/workflow-deployment.png) ### Node-to-Manifest Transformation Each visual node is converted to a Kubernetes manifest through the template system: -``` -Canvas Node Template Engine Kubernetes -───────────── ─────────────── ────────── -{ templates/core/ - type: "deployment" deployment/template.yaml - data: { ↓ Go template rendering - name: "web-app" → apiVersion: apps/v1 → kubectl apply - image: "nginx:1.25" kind: Deployment - replicas: 3 metadata: - port: 80 name: web-app - } spec: -} replicas: 3 - template: - spec: - containers: - - name: web-app - image: nginx:1.25 - ports: - - containerPort: 80 -``` +![Transformation Phase](../../../assets/images/architecture/data-flow/node-to-manifest.png) ## Docker Compose Import Flow Users can import existing Docker Compose files to auto-generate workflow nodes. -``` -┌─────────┐ ┌──────────────┐ ┌───────────────────────────────────┐ -│ User │ │ UI │ │ Core │ -│ │ │ │ │ │ -│ Upload │────►│ POST │────►│ 1. Parse docker-compose.yml │ -│ file or │ │ /import/ │ │ (docker_compose_parser.go) │ -│ paste URL│ │ analyze │ │ │ -│ │ │ │ │ 2. For each service: │ -│ │ │ │ │ - Create Deployment node │ -│ │ │ │ │ - Create Service node if ports │ -│ │ │ │ │ - Create ConfigMap for env │ -│ │ │ │ │ - Create PVC for volumes │ -│ │ │ │ │ (node_converter.go) │ -│ │ │ │ │ │ -│ │ │ │ │ 3. Auto-layout nodes │ -│ │ │ │ │ (layout_engine.go) │ -│ │ │ │ │ │ -│ │ │ │ │ 4. Generate edges from │ -│ Preview │◄────│ Show import │◄────│ depends_on relationships │ -│ & adjust │ │ preview with │ │ │ -│ │ │ suggested │ │ │ -│ │ │ nodes/edges │ │ │ -│ │ │ │ │ │ -│ Apply │────►│ POST │────►│ 5. Merge nodes into workflow │ -│ │ │ /import/apply │ │ or create new workflow │ -└─────────┘ └──────────────┘ └───────────────────────────────────┘ -``` +![Docker Compose Import Flow](../../../assets/images/architecture/data-flow/docker-compose-import.png) For Git repository imports, the flow includes an async step where the core clones the repo, detects the compose file, and streams progress via SSE. @@ -120,21 +35,7 @@ For Git repository imports, the flow includes an async step where the core clone Users can build container images from Git repositories using Nixpacks. -``` -┌─────────┐ ┌──────────────┐ ┌────────────────────┐ ┌──────────┐ -│ User │ │ UI │ │ Core │ │ Registry │ -│ │ │ │ │ │ │ │ -│ Start │────►│ POST │────►│ 1. Clone repo │ │ │ -│ build │ │ /builds/start │ │ (git_service) │ │ │ -│ │ │ │ │ │ │ │ -│ │ │ SSE stream │◄────│ 2. Build with │ │ │ -│ See live │◄────│ useBuildStream│ │ Nixpacks │ │ │ -│ logs │ │ hook │ │ (nixpacks_service) │ │ │ -│ │ │ │ │ │ │ │ -│ │ │ │◄────│ 3. Push image ─┼────►│ Store │ -│ Done │◄────│ Build complete│ │ to registry │ │ image │ -└─────────┘ └──────────────┘ └────────────────────┘ └──────────┘ -``` +![Container Build Flow](../../../assets/images/architecture/data-flow/container-build.png) Build status progresses: `pending → cloning → building → pushing → completed/failed` @@ -142,74 +43,29 @@ Build status progresses: `pending → cloning → building → pushing → compl ### Built-in Email/Password -``` -┌─────────┐ ┌──────────────┐ ┌────────────────────┐ ┌──────────┐ -│ User │ │ UI │ │ Core │ │ MongoDB │ -│ │ │ │ │ │ │ │ -│ Register │────►│ POST │────►│ 1. Validate input │ │ │ -│ │ │ /auth/register│ │ 2. Hash password │ │ │ -│ │ │ │ │ (bcrypt cost 12) │ │ │ -│ │ │ │ │ 3. Check if first │────►│ Count │ -│ │ │ │ │ user (→ admin) │◄────│ users │ -│ │ │ │ │ 4. Save user │────►│ Insert │ -│ │ │ │ │ 5. Generate JWT │ │ │ -│ Logged │◄────│ Store token │◄────│ (24h expiry) │ │ │ -│ in │ │ in AuthStore │ │ │ │ │ -└─────────┘ └──────────────┘ └────────────────────┘ └──────────┘ -``` +1. User submits registration/login form +2. Core validates input and hashes password (bcrypt, cost 12) +3. If first user, automatically assigned admin role +4. User saved to MongoDB, JWT generated (24h expiry) +5. UI stores token in Zustand AuthStore (persisted to localStorage) +6. All subsequent requests include `Authorization: Bearer ` +7. Token refresh available via `POST /auth/refresh` (max 7 days) ### OAuth2/OIDC Flow -``` -┌─────────┐ ┌──────┐ ┌──────────┐ ┌───────────┐ ┌──────────┐ -│ User │ │ UI │ │ Core │ │ Provider │ │ MongoDB │ -│ │ │ │ │ │ │ (GitHub, │ │ │ -│ Click │────►│ │────►│ Generate │ │ Authentik)│ │ │ -│ "Login │ │ │ │ state + │────►│ │ │ │ -│ with X" │ │ │ │ redirect │ │ │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ Consent │◄───────────────────────────────────│ Auth page │ │ │ -│ │────►│ │ │ │◄────│ Callback │ │ │ -│ │ │ │ │ │ │ with code │ │ │ -│ │ │ │ │ Exchange │────►│ Token │ │ │ -│ │ │ │ │ code for │◄────│ endpoint │ │ │ -│ │ │ │ │ user info │────►│ Userinfo │ │ │ -│ │ │ │ │ │◄────│ endpoint │ │ │ -│ │ │ │ │ Create/ │────►│ │ │ Upsert │ -│ │ │ │ │ link user │ │ │ │ user │ -│ │ │ │◄────│ Redirect │ │ │ │ │ -│ Logged │◄────│ Token │ │ with code │ │ │ │ │ -│ in │ │ │────►│ Exchange │ │ │ │ │ -│ │ │ Store │◄────│ → JWT │ │ │ │ │ -└─────────┘ └──────┘ └──────────┘ └───────────┘ └──────────┘ -``` +1. User clicks "Login with X" (GitHub, Authentik, etc.) +2. Core generates a state parameter and redirects to the provider's auth page +3. User consents, provider redirects back to Core with an authorization code +4. Core exchanges the code for an access token, then fetches user info from the provider +5. Core creates or links the user account in MongoDB +6. Core redirects to UI with a short-lived authorization code +7. UI exchanges the code for a JWT via `POST /auth/oauth/exchange` ## Real-Time Resource Monitoring After deployment, the core maintains active watchers on Kubernetes resources: -``` -┌────────────────┐ ┌──────────────────────┐ ┌───────────────┐ -│ K8s API Server │ │ Core │ │ UI │ -│ │ │ │ │ │ -│ Watch API │────►│ ResourceWatcher │ │ │ -│ (streaming) │ │ ├── Deployment watch│ │ │ -│ │ │ ├── Pod watch │ │ │ -│ │ │ └── Service watch │ │ │ -│ │ │ │ │ │ │ -│ Event: │────►│ Parse event │ │ │ -│ Pod Ready │ │ │ │ │ │ -│ │ │ ResourceWatcher │ │ │ -│ │ │ Manager │ │ │ -│ │ │ │ │ │ │ -│ │ │ SSEBroadcaster │ │ │ -│ │ │ .Publish({ │────►│ EventSource │ -│ │ │ type: "resource" │ │ onmessage │ -│ │ │ data: { status, │ │ → update │ -│ │ │ replicas, ... } │ │ node state │ -│ │ │ }) │ │ on canvas │ -└────────────────┘ └──────────────────────┘ └───────────────┘ -``` +![Real-Time Resource Monitoring](../../../assets/images/architecture/data-flow/realtime-monitoring.png) ## Version Control Flow diff --git a/src/content/docs/architecture/ecosystem-overview.md b/src/content/docs/architecture/ecosystem-overview.md index 6bb5c2b..c652c01 100644 --- a/src/content/docs/architecture/ecosystem-overview.md +++ b/src/content/docs/architecture/ecosystem-overview.md @@ -7,34 +7,7 @@ KubeOrch is a three-repo platform: a Go backend (core), a Next.js frontend (ui), ## System Architecture -``` - KubeOrch Platform - ┌─────────────────────────────────────────────────────────────────────────┐ - │ │ - │ ┌─────────────────────┐ REST/SSE ┌──────────────────┐ │ - │ │ │ ◄───────────────────────── │ │ │ - │ │ Core Backend │ │ UI Frontend │ │ - │ │ (Go / Gin) │ ─────────────────────────► │ (Next.js 15) │ │ - │ │ Port 3000 │ JSON responses / SSE │ Port 3001 │ │ - │ │ │ │ │ │ - │ └────────┬────────────┘ └──────────────────┘ │ - │ │ │ - │ │ │ - │ ┌────────▼────────────┐ ┌──────────────────────────────────┐ │ - │ │ │ │ │ │ - │ │ MongoDB │ │ Kubernetes Clusters │ │ - │ │ (Persistence) │ │ (via client-go) │ │ - │ │ │ │ │ │ - │ └─────────────────────┘ └──────────────────────────────────┘ │ - │ │ - └──────────────────────────────────────────────┬──────────────────────────┘ - │ - ┌──────────▼──────────┐ - │ orchcli (CLI) │ - │ Docker Compose │ - │ Dev Orchestration │ - └─────────────────────┘ -``` +![KubeOrch Platform System Architecture](../../../assets/images/architecture/ecosystem-overview/system-architecture.png) ## Component Responsibilities diff --git a/src/content/docs/architecture/ui-frontend.md b/src/content/docs/architecture/ui-frontend.md index 49da973..aeb83e7 100644 --- a/src/content/docs/architecture/ui-frontend.md +++ b/src/content/docs/architecture/ui-frontend.md @@ -144,29 +144,16 @@ ui/ The app uses Zustand with a store-per-domain pattern. Some stores use `persist` middleware to survive page reloads via `localStorage`. -``` -┌──────────────────────────────────────────────────────┐ -│ Zustand Stores │ -├──────────────┬───────────────┬────────────────────────┤ -│ AuthStore │ WorkflowStore │ ClusterStore │ -│ (persisted) │ (runtime) │ (partially persisted) │ -│ │ │ │ -│ - token │ - nodeUpdate │ - clusters[] │ -│ - user │ Handler │ - selectedCluster │ -│ - expiresAt │ - secretValues│ - clusterStatuses │ -│ │ - envValues │ - defaultClusterId │ -├──────────────┼───────────────┼────────────────────────┤ -│ ResourceStore│ PluginStore │ RegistryStore │ -│ (persisted) │ (runtime) │ (runtime) │ -│ │ │ │ -│ - viewMode │ - plugins[] │ - registries[] │ -│ - filters │ - categories │ - defaultRegistry │ -├──────────────┼───────────────┼────────────────────────┤ -│ PanelStore │ SidebarStore │ │ -│ (persisted) │ (persisted) │ │ -│ - widths │ - folderState │ │ -└──────────────┴───────────────┴────────────────────────┘ -``` +| Store | Persistence | State | +|-------|-------------|-------| +| **AuthStore** | persisted | `token`, `user`, `expiresAt` | +| **WorkflowStore** | runtime | `nodeUpdateHandler`, `secretValues`, `envValues` | +| **ClusterStore** | partial | `clusters[]`, `selectedCluster`, `clusterStatuses`, `defaultClusterId` | +| **ResourceStore** | persisted | `viewMode`, `filters` | +| **PluginStore** | runtime | `plugins[]`, `categories` | +| **RegistryStore** | runtime | `registries[]`, `defaultRegistry` | +| **PanelStore** | persisted | `widths` | +| **SidebarStore** | persisted | `folderState` | ## API Client Pattern diff --git a/src/content/docs/guides/workflow-lifecycle.md b/src/content/docs/guides/workflow-lifecycle.md index 0aaeb93..c478765 100644 --- a/src/content/docs/guides/workflow-lifecycle.md +++ b/src/content/docs/guides/workflow-lifecycle.md @@ -7,19 +7,7 @@ A workflow in KubeOrch represents a complete Kubernetes application topology -- ## Workflow States -``` - ┌───────┐ Publish ┌───────────┐ Archive ┌──────────┐ - │ Draft │ ──────────────────► │ Published │ ────────────────► │ Archived │ - │ │ ◄────────────────── │ │ ◄──────────────── │ │ - └───────┘ Unpublish └───────────┘ Unarchive └──────────┘ - │ │ - │ Run │ Run - └──────────┬───────────────────┘ - ▼ - ┌──────────┐ - │ Running │──► Completed / Failed - └──────────┘ -``` +![Workflow State Machine](../../../assets/images/guides/workflow-lifecycle/state-machine.png) - **Draft** -- Initial state. Workflow is being designed on the canvas. - **Published** -- Workflow is finalized and ready for deployment.