mirror of
https://github.com/taylanbakircioglu/flowfish.git
synced 2026-09-12 05:48:55 +00:00
refactor: rename AI Integration Hub to Integration Hub with UX improvements
Made-with: Cursor
This commit is contained in:
@@ -29,7 +29,7 @@ Centralized multi-cluster Kubernetes observability platform — real-time depend
|
||||
- [Change Detection](#change-detection)
|
||||
- [Impact Simulation](#impact-simulation)
|
||||
- [Blast Radius Oracle](#blast-radius-oracle)
|
||||
- [AI Integration Hub](#ai-integration-hub)
|
||||
- [Integration Hub](#integration-hub)
|
||||
- [Pod & Deployment Annotations](#pod--deployment-annotations)
|
||||
- [Activity Monitor](#activity-monitor)
|
||||
- [Events Timeline](#events-timeline)
|
||||
@@ -101,8 +101,8 @@ Unlike traditional APM tools that require agent installation or service meshes t
|
||||
- **Role-Based Access Control** — User and role management with Admin, Viewer, and custom roles with granular permissions
|
||||
- **Multi-Tab Dashboard** — Overview, Operations, Security, Network, Changes, and Workloads tabs with real-time metrics
|
||||
- **CI/CD Pipeline Integration** — Blast radius checks for Azure DevOps, GitHub Actions, Jenkins, and GitLab CI
|
||||
- **AI Integration Hub** — Three-step wizard (Configure → Preview → Integration Code) for dependency data integrations with ready-to-use code snippets for Azure DevOps, GitHub Actions, Jenkins, GitLab CI, Python, JavaScript, and cURL — includes a Blast Radius tab for pre-deployment risk assessment pipeline integration
|
||||
- **Pod & Deployment Annotations** — Full annotation support including automatic merge of Deployment/StatefulSet annotations into pods, visible across Map, Network Explorer, Application Inventory, Impact Simulation, and AI Integration Hub
|
||||
- **Integration Hub** — Four-step wizard (Integration Type → Configure → Preview → Integration Code) for dependency data and blast radius gate integrations with ready-to-use code snippets for Azure DevOps, GitHub Actions, Jenkins, GitLab CI, Python, JavaScript, and cURL
|
||||
- **Pod & Deployment Annotations** — Full annotation support including automatic merge of Deployment/StatefulSet annotations into pods, visible across Map, Network Explorer, Application Inventory, Impact Simulation, and Integration Hub
|
||||
- **API Key Management** — Generate, expire, and revoke API keys for secure programmatic access alongside JWT authentication
|
||||
|
||||
---
|
||||
@@ -251,9 +251,9 @@ The analysis wizard guides you through creating a new eBPF data collection sessi
|
||||
|
||||

|
||||
|
||||
**AI Integration Hub** — Three-step wizard for dependency data integrations. Configure analysis scope and service identification method, preview dependency results with upstream/downstream statistics, and generate ready-to-use code snippets (Pipeline YAML, cURL, Python, JavaScript) with a dedicated Blast Radius tab for pre-deployment risk assessment:
|
||||
**Integration Hub** — Four-step wizard for dependency data and blast radius gate integrations. Select integration type, configure analysis scope and service identification method, preview dependency results with upstream/downstream statistics, and generate ready-to-use code snippets (Pipeline YAML, cURL, Python, JavaScript):
|
||||
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
@@ -644,7 +644,7 @@ The Blast Radius Oracle provides a **pre-deployment impact assessment API** desi
|
||||
```yaml
|
||||
- script: |
|
||||
RESULT=$(curl -s -X POST "$(FLOWFISH_URL)/api/v1/blast-radius/assess" \
|
||||
-H "Authorization: Bearer $(FLOWFISH_TOKEN)" \
|
||||
-H "X-API-Key: $(FLOWFISH_API_KEY)" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"cluster_id": $(CLUSTER_ID), "change": {"type": "image_update", "target": "payment-service", "namespace": "production"}}')
|
||||
echo "Risk Score: $(echo $RESULT | jq '.risk_score')"
|
||||
@@ -657,7 +657,7 @@ The Blast Radius Oracle provides a **pre-deployment impact assessment API** desi
|
||||
- name: Blast Radius Check
|
||||
run: |
|
||||
RESULT=$(curl -s -X POST "${{ secrets.FLOWFISH_URL }}/api/v1/blast-radius/assess" \
|
||||
-H "Authorization: Bearer ${{ secrets.FLOWFISH_TOKEN }}" \
|
||||
-H "X-API-Key: ${{ secrets.FLOWFISH_API_KEY }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"cluster_id": ${{ env.CLUSTER_ID }}, "change": {"type": "image_update", "target": "payment-service", "namespace": "production"}}')
|
||||
echo "Risk: $(echo $RESULT | jq -r '.risk_level')"
|
||||
@@ -671,7 +671,7 @@ stage('Blast Radius Check') {
|
||||
def result = httpRequest(
|
||||
url: "${FLOWFISH_URL}/api/v1/blast-radius/assess",
|
||||
httpMode: 'POST',
|
||||
customHeaders: [[name: 'Authorization', value: "Bearer ${FLOWFISH_TOKEN}"]],
|
||||
customHeaders: [[name: 'X-API-Key', value: "${FLOWFISH_API_KEY}"]],
|
||||
requestBody: '{"cluster_id": ' + CLUSTER_ID + ', "change": {"type": "image_update", "target": "payment-service", "namespace": "production"}}'
|
||||
)
|
||||
def json = readJSON text: result.content
|
||||
@@ -691,13 +691,13 @@ The UI includes a live test runner for ad-hoc assessments: select cluster, analy
|
||||
|
||||
Full history of all assessments with assessment ID, timestamp, target, namespace, change type, risk score, risk level, affected count, and pipeline source. Click any entry for detailed JSON view.
|
||||
|
||||
The Overview tab also includes a cross-link to the **AI Integration Hub** for users who need dependency data integrations alongside blast radius assessments.
|
||||
The Overview tab also includes a cross-link to the **Integration Hub** for users who need dependency data integrations alongside blast radius assessments.
|
||||
|
||||
---
|
||||
|
||||
### AI Integration Hub
|
||||
### Integration Hub
|
||||
|
||||
The AI Integration Hub provides a **three-step guided wizard** (Configure → Preview → Integration Code) for setting up dependency data integrations with AI code agents and CI/CD pipelines. It enables cross-project impact analysis by exposing Flowfish dependency data through a compact, categorized JSON API. The wizard also includes a Blast Radius tab for generating pre-deployment risk assessment pipeline snippets, with a cross-link to the Blast Radius Oracle page for interactive testing.
|
||||
The Integration Hub provides a **four-step guided wizard** (Integration Type → Configure → Preview → Integration Code) for setting up CI/CD pipeline integrations. Users choose between two integration types: **Dependency Analysis** for cross-project impact analysis via categorized dependency data, or **Blast Radius Gate** for pre-deployment risk scoring. The wizard generates ready-to-use pipeline snippets for all major CI/CD platforms with consistent `X-API-Key` authentication.
|
||||
|
||||
#### Use Case: Cross-Project Impact Analysis
|
||||
|
||||
@@ -763,7 +763,7 @@ Annotations are visible across:
|
||||
- **Application Inventory** — Searchable annotation column with expandable detail view
|
||||
- **Network Explorer** — Metadata column with annotations included in CSV exports
|
||||
- **Impact Simulation** — Affected service annotations in results and exports
|
||||
- **AI Integration Hub** — Annotations exposed in dependency summary API responses
|
||||
- **Integration Hub** — Annotations exposed in dependency summary API responses
|
||||
|
||||
Internal Kubernetes annotations (`kubectl.kubernetes.io/`, `kubernetes.io/`, `openshift.io/` prefixes) are filtered during ingestion to reduce noise, and values exceeding 500 characters are excluded.
|
||||
|
||||
@@ -1556,7 +1556,7 @@ Interactive docs at `http://localhost:8000/api/docs` (Swagger) or `http://localh
|
||||
| **Analyses** | `/api/v1/analyses` | Create, start, stop, delete analyses |
|
||||
| **Dependencies** | `/api/v1/dependencies` | Graph queries, upstream/downstream |
|
||||
| **Communications** | `/api/v1/communications` | Network flow data |
|
||||
| **AI Integration** | `/api/v1/communications/dependencies/*` | Dependency summary, stream, batch, diff, and impact for AI agents and CI/CD pipelines |
|
||||
| **Integration** | `/api/v1/communications/dependencies/*` | Dependency summary, stream, batch, diff, and impact for CI/CD pipelines |
|
||||
| **Changes** | `/api/v1/changes` | Change detection events |
|
||||
| **Blast Radius** | `/api/v1/blast-radius` | Pre-deployment assessment |
|
||||
| **Simulation** | `/api/v1/simulation` | Impact simulation |
|
||||
|
||||
+10
-10
@@ -12,7 +12,7 @@ info:
|
||||
- **Real-Time Dependency Map** — Live visualization of service dependency graphs
|
||||
- **Anomaly Detection** — Intelligent anomaly detection powered by statistical analysis
|
||||
- **Multi-Cluster** — Manage multiple clusters from a single interface
|
||||
- **AI Integration** — Dependency intelligence APIs for AI agents and CI/CD pipeline integration
|
||||
- **Integration** — Dependency intelligence APIs for CI/CD pipeline integration
|
||||
- **Pod & Deployment Annotations** — Rich metadata enrichment including annotations merged from owning Deployments/StatefulSets
|
||||
- **Import/Export** — Data import and export in multiple formats
|
||||
|
||||
@@ -57,8 +57,8 @@ tags:
|
||||
description: Kubernetes workload inventory (Pod, Deployment, Service, StatefulSet) with labels and annotations
|
||||
- name: Communications
|
||||
description: Service-to-service communication records and dependency graphs
|
||||
- name: AI Integration
|
||||
description: Dependency intelligence APIs for AI agents and CI/CD pipeline integrations — dependency discovery, impact analysis, and cross-project dependency mapping
|
||||
- name: Integration
|
||||
description: Dependency intelligence APIs for CI/CD pipeline integrations — dependency discovery, impact analysis, and cross-project dependency mapping
|
||||
- name: Dependencies
|
||||
description: Dependency map and graph queries
|
||||
- name: Anomalies
|
||||
@@ -1231,7 +1231,7 @@ paths:
|
||||
/communications/dependencies/stream:
|
||||
get:
|
||||
tags:
|
||||
- AI Integration
|
||||
- Integration
|
||||
- Communications
|
||||
summary: Get pod dependencies as upstream/downstream
|
||||
description: |
|
||||
@@ -1340,7 +1340,7 @@ paths:
|
||||
/communications/dependencies/batch:
|
||||
post:
|
||||
tags:
|
||||
- AI Integration
|
||||
- Integration
|
||||
- Communications
|
||||
summary: Batch query dependencies for multiple services
|
||||
requestBody:
|
||||
@@ -1360,7 +1360,7 @@ paths:
|
||||
/communications/dependencies/diff:
|
||||
get:
|
||||
tags:
|
||||
- AI Integration
|
||||
- Integration
|
||||
- Communications
|
||||
summary: Get dependency diff between two analyses
|
||||
parameters:
|
||||
@@ -1401,7 +1401,7 @@ paths:
|
||||
/communications/dependencies/impact:
|
||||
get:
|
||||
tags:
|
||||
- AI Integration
|
||||
- Integration
|
||||
- Communications
|
||||
summary: Dependency impact analysis by change type
|
||||
parameters:
|
||||
@@ -1469,10 +1469,10 @@ paths:
|
||||
/communications/dependencies/summary:
|
||||
get:
|
||||
tags:
|
||||
- AI Integration
|
||||
summary: AI-agent-friendly dependency summary grouped by category
|
||||
- Integration
|
||||
summary: Dependency summary grouped by category for CI/CD integration
|
||||
description: |
|
||||
Returns a compact, grouped dependency summary for AI agents and CI/CD pipelines.
|
||||
Returns a compact, grouped dependency summary for CI/CD pipelines and automation.
|
||||
Dependencies are grouped by service_category. Annotations and labels are prominently
|
||||
exposed for cross-project impact analysis (e.g. git-repo URLs, team info).
|
||||
Requires at least one analysis_id and one search parameter.
|
||||
|
||||
+1
-1
@@ -200,7 +200,7 @@ openapi_tags = [
|
||||
{"name": "Analyses", "description": "Traffic analysis creation, lifecycle, and run management"},
|
||||
{"name": "Workloads", "description": "Kubernetes workload inventory and metadata"},
|
||||
{"name": "Communications", "description": "Service-to-service communication graph, dependency map, and topology"},
|
||||
{"name": "AI Integration", "description": "AI agent and CI/CD pipeline integration endpoints for dependency discovery, impact analysis, and cross-project dependency mapping"},
|
||||
{"name": "Integration", "description": "CI/CD pipeline integration endpoints for dependency discovery, impact analysis, and cross-project dependency mapping"},
|
||||
{"name": "Impact Analysis", "description": "Blast radius assessment, impact simulation, and pre-deployment risk evaluation"},
|
||||
{"name": "Events", "description": "eBPF event statistics, queries, and timeline"},
|
||||
{"name": "Changes", "description": "Change detection and infrastructure drift tracking"},
|
||||
|
||||
@@ -1351,7 +1351,7 @@ async def _get_neo4j_error_stats(
|
||||
)
|
||||
|
||||
|
||||
@router.get("/dependencies/stream", tags=["AI Integration"])
|
||||
@router.get("/dependencies/stream", tags=["Integration"])
|
||||
async def find_pod_dependencies(
|
||||
analysis_id: Optional[int] = Query(None, description="Analysis ID for scope"),
|
||||
cluster_id: Optional[int] = Query(None, description="Cluster ID for scope"),
|
||||
@@ -1431,7 +1431,7 @@ async def find_pod_dependencies(
|
||||
)
|
||||
|
||||
|
||||
@router.post("/dependencies/batch", tags=["AI Integration"])
|
||||
@router.post("/dependencies/batch", tags=["Integration"])
|
||||
async def batch_find_dependencies(
|
||||
request: dict,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
@@ -1452,7 +1452,7 @@ async def batch_find_dependencies(
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/dependencies/diff", tags=["AI Integration"])
|
||||
@router.get("/dependencies/diff", tags=["Integration"])
|
||||
async def diff_dependencies(
|
||||
analysis_id_before: str = Query(..., description="Analysis ID before"),
|
||||
analysis_id_after: str = Query(..., description="Analysis ID after"),
|
||||
@@ -1491,7 +1491,7 @@ async def diff_dependencies(
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/dependencies/summary", tags=["AI Integration"])
|
||||
@router.get("/dependencies/summary", tags=["Integration"])
|
||||
async def get_dependency_summary(
|
||||
analysis_ids: List[int] = Query(..., description="Analysis IDs (required, at least one)"),
|
||||
cluster_id: Optional[int] = Query(None, description="Cluster ID"),
|
||||
@@ -1549,7 +1549,7 @@ async def get_dependency_summary(
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/dependencies/impact", tags=["AI Integration"])
|
||||
@router.get("/dependencies/impact", tags=["Integration"])
|
||||
async def get_dependency_impact(
|
||||
analysis_id: Optional[int] = Query(None, description="Analysis ID"),
|
||||
cluster_id: Optional[int] = Query(None, description="Cluster ID"),
|
||||
|
||||
@@ -1255,8 +1255,8 @@ Range: 0-100
|
||||
- Security events
|
||||
- Audit events
|
||||
|
||||
### 2.10. AI Integration Hub
|
||||
- Three-step guided wizard (Configure → Preview → Integration Code) for dependency data integrations
|
||||
### 2.10. Integration Hub
|
||||
- Four-step guided wizard (Integration Type → Configure → Preview → Integration Code) with two integration paths: Dependency Analysis and Blast Radius Gate
|
||||
- Configure step: analysis selection, service identification method (Annotation, Label, Namespace + Deployment, Pod Name, Advanced), search depth, live test query
|
||||
- Preview step: dependency summary with upstream service metadata, downstream/caller statistics, matched services table
|
||||
- Integration Code step: tabbed snippet generation (Pipeline YAML, cURL, Python, JavaScript, Blast Radius)
|
||||
@@ -2105,7 +2105,7 @@ Would you like me to create rollback CR?
|
||||
| **Authentication** | ✅ OAuth/SSO, K8s SA | ✅ | ✅ |
|
||||
| **API Key Management** | ✅ | ✅ | ✅ |
|
||||
| **Pod & Deployment Annotations** | ✅ | ✅ | ✅ |
|
||||
| **AI Integration Hub** | ❌ | ✅ | ✅ |
|
||||
| **Integration Hub** | ❌ | ✅ | ✅ |
|
||||
| **Multi-Cluster** | ❌ | ✅ | ✅ |
|
||||
| **Change Detection** | ❌ | ✅ | ✅ |
|
||||
| **Anomaly Detection** | ❌ | ✅ LLM | ✅ LLM + ML models |
|
||||
|
||||
@@ -877,7 +877,7 @@ frontend/
|
||||
│ │ ├── PolicySimulation.tsx
|
||||
│ │ ├── UserManagement.tsx
|
||||
│ │ ├── Settings.tsx
|
||||
│ │ └── Integrations.tsx
|
||||
│ │ └── IntegrationHub.tsx
|
||||
│ ├── store/ # Redux store
|
||||
│ │ ├── index.ts
|
||||
│ │ ├── slices/
|
||||
@@ -978,7 +978,7 @@ frontend/
|
||||
|
||||
The HTTP API is organized under `/api/v1/` (see the endpoint tree under **Backend API (FastAPI)** above). **Authentication** supports both **JWT** (standard Bearer tokens) and **API keys** supplied via the **`X-API-Key`** header, so automation, agents, and CI/CD can authenticate without an interactive login flow.
|
||||
|
||||
**AI Integration** exposes dependency-oriented endpoints for AI agents and CI/CD pipelines (tagged **AI Integration** in the OpenAPI spec), including:
|
||||
**Integration** exposes dependency-oriented endpoints for CI/CD pipelines (tagged **Integration** in the OpenAPI spec), including:
|
||||
|
||||
| Area | Path (relative to `/api/v1`) |
|
||||
|------|------------------------------|
|
||||
|
||||
@@ -24,7 +24,7 @@ import Settings from './pages/Settings';
|
||||
import UserManagement from './pages/UserManagement';
|
||||
import BlastRadiusOracle from './pages/BlastRadiusOracle';
|
||||
import APIDocumentation from './pages/APIDocumentation';
|
||||
import AIIntegrationHub from './pages/AIIntegrationHub';
|
||||
import IntegrationHub from './pages/IntegrationHub';
|
||||
|
||||
// Build Timestamp forces unique webpack hash on each build
|
||||
const BUILD_TIMESTAMP = process.env.REACT_APP_BUILD_TIMESTAMP || 'dev';
|
||||
@@ -76,8 +76,9 @@ const App: React.FC = () => {
|
||||
<Route path="impact/simulation" element={<ImpactSimulation />} />
|
||||
<Route path="impact/blast-radius" element={<BlastRadiusOracle />} />
|
||||
|
||||
{/* AI Integration routes */}
|
||||
<Route path="integration/ai-hub" element={<AIIntegrationHub />} />
|
||||
{/* Integration routes */}
|
||||
<Route path="integration/hub" element={<IntegrationHub />} />
|
||||
<Route path="integration/ai-hub" element={<Navigate to="/integration/hub" replace />} />
|
||||
|
||||
{/* Observability routes */}
|
||||
<Route path="observability/activity" element={<ActivityMonitor />} />
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
RadarChartOutlined,
|
||||
AlertOutlined,
|
||||
RocketOutlined,
|
||||
RobotOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import FlowfishLogo from '../FlowfishLogo';
|
||||
import type { MenuProps } from 'antd';
|
||||
@@ -98,13 +97,13 @@ const Sidebar: React.FC<SidebarProps> = ({ collapsed }) => {
|
||||
},
|
||||
{
|
||||
key: 'integration',
|
||||
icon: <RobotOutlined />,
|
||||
label: 'AI Integration',
|
||||
icon: <ApiOutlined />,
|
||||
label: 'Integration',
|
||||
children: [
|
||||
{
|
||||
key: '/integration/ai-hub',
|
||||
label: 'AI Integration Hub',
|
||||
onClick: () => navigate('/integration/ai-hub'),
|
||||
key: '/integration/hub',
|
||||
label: 'Integration Hub',
|
||||
onClick: () => navigate('/integration/hub'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -55,5 +55,5 @@ export const ROUTES = {
|
||||
ANALYSIS_WIZARD: '/analysis/wizard',
|
||||
DEPENDENCY_MAP: '/discovery/map',
|
||||
CLUSTER_MANAGEMENT: '/management/clusters',
|
||||
AI_INTEGRATION_HUB: '/integration/ai-hub',
|
||||
INTEGRATION_HUB: '/integration/hub',
|
||||
} as const;
|
||||
|
||||
@@ -171,7 +171,7 @@ curl -s -f -H "X-API-Key: fk_your_api_key_here" \\
|
||||
curl -X GET "${baseUrl}/api/v1/clusters" \\
|
||||
-H "Authorization: Bearer eyJhbGciOiJIUz..."
|
||||
|
||||
# Example: Get dependency summary (AI Integration)
|
||||
# Example: Get dependency summary (Integration)
|
||||
curl -s -f -H "X-API-Key: fk_your_api_key" \\
|
||||
"${baseUrl}/api/v1/communications/dependencies/summary?analysis_ids=1&namespace=production"
|
||||
|
||||
@@ -194,7 +194,7 @@ curl -X GET "${baseUrl}/api/v1/communications/graph?cluster_id=1" \\
|
||||
<li><Text strong>Workloads</Text> - Kubernetes workload inventory and metadata</li>
|
||||
<li><Text strong>Analyses</Text> - Traffic analysis creation, scheduling, and lifecycle</li>
|
||||
<li><Text strong>Communications</Text> - Service-to-service communication and dependency graphs</li>
|
||||
<li><Text strong>AI Integration</Text> - Dependency discovery, impact analysis, and CI/CD pipeline integration endpoints</li>
|
||||
<li><Text strong>Integration</Text> - Dependency discovery, impact analysis, and CI/CD pipeline integration endpoints</li>
|
||||
<li><Text strong>Events & Event Types</Text> - eBPF event statistics, queries, and type definitions</li>
|
||||
<li><Text strong>Changes</Text> - Change detection and infrastructure drift tracking</li>
|
||||
<li><Text strong>Simulation & Blast Radius</Text> - Impact simulation and pre-deployment assessment</li>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,8 @@ import {
|
||||
theme,
|
||||
} from 'antd';
|
||||
import {
|
||||
RobotOutlined,
|
||||
ApiOutlined,
|
||||
BranchesOutlined,
|
||||
CodeOutlined,
|
||||
CheckCircleOutlined,
|
||||
ArrowLeftOutlined,
|
||||
@@ -63,9 +64,29 @@ import {
|
||||
const { Text, Title, Paragraph } = Typography;
|
||||
const { Option } = Select;
|
||||
|
||||
const AIIntegrationHub: React.FC = () => {
|
||||
type IntegrationType = 'dependency' | 'blast_radius' | null;
|
||||
|
||||
const EXAMPLE_BR_RESPONSE = `{
|
||||
"assessment_id": "br-20260327-abc123",
|
||||
"risk_score": 42,
|
||||
"risk_level": "medium",
|
||||
"blast_radius": {
|
||||
"total_affected": 8,
|
||||
"direct_dependencies": 3,
|
||||
"indirect_dependencies": 5,
|
||||
"critical_services": ["checkout-service"]
|
||||
},
|
||||
"recommendation": "proceed",
|
||||
"suggested_actions": [
|
||||
{ "action": "Notify checkout-service team", "priority": "medium" }
|
||||
],
|
||||
"advisory_only": true
|
||||
}`;
|
||||
|
||||
const IntegrationHub: React.FC = () => {
|
||||
const { token } = theme.useToken();
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [integrationType, setIntegrationType] = useState<IntegrationType>(null);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const [selectedAnalysisIds, setSelectedAnalysisIds] = useState<number[]>([]);
|
||||
@@ -73,6 +94,10 @@ const AIIntegrationHub: React.FC = () => {
|
||||
const [idMethod, setIdMethod] = useState('annotation');
|
||||
const [depth, setDepth] = useState(1);
|
||||
|
||||
// Blast Radius Gate flow state
|
||||
const [brTargetService, setBrTargetService] = useState('');
|
||||
const [brTargetNamespace, setBrTargetNamespace] = useState('');
|
||||
|
||||
const [triggerSummary, { data: rawSummaryData, isFetching: summaryLoading, error: rawSummaryError }] =
|
||||
useLazyGetDependencySummaryQuery();
|
||||
const [summaryParams, setSummaryParams] = useState<DependencySummaryParams | null>(null);
|
||||
@@ -91,6 +116,8 @@ const AIIntegrationHub: React.FC = () => {
|
||||
const urlAnnotationKey = searchParams.get('annotation_key');
|
||||
const urlAnnotationValue = searchParams.get('annotation_value');
|
||||
if (urlOwner || urlNs || urlAnnotationKey) {
|
||||
setIntegrationType('dependency');
|
||||
setCurrentStep(1);
|
||||
if (urlAnnotationKey) setIdMethod('annotation');
|
||||
else if (urlOwner || urlNs) setIdMethod('namespace_deployment');
|
||||
setTimeout(() => {
|
||||
@@ -132,7 +159,7 @@ const AIIntegrationHub: React.FC = () => {
|
||||
return raw;
|
||||
}, [summaryError, summaryData]);
|
||||
|
||||
const canProceedStep0 = selectedAnalysisIds.length > 0;
|
||||
const canProceedConfigure = selectedAnalysisIds.length > 0;
|
||||
|
||||
const buildParamsFromForm = useCallback((): DependencySummaryParams | null => {
|
||||
const values = form.getFieldsValue();
|
||||
@@ -180,7 +207,7 @@ const AIIntegrationHub: React.FC = () => {
|
||||
return;
|
||||
}
|
||||
setSummaryParams(params);
|
||||
setCurrentStep(2);
|
||||
setCurrentStep(3);
|
||||
}, [selectedAnalysisIds, buildParamsFromForm]);
|
||||
|
||||
const responseSize = useMemo(() => {
|
||||
@@ -191,15 +218,85 @@ const AIIntegrationHub: React.FC = () => {
|
||||
const contextNamespace = summaryParams?.namespace;
|
||||
const contextOwnerName = summaryParams?.owner_name;
|
||||
|
||||
const handleSelectType = (type: IntegrationType) => {
|
||||
setIntegrationType(type);
|
||||
setCurrentStep(1);
|
||||
};
|
||||
|
||||
const handleBackToTypeSelection = () => {
|
||||
setIntegrationType(null);
|
||||
setCurrentStep(0);
|
||||
setBrTargetService('');
|
||||
setBrTargetNamespace('');
|
||||
resetSummary();
|
||||
};
|
||||
|
||||
const depSteps = [
|
||||
{ title: 'Integration Type', icon: <ApiOutlined /> },
|
||||
{ title: 'Configure', icon: <ExperimentOutlined /> },
|
||||
{ title: 'Preview', icon: <EyeOutlined /> },
|
||||
{ title: 'Integration Code', icon: <CodeOutlined /> },
|
||||
];
|
||||
|
||||
const brSteps = [
|
||||
{ title: 'Integration Type', icon: <ApiOutlined /> },
|
||||
{ title: 'Configure', icon: <ExperimentOutlined /> },
|
||||
{ title: 'Integration Code', icon: <CodeOutlined /> },
|
||||
];
|
||||
|
||||
const activeSteps = integrationType === 'blast_radius' ? brSteps : depSteps;
|
||||
|
||||
const handleStepClick = (n: number) => {
|
||||
if (n === 0) {
|
||||
handleBackToTypeSelection();
|
||||
return;
|
||||
}
|
||||
if (n < currentStep) {
|
||||
setCurrentStep(n);
|
||||
return;
|
||||
}
|
||||
if (integrationType === 'dependency') {
|
||||
if (n === 2 && summaryData?.success) setCurrentStep(n);
|
||||
else if (n === 3 && (summaryData?.success || summaryParams)) setCurrentStep(n);
|
||||
}
|
||||
if (integrationType === 'blast_radius') {
|
||||
if (n === 2) setCurrentStep(n);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── Shared auth card ───
|
||||
const authCard = (
|
||||
<Card
|
||||
title={<span><KeyOutlined /> Authentication</span>}
|
||||
size="small"
|
||||
style={{ marginTop: 16 }}
|
||||
>
|
||||
<Paragraph>
|
||||
All API calls require authentication via <Text strong>API Key</Text>. Include the header <Text code>X-API-Key: fk_your_key</Text> in every request.
|
||||
</Paragraph>
|
||||
<ol>
|
||||
<li>Go to <Link to="/settings"><Text strong>Settings</Text></Link> and open the <Text strong>API Keys</Text> tab</li>
|
||||
<li>Click <Text strong>Generate New API Key</Text> and give it a descriptive name (e.g. "azure-devops-pipeline")</li>
|
||||
<li>Copy the generated key (starts with <Text code>fk_</Text>) and store it securely in your CI/CD platform's secrets/variables</li>
|
||||
</ol>
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
message="API keys provide full API access. Store them as encrypted secrets in your pipeline platform, never in source code."
|
||||
style={{ marginTop: 8 }}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: 1100, margin: '0 auto' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
||||
<div>
|
||||
<Title level={2} style={{ marginBottom: 4 }}>
|
||||
<RobotOutlined /> AI Integration Hub
|
||||
<ApiOutlined /> Integration Hub
|
||||
</Title>
|
||||
<Paragraph type="secondary" style={{ marginBottom: 0 }}>
|
||||
Set up CI/CD pipeline and AI agent integrations with Flowfish dependency and impact data.
|
||||
Set up CI/CD pipeline integrations with Flowfish dependency and impact data.
|
||||
</Paragraph>
|
||||
</div>
|
||||
<Link to="/discovery/map">
|
||||
@@ -207,24 +304,104 @@ const AIIntegrationHub: React.FC = () => {
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<Card style={{ marginBottom: 16 }}>
|
||||
<Steps
|
||||
current={currentStep}
|
||||
onChange={(n) => {
|
||||
if (n < currentStep) setCurrentStep(n);
|
||||
else if (n === 1 && summaryData?.success) setCurrentStep(n);
|
||||
else if (n === 2 && (summaryData?.success || summaryParams)) setCurrentStep(n);
|
||||
}}
|
||||
items={[
|
||||
{ title: 'Configure', icon: <ExperimentOutlined /> },
|
||||
{ title: 'Preview', icon: <EyeOutlined /> },
|
||||
{ title: 'Integration Code', icon: <CodeOutlined /> },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
{integrationType && (
|
||||
<Card style={{ marginBottom: 16 }}>
|
||||
<Steps
|
||||
current={currentStep}
|
||||
onChange={handleStepClick}
|
||||
items={activeSteps}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* ─── Step 0: Configure ─── */}
|
||||
{/* ═══════════════════════════════════════════════════════════ */}
|
||||
{/* Step 0: Integration Type Selection */}
|
||||
{/* ═══════════════════════════════════════════════════════════ */}
|
||||
{currentStep === 0 && (
|
||||
<Row gutter={24} style={{ marginTop: 8 }}>
|
||||
<Col xs={24} md={12}>
|
||||
<Card
|
||||
hoverable
|
||||
onClick={() => handleSelectType('dependency')}
|
||||
style={{
|
||||
height: '100%',
|
||||
borderColor: token.colorPrimary,
|
||||
cursor: 'pointer',
|
||||
transition: 'box-shadow 0.2s',
|
||||
}}
|
||||
styles={{ body: { padding: 24 } }}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 }}>
|
||||
<div style={{
|
||||
width: 48, height: 48, borderRadius: 12,
|
||||
background: `${token.colorPrimary}15`,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
<BranchesOutlined style={{ fontSize: 24, color: token.colorPrimary }} />
|
||||
</div>
|
||||
<div>
|
||||
<Text strong style={{ fontSize: 16 }}>Dependency Analysis</Text>
|
||||
<Tag color="blue" style={{ marginLeft: 8 }}>Most Common</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<Paragraph type="secondary" style={{ marginBottom: 12 }}>
|
||||
Expose cross-service dependency data to CI/CD pipelines. Identify affected repositories, critical services, and downstream impact chains.
|
||||
</Paragraph>
|
||||
<ul style={{ margin: 0, paddingLeft: 20, color: token.colorTextSecondary, fontSize: 13 }}>
|
||||
<li>Multi-analysis scope with 5 identification methods</li>
|
||||
<li>Live preview with downstream/caller categorization</li>
|
||||
<li>Pipeline YAML, curl, Python, and JavaScript snippets</li>
|
||||
<li>Git-repo annotation extraction for cross-project impact</li>
|
||||
</ul>
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Button type="primary" icon={<ArrowRightOutlined />}>Get Started</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={24} md={12}>
|
||||
<Card
|
||||
hoverable
|
||||
onClick={() => handleSelectType('blast_radius')}
|
||||
style={{
|
||||
height: '100%',
|
||||
cursor: 'pointer',
|
||||
transition: 'box-shadow 0.2s',
|
||||
}}
|
||||
styles={{ body: { padding: 24 } }}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 }}>
|
||||
<div style={{
|
||||
width: 48, height: 48, borderRadius: 12,
|
||||
background: `${token.colorWarning}15`,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
<ThunderboltOutlined style={{ fontSize: 24, color: token.colorWarning }} />
|
||||
</div>
|
||||
<Text strong style={{ fontSize: 16 }}>Blast Radius Gate</Text>
|
||||
</div>
|
||||
<Paragraph type="secondary" style={{ marginBottom: 12 }}>
|
||||
Add pre-deployment risk scoring to your CI/CD pipeline. Get automated risk assessments, affected service counts, and actionable recommendations.
|
||||
</Paragraph>
|
||||
<ul style={{ margin: 0, paddingLeft: 20, color: token.colorTextSecondary, fontSize: 13 }}>
|
||||
<li>Risk score (0-100) with level classification</li>
|
||||
<li>Blast radius: direct, indirect, and critical services</li>
|
||||
<li>Advisory-only — Flowfish never blocks deployments</li>
|
||||
<li>Pipeline snippets for all major CI/CD platforms</li>
|
||||
</ul>
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Button icon={<ArrowRightOutlined />}>Get Started</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
|
||||
{/* ═══════════════════════════════════════════════════════════ */}
|
||||
{/* DEPENDENCY ANALYSIS FLOW (Steps 1-3) */}
|
||||
{/* ═══════════════════════════════════════════════════════════ */}
|
||||
|
||||
{/* ─── Dep Step 1: Configure ─── */}
|
||||
{integrationType === 'dependency' && currentStep === 1 && (
|
||||
<Card title="Analysis Scope & Service Identification">
|
||||
<Form.Item label="Analysis (required, multi-select)" required>
|
||||
<Select
|
||||
@@ -376,7 +553,7 @@ const AIIntegrationHub: React.FC = () => {
|
||||
icon={<ExperimentOutlined />}
|
||||
onClick={onTestQuery}
|
||||
loading={summaryLoading}
|
||||
disabled={!canProceedStep0}
|
||||
disabled={!canProceedConfigure}
|
||||
>
|
||||
Test Query
|
||||
</Button>
|
||||
@@ -407,26 +584,31 @@ const AIIntegrationHub: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', marginTop: 24, gap: 8 }}>
|
||||
{!summaryData?.success && (
|
||||
<Button onClick={onSkipToSetup} disabled={!canProceedStep0}>
|
||||
Skip to Integration Code <ArrowRightOutlined />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<ArrowRightOutlined />}
|
||||
disabled={!summaryData?.success}
|
||||
onClick={() => setCurrentStep(1)}
|
||||
>
|
||||
Preview Results
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 24 }}>
|
||||
<Button icon={<ArrowLeftOutlined />} onClick={handleBackToTypeSelection}>
|
||||
Back
|
||||
</Button>
|
||||
<Space>
|
||||
{!summaryData?.success && (
|
||||
<Button onClick={onSkipToSetup} disabled={!canProceedConfigure}>
|
||||
Skip to Integration Code <ArrowRightOutlined />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<ArrowRightOutlined />}
|
||||
disabled={!summaryData?.success}
|
||||
onClick={() => setCurrentStep(2)}
|
||||
>
|
||||
Preview Results
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* ─── Step 1: Preview & Validate ─── */}
|
||||
{currentStep === 1 && !summaryData?.success && (
|
||||
{/* ─── Dep Step 2: Preview & Validate ─── */}
|
||||
{integrationType === 'dependency' && currentStep === 2 && !summaryData?.success && (
|
||||
<Card>
|
||||
<Alert
|
||||
type="warning"
|
||||
@@ -434,10 +616,10 @@ const AIIntegrationHub: React.FC = () => {
|
||||
message="Preview data is no longer available. Please run Test Query again."
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<Button type="primary" onClick={() => setCurrentStep(0)}>Back to Configure</Button>
|
||||
<Button type="primary" onClick={() => setCurrentStep(1)}>Back to Configure</Button>
|
||||
</Card>
|
||||
)}
|
||||
{currentStep === 1 && summaryData?.success && (
|
||||
{integrationType === 'dependency' && currentStep === 2 && summaryData?.success && (
|
||||
<div>
|
||||
<Card size="small" style={{ borderLeft: `3px solid ${token.colorPrimary}`, marginBottom: 16 }}>
|
||||
<Row gutter={16} align="middle">
|
||||
@@ -526,25 +708,18 @@ const AIIntegrationHub: React.FC = () => {
|
||||
/>
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 24 }}>
|
||||
<Button
|
||||
icon={<ArrowLeftOutlined />}
|
||||
onClick={() => setCurrentStep(0)}
|
||||
>
|
||||
<Button icon={<ArrowLeftOutlined />} onClick={() => setCurrentStep(1)}>
|
||||
Back
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<ArrowRightOutlined />}
|
||||
onClick={() => setCurrentStep(2)}
|
||||
>
|
||||
<Button type="primary" icon={<ArrowRightOutlined />} onClick={() => setCurrentStep(3)}>
|
||||
Integration Code
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ─── Step 2: Integration Code ─── */}
|
||||
{currentStep === 2 && !summaryData?.success && !summaryParams && (
|
||||
{/* ─── Dep Step 3: Integration Code ─── */}
|
||||
{integrationType === 'dependency' && currentStep === 3 && !summaryData?.success && !summaryParams && (
|
||||
<Card>
|
||||
<Alert
|
||||
type="warning"
|
||||
@@ -552,10 +727,10 @@ const AIIntegrationHub: React.FC = () => {
|
||||
message="Configuration required. Please set up your query in the Configure step."
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<Button type="primary" onClick={() => setCurrentStep(0)}>Back to Configure</Button>
|
||||
<Button type="primary" onClick={() => setCurrentStep(1)}>Back to Configure</Button>
|
||||
</Card>
|
||||
)}
|
||||
{currentStep === 2 && (summaryData?.success || summaryParams) && (
|
||||
{integrationType === 'dependency' && currentStep === 3 && (summaryData?.success || summaryParams) && (
|
||||
<div>
|
||||
{!summaryData?.success && (
|
||||
<Alert
|
||||
@@ -572,10 +747,7 @@ const AIIntegrationHub: React.FC = () => {
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
|
||||
<Card
|
||||
size="small"
|
||||
style={{ marginBottom: 16 }}
|
||||
>
|
||||
<Card size="small" style={{ marginBottom: 16 }}>
|
||||
<Space align="center">
|
||||
<Text strong>Pipeline Platform:</Text>
|
||||
<Select value={platform} onChange={setPlatform} style={{ width: 200 }}>
|
||||
@@ -617,7 +789,7 @@ const AIIntegrationHub: React.FC = () => {
|
||||
showIcon
|
||||
icon={<InfoCircleOutlined />}
|
||||
message="Pre-deployment risk assessment"
|
||||
description="Use this endpoint to assess the impact of deploying changes to a service. Returns a risk score (0-100), affected services count, and actionable recommendations."
|
||||
description={<>Use this endpoint to assess the impact of deploying changes to a service. You can also <Button type="link" style={{ padding: 0 }} onClick={handleBackToTypeSelection}>set up Blast Radius as a dedicated integration type</Button> from Step 1.</>}
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<Tabs
|
||||
@@ -636,7 +808,7 @@ const AIIntegrationHub: React.FC = () => {
|
||||
]}
|
||||
/>
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Link to="/impact/blast-radius">
|
||||
<Link to="/impact/blast-radius?tab=test">
|
||||
<Button type="link" style={{ padding: 0 }}>
|
||||
<ThunderboltOutlined /> Test blast radius assessments interactively
|
||||
</Button>
|
||||
@@ -648,26 +820,7 @@ const AIIntegrationHub: React.FC = () => {
|
||||
]}
|
||||
/>
|
||||
|
||||
<Card
|
||||
title={<span><KeyOutlined /> Authentication</span>}
|
||||
size="small"
|
||||
style={{ marginTop: 16 }}
|
||||
>
|
||||
<Paragraph>
|
||||
All API calls require authentication via <Text strong>API Key</Text>. Include the header <Text code>X-API-Key: fk_your_key</Text> in every request.
|
||||
</Paragraph>
|
||||
<ol>
|
||||
<li>Go to <Link to="/settings"><Text strong>Settings</Text></Link> and open the <Text strong>API Keys</Text> tab</li>
|
||||
<li>Click <Text strong>Generate New API Key</Text> and give it a descriptive name (e.g. "azure-devops-pipeline")</li>
|
||||
<li>Copy the generated key (starts with <Text code>fk_</Text>) and store it securely in your CI/CD platform's secrets/variables</li>
|
||||
</ol>
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
message="API keys provide full API access. Store them as encrypted secrets in your pipeline platform, never in source code."
|
||||
style={{ marginTop: 8 }}
|
||||
/>
|
||||
</Card>
|
||||
{authCard}
|
||||
|
||||
<Card title="Understanding the Response" size="small" style={{ marginTop: 16 }}>
|
||||
<Paragraph>
|
||||
@@ -675,10 +828,10 @@ const AIIntegrationHub: React.FC = () => {
|
||||
Each dependency includes its Kubernetes <Text strong>annotations</Text> and <Text strong>labels</Text>.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
Your AI agent or pipeline should:
|
||||
Your pipeline should:
|
||||
</Paragraph>
|
||||
<ol>
|
||||
<li>Extract <Text code>annotations["git-repo"]</Text> from each downstream service to identify affected repositories</li>
|
||||
<li>Extract <Text code>annotations["git-repo"]</Text> from each downstream service to identify affected repositories</li>
|
||||
<li>Check <Text code>is_critical</Text> flag to prioritize critical dependency changes</li>
|
||||
<li>Use <Text code>service_category</Text> grouping to understand the type of each dependency (database, cache, API, etc.)</li>
|
||||
<li>Examine <Text code>callers</Text> to understand which services call the changed service</li>
|
||||
@@ -686,14 +839,144 @@ const AIIntegrationHub: React.FC = () => {
|
||||
</Card>
|
||||
|
||||
<div style={{ marginTop: 24 }}>
|
||||
<Button icon={<ArrowLeftOutlined />} onClick={() => setCurrentStep(summaryData?.success ? 1 : 0)}>
|
||||
<Button icon={<ArrowLeftOutlined />} onClick={() => setCurrentStep(summaryData?.success ? 2 : 1)}>
|
||||
{summaryData?.success ? 'Back to Preview' : 'Back to Configure'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ═══════════════════════════════════════════════════════════ */}
|
||||
{/* BLAST RADIUS GATE FLOW (Steps 1-2) */}
|
||||
{/* ═══════════════════════════════════════════════════════════ */}
|
||||
|
||||
{/* ─── BR Step 1: Configure ─── */}
|
||||
{integrationType === 'blast_radius' && currentStep === 1 && (
|
||||
<Card title="Blast Radius Gate Configuration">
|
||||
<Paragraph type="secondary">
|
||||
Configure your pre-deployment risk assessment integration. The Blast Radius API evaluates the impact of changes
|
||||
and returns a risk score with recommendations — your pipeline decides what to do.
|
||||
</Paragraph>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Form layout="vertical">
|
||||
<Form.Item label="Pipeline Platform" required>
|
||||
<Select value={platform} onChange={setPlatform} style={{ maxWidth: 300 }}>
|
||||
{PIPELINE_PLATFORMS.map(p => <Option key={p.value} value={p.value}>{p.label}</Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col xs={24} sm={12}>
|
||||
<Form.Item
|
||||
label="Target Service Name"
|
||||
tooltip="Optional — if left empty, snippets will use a placeholder. You can parameterize this in your pipeline."
|
||||
>
|
||||
<Input
|
||||
placeholder="e.g. payment-service"
|
||||
value={brTargetService}
|
||||
onChange={e => setBrTargetService(e.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xs={24} sm={12}>
|
||||
<Form.Item
|
||||
label="Target Namespace"
|
||||
tooltip="Optional — defaults to 'default' in generated snippets."
|
||||
>
|
||||
<Input
|
||||
placeholder="e.g. production"
|
||||
value={brTargetNamespace}
|
||||
onChange={e => setBrTargetNamespace(e.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 24 }}>
|
||||
<Button icon={<ArrowLeftOutlined />} onClick={handleBackToTypeSelection}>
|
||||
Back
|
||||
</Button>
|
||||
<Button type="primary" icon={<ArrowRightOutlined />} onClick={() => setCurrentStep(2)}>
|
||||
Generate Integration Code
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* ─── BR Step 2: Integration Code ─── */}
|
||||
{integrationType === 'blast_radius' && currentStep === 2 && (
|
||||
<div>
|
||||
<Alert
|
||||
type="info"
|
||||
showIcon
|
||||
message="All snippets below use your configured parameters. Copy and adapt to your environment."
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
|
||||
<Card size="small" style={{ marginBottom: 16 }}>
|
||||
<Space align="center">
|
||||
<Text strong>Pipeline Platform:</Text>
|
||||
<Select value={platform} onChange={setPlatform} style={{ width: 200 }}>
|
||||
{PIPELINE_PLATFORMS.map(p => <Option key={p.value} value={p.value}>{p.label}</Option>)}
|
||||
</Select>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
<Tabs
|
||||
items={[
|
||||
{
|
||||
key: 'br-pipeline',
|
||||
label: <span><RocketOutlined /> {PIPELINE_PLATFORMS.find(p => p.value === platform)?.label || 'Pipeline'}</span>,
|
||||
children: <CodeBlock code={buildBlastRadiusPipelineSnippet(platform, brTargetNamespace || undefined, brTargetService || undefined)} label="Blast Radius Pipeline" />,
|
||||
},
|
||||
{
|
||||
key: 'br-curl',
|
||||
label: <span><CodeOutlined /> curl</span>,
|
||||
children: <CodeBlock code={buildBlastRadiusCurlSnippet(brTargetNamespace || undefined, brTargetService || undefined)} label="Blast Radius curl" />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<Card title="Example Response" size="small" style={{ marginTop: 16 }}>
|
||||
<Paragraph type="secondary" style={{ marginBottom: 8 }}>
|
||||
The <Text code>POST /api/v1/blast-radius/assess</Text> endpoint returns a risk assessment:
|
||||
</Paragraph>
|
||||
<CodeBlock code={EXAMPLE_BR_RESPONSE} label="Example Response" />
|
||||
</Card>
|
||||
|
||||
<Card title="Response Fields" size="small" style={{ marginTop: 16 }}>
|
||||
<Descriptions size="small" column={1} bordered>
|
||||
<Descriptions.Item label={<Text code>risk_score</Text>}>0-100, higher = more risky</Descriptions.Item>
|
||||
<Descriptions.Item label={<Text code>risk_level</Text>}>low / medium / high / critical</Descriptions.Item>
|
||||
<Descriptions.Item label={<Text code>blast_radius.total_affected</Text>}>Total services in impact zone</Descriptions.Item>
|
||||
<Descriptions.Item label={<Text code>blast_radius.critical_services</Text>}>Names of critical downstream services</Descriptions.Item>
|
||||
<Descriptions.Item label={<Text code>recommendation</Text>}>proceed / review_required / delay_suggested</Descriptions.Item>
|
||||
<Descriptions.Item label={<Text code>advisory_only</Text>}>Always true — Flowfish never blocks deployments</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</Card>
|
||||
|
||||
{authCard}
|
||||
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Link to="/impact/blast-radius?tab=test">
|
||||
<Button type="link" icon={<ThunderboltOutlined />} style={{ padding: 0 }}>
|
||||
Test blast radius assessments interactively
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: 24 }}>
|
||||
<Button icon={<ArrowLeftOutlined />} onClick={() => setCurrentStep(1)}>
|
||||
Back to Configure
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AIIntegrationHub;
|
||||
export default IntegrationHub;
|
||||
@@ -85,7 +85,6 @@ import {
|
||||
BarChartOutlined,
|
||||
CheckCircleOutlined,
|
||||
AlertOutlined,
|
||||
RobotOutlined,
|
||||
CopyOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
@@ -7673,25 +7672,25 @@ const MapInner: React.FC = () => {
|
||||
})() : null,
|
||||
},
|
||||
{
|
||||
key: 'ai-hub',
|
||||
label: <span><RobotOutlined /> AI Hub</span>,
|
||||
children: drawerTab === 'ai-hub' ? (
|
||||
key: 'integration',
|
||||
label: <span><ApiOutlined /> Integration</span>,
|
||||
children: drawerTab === 'integration' ? (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
<Typography.Text type="secondary">
|
||||
Analyze this service's dependencies, impact radius, and generate integration snippets for AI Agents and CI/CD pipelines.
|
||||
Analyze this service's dependencies, impact radius, and generate integration snippets for CI/CD pipelines.
|
||||
</Typography.Text>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<RobotOutlined />}
|
||||
icon={<ApiOutlined />}
|
||||
onClick={() => {
|
||||
const node = selectedNode as any;
|
||||
const params = new URLSearchParams();
|
||||
if (node?.name) params.set('owner_name', node.owner_name || node.name);
|
||||
if (node?.namespace && node.namespace !== 'external') params.set('namespace', node.namespace);
|
||||
navigate(`/integration/ai-hub?${params.toString()}`);
|
||||
navigate(`/integration/hub?${params.toString()}`);
|
||||
}}
|
||||
>
|
||||
Open AI Integration Hub
|
||||
Open Integration Hub
|
||||
</Button>
|
||||
</div>
|
||||
) : null,
|
||||
|
||||
Reference in New Issue
Block a user