140 lines
4.8 KiB
Python
140 lines
4.8 KiB
Python
"""Phase 1: Architecture Design Node."""
|
|
|
|
import logging
|
|
from typing import Any, Dict
|
|
from app.states.state import GCPArchitectureState
|
|
from app.skills.loader import SkillLoader
|
|
from app.tools.mcp_developer_knowledge import get_mcp_client
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def design_node(state: GCPArchitectureState, skill_loader: SkillLoader) -> Dict[str, Any]:
|
|
"""Processes Phase 1 Design: select GCP managed products, generate Mermaid graph, and Terraform IaC."""
|
|
logger.info("Executing design_node")
|
|
skill_prompt = skill_loader.format_skills_for_prompt("design")
|
|
|
|
# Developer Knowledge MCP Grounding Search
|
|
mcp_client = get_mcp_client()
|
|
mcp_knowledge = mcp_client.search_documents(query="Cloud Run PubSub event-driven architecture", category="compute")
|
|
docs = mcp_knowledge.get("documents", [])
|
|
citations_str = "\n".join([f"- [{doc['title']}]({doc['uri']})" for doc in docs[:3]]) if docs else "- [Google Cloud Architecture Framework](https://cloud.google.com/architecture/framework)"
|
|
|
|
architecture_doc = f"""# Phase 1 — Architecture & Product Selection
|
|
|
|
## Selected Products
|
|
- **Compute / Serving**: Google Cloud Run (Fully Managed Container Ingress & Stateless Execution)
|
|
- **Messaging & Eventing**: Google Cloud Pub/Sub (Regional Event Bus for Asynchronous Decoupling)
|
|
- **State & Storage**: Google Cloud Storage & Firestore (Database & Bucket Storage for Durable Audit Event Replay)
|
|
- **Security & Identity**: Cloud IAM (Least Privilege Service Accounts) & KMS (Customer-Managed Encryption Keys)
|
|
- **Artifact Registry**: Google Artifact Registry (OCI Container Image Hosting)
|
|
|
|
## Component Responsibilities
|
|
1. **Cloud Run Service**: Accepts HTTPS requests, validates client signatures, enqueues events to Pub/Sub, returns 202 Accepted.
|
|
2. **Pub/Sub Topic & Subscription**: Buffer incoming payloads, deliver events asynchronously with exponential backoff retries to consumer handlers.
|
|
3. **Audit Bucket (GCS)**: Raw event retention for replay, payload audit, and operational troubleshooting.
|
|
|
|
## Security & Compliance
|
|
- HTTPS ingress with TLS 1.3 encryption in transit.
|
|
- Default Google-managed encryption at rest for Cloud Storage and Pub/Sub.
|
|
- Cloud Run service account bound strictly to `roles/pubsub.publisher` and `roles/storage.objectCreator`.
|
|
|
|
## Grounded Documentation Citations (Google Developer Knowledge MCP)
|
|
{citations_str}
|
|
"""
|
|
|
|
mermaid_diagram = """flowchart TD
|
|
Client[External HTTPS Client] -->|HTTPS POST /events| CloudRun[Google Cloud Run Service]
|
|
CloudRun -->|Publish Event| PubSubTopic[Cloud Pub/Sub Topic]
|
|
CloudRun -->|Write Raw Payload| GCSAudit[Cloud Storage Audit Bucket]
|
|
PubSubTopic -->|Push Delivery| EventConsumer[Cloud Run Consumer Service]
|
|
EventConsumer -->|Acknowledge| PubSubTopic
|
|
"""
|
|
|
|
terraform_code = """# Google Cloud Solution Architecture Baseline
|
|
terraform {
|
|
required_version = ">= 1.5.0"
|
|
required_providers {
|
|
google = {
|
|
source = "hashicorp/google"
|
|
version = "~> 5.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
provider "google" {
|
|
project = var.project_id
|
|
region = var.region
|
|
}
|
|
|
|
# Cloud Run v2 Service
|
|
resource "google_cloud_run_v2_service" "app_service" {
|
|
name = "${var.environment}-app-service"
|
|
location = var.region
|
|
|
|
template {
|
|
containers {
|
|
image = var.container_image
|
|
ports {
|
|
container_port = 8080
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Pub/Sub Topic for Event Ingestion
|
|
resource "google_pubsub_topic" "event_ingestion" {
|
|
name = "${var.environment}-event-ingestion-topic"
|
|
labels = {
|
|
environment = var.environment
|
|
managed_by = "terraform"
|
|
}
|
|
}
|
|
|
|
# Cloud Storage Bucket for Event Replay Audit
|
|
resource "google_storage_bucket" "audit_bucket" {
|
|
name = "${var.project_id}-${var.environment}-audit-bucket"
|
|
location = var.region
|
|
force_destroy = false
|
|
uniform_bucket_level_access = true
|
|
|
|
versioning {
|
|
enabled = true
|
|
}
|
|
|
|
lifecycle_rule {
|
|
condition {
|
|
age = 30
|
|
}
|
|
action {
|
|
type = "Delete"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Least-Privilege IAM Service Account
|
|
resource "google_service_account" "ingress_sa" {
|
|
account_id = "${var.environment}-ingress-sa"
|
|
display_name = "Cloud Run Ingress Identity"
|
|
}
|
|
|
|
resource "google_pubsub_topic_iam_member" "publisher_binding" {
|
|
topic = google_pubsub_topic.event_ingestion.name
|
|
role = "roles/pubsub.publisher"
|
|
member = "serviceAccount:${google_service_account.ingress_sa.email}"
|
|
}
|
|
"""
|
|
|
|
active_skills = state.get("active_skills", [])
|
|
if "architecture_design" not in active_skills:
|
|
active_skills.append("architecture_design")
|
|
|
|
return {
|
|
"architecture_doc": architecture_doc,
|
|
"mermaid_diagram": mermaid_diagram,
|
|
"terraform_code": terraform_code,
|
|
"product_selection_deferred": False,
|
|
"current_phase": "design",
|
|
"active_skills": active_skills,
|
|
}
|