Tanush1912/cohesion-app
GitHub: Tanush1912/cohesion-app
通过聚合后端静态分析、前端静态分析和运行时流量推断三个来源的 API Schema,自动发现前后端及不同环境之间的契约不一致问题。
Stars: 2 | Forks: 0
# Cohesion
Cohesion 揭示了你的系统边界上的真相——不是你的文档声称了什么,而是你的代码和流量实际做了什么。
## 目录
- [本项目的作用](#what-this-project-does)
- [仓库结构图](#repository-map)
- [架构](#architecture)
- [Schema IR](#schema-ir)
- [静态分析](#static-analysis)
- [Diff 引擎](#diff-engine)
- [实时抓包](#live-capture)
- [双重来源与反向代理](#dual-sources--reverse-proxy)
- [实时 Diff](#live-diff)
- [实时握手](#live-handshake)
- [GitHub App 集成](#github-app-integration)
- [前端 UI](#frontend-ui)
- [API 参考](#api-reference)
- [本地开发](#local-development)
- [扩展系统](#extending-the-system)
## 本项目的作用
Cohesion 是一个 schema 聚合与分析引擎。它从三个独立的来源收集 API 契约信息,并揭示它们之间的每一个不匹配项:
| 来源 | 工作原理 | 代表内容 |
|--------|-------------|-------------------|
| **后端静态分析 (Backend Static)** | 服务器代码的 AST / AI 分析 | 后端提供服务的内容及其期望 |
| **前端静态分析 (Frontend Static)** | 客户端代码的 AST / AI 分析 | 前端发送的内容及其期望 |
| **运行时观测 (Runtime Observed)** | 实时流量捕获 + 推断 | 运行时实际发生的情况 |
每个来源都会生成相同的、与语言无关的 **Schema IR**。Diff 引擎逐个字段对它们进行比较,UI 将结果渲染为交互式可视化图表。
## 仓库结构图
```
cohesion-app/
├── cohesion_backend/ Go control plane, diff engine, live capture, reverse proxy
│ ├── cmd/server/ Entry point
│ ├── internal/
│ │ ├── controlplane/ Chi router + HTTP handlers (incl. GitHub App webhooks)
│ │ ├── crypto/ AES-256-GCM encryption for stored secrets
│ │ ├── services/ Live service, diff service, schema service, GitHub installation service
│ │ ├── repository/ PostgreSQL repositories
│ │ └── models/ Database models
│ ├── pkg/
│ │ ├── diff/ Diff engine (compare, severity, confidence)
│ │ ├── github/ GitHub API fetcher + GitHub App authentication
│ │ ├── sourcefile/ Language detection, test file filtering, skip directories
│ │ └── analyzer/ Gemini-powered static analysis
│ └── migrations/ PostgreSQL schema migrations
├── cohesion_fe_analyzer/ TypeScript analyzer (ts-morph) for frontend codebases
├── cohesion_frontend/ Next.js 16 App Router UI
│ └── src/
│ ├── app/ Pages: dashboard, project, endpoint, live, docs, settings
│ ├── components/ UI kit, visualizations, live components
│ ├── lib/ API client, types, auth, utilities
│ └── stores/ Zustand state management
└── PRD.md Product requirements
```
## 架构
### 系统概述
```
flowchart TD
subgraph UI["Next.js UI"]
Dash["Dashboard"]
Project["Project Detail"]
Endpoint["Endpoint Detail + Handshake"]
Live["Live Capture (Unified / Dual / Diff / Handshake)"]
Docs["Documentation"]
Settings["Settings + GitHub App"]
end
subgraph CP["Control Plane (Go + Chi)"]
Projects["Project & Endpoint CRUD"]
SchemaStore["Schema Ingestion & Storage"]
DiffEngine["Diff Engine"]
LiveService["Live Service + SSE"]
Proxy["Reverse Proxy"]
GitHubApp["GitHub App Integration"]
Crypto["Encrypted Secret Storage"]
end
subgraph Analyzers["Analyzers"]
BE["Go / Python / Java Static Analyzer"]
FE["Next.js / React FE Analyzer"]
AI["AI-Powered Scan (Gemini)"]
RT["Runtime Inference"]
end
subgraph Storage["PostgreSQL"]
SchemaIR[("Schema IR (JSONB)")]
UserData[("Projects, Endpoints, Settings")]
Installations[("GitHub Installations")]
end
Dash --> Projects
Endpoint --> DiffEngine
Live --> LiveService
Live --> Proxy
Settings --> GitHubApp
BE --> SchemaStore
FE --> SchemaStore
AI --> SchemaStore
RT --> SchemaStore
SchemaStore --> SchemaIR
Projects --> UserData
DiffEngine --> SchemaIR
LiveService --> RT
GitHubApp --> Installations
Crypto --> UserData
```
### 数据流
```
sequenceDiagram
participant Dev as Developer
participant Analyzer as Static Analyzer
participant App as Your Application
participant CP as Control Plane API
participant DB as Schema Store
participant UI as Next.js UI
Note over Dev,UI: Static Analysis Path
Dev->>Analyzer: Scan codebase (or upload files)
Analyzer-->>CP: POST /api/analyze/{backend,frontend}
CP-->>DB: Normalize + persist Schema IR
Note over Dev,UI: Runtime Observation Path
App->>CP: POST /api/live/ingest (captured traffic)
CP->>CP: Buffer requests, broadcast via SSE
Dev->>CP: POST /api/live/infer
CP-->>DB: Inferred Schema IR (runtime-observed)
Note over Dev,UI: Visualization
UI->>CP: GET /api/endpoints, GET /api/diff/{id}
CP-->>UI: Schemas + diff results
UI->>UI: Render handshake graph, diff panel
```
## Schema IR
**Schema 中间表示 (Intermediate Representation)** 是 Cohesion 的骨干。每个分析器、每个推断引擎和每次上传都会生成这种格式。它是 JSON 可序列化的、确定性的,并且与语言无关。
```
{
"endpoint": "/api/users",
"method": "POST",
"source": "backend-static",
"request": {
"type": "object",
"fields": {
"email": { "type": "string", "required": true },
"name": { "type": "string", "required": true },
"role": { "type": "string", "required": false }
}
},
"response": {
"201": {
"type": "object",
"fields": {
"id": { "type": "string", "required": true },
"email": { "type": "string", "required": true }
}
}
}
}
```
**关键属性:**
- `source` — `backend-static`、`frontend-static`、`runtime-observed` 三者之一
- `request` — 期望的请求体 schema
- `response` — HTTP 状态码到响应体 schema 的映射
- `fields` — 每个字段都有一个 `type`、`required` 标志、可选的 `nested` 对象,以及用于运行时推断字段的可选 `confidence` (0.0–1.0)
## 静态分析
Cohesion 可以通过两种方式分析代码库:
### AI 驱动的扫描
上传文件或指向一个 GitHub 仓库。Cohesion 将代码发送给 Gemini API,后者会提取 endpoint 定义并生成 Schema IR。
```
POST /api/analyze/scan — scan local files
POST /api/analyze/github — scan a GitHub repository
```
**支持的语言:** Go, Python, TypeScript, JavaScript, Java, Ruby, Rust, PHP, C#, Kotlin, Elixir, Scala, Swift
`sourcefile` 包负责处理语言检测、测试文件过滤,并自动跳过非源码目录(`vendor`、`node_modules`、`.git`、`__pycache__`、`dist`、`build`、`target`、`.next` 等)。
### 直接上传 Schema
如果您已经有 schema(来自 OpenAPI、您自己的工具等),可以直接上传它们:
```
POST /api/analyze/backend — backend schemas
POST /api/analyze/frontend — frontend schemas
POST /api/analyze/runtime — runtime-observed schemas
```
### 前端分析器
`cohesion_fe_analyzer` 包使用 ts-morph 静态分析 Next.js/React 代码库。它会发现 `fetch()` 和 `axios` 调用,提取 URL 模式、HTTP 方法和负载结构,并输出 Schema IR。
```
flowchart LR
Code["TypeScript Source"] --> TSMorph["ts-morph AST"]
TSMorph --> Extract["Extract fetch/axios calls"]
Extract --> IR["Schema IR"]
IR -->|POST| CP["/api/analyze/frontend"]
```
## Diff 引擎
Diff 引擎是 Cohesion 的核心知识产权。它比较来自同一 endpoint 的多个来源的 Schema IR,并生成详细的不匹配报告。
### 工作原理
```
flowchart TD
BE["Backend Schema"] --> Normalize["Field Normalization"]
FE["Frontend Schema"] --> Normalize
RT["Runtime Schema"] --> Normalize
Normalize --> CompareReq["Compare Request Fields"]
Normalize --> CompareRes["Compare Response Fields"]
CompareReq --> Mismatches["Mismatch List"]
CompareRes --> Mismatches
Mismatches --> Severity["Assign Severity"]
Severity --> Confidence["Compute Confidence Score"]
Confidence --> Result["DiffResult"]
```
### 字段归一化
在比较之前,引擎会对字段名称和类型进行归一化,以避免误报:
- **名称:** `camelCase`、`PascalCase` 和 `kebab-case` 都会转换为 `snake_case`
- **类型:** 等效类型会被分组 —— `int/integer/number/float` → `number`,`bool/boolean` → `boolean`,`object/map` → `object`,`array/list` → `array`
### 不匹配类型
| 类型 | 含义 | 示例 |
|------|---------|---------|
| `missing` | 字段存在于某些来源中,但在其他来源中不存在 | 后端返回 `avatar_url`,但前端没有期望它 |
| `type_mismatch` | 相同字段,类型不同 | 后端指定 `string`,前端指定 `number` |
| `optionality_mismatch` | 在一个来源中是必填的,在另一个来源中是可选的 | 后端要求提供 `role`,前端选择性地发送它 |
| `extra_field` | 字段只存在于其中一侧 | 前端发送 `debug_mode`,后端忽略它 |
### 严重程度级别
引擎根据数据流的方向分配严重程度:
| 严重程度 | 时机 | 影响 |
|----------|------|--------|
| **Critical** | 类型不匹配;前端期望一个后端没有返回的响应字段 | 将在运行时中断 |
| **Warning** | 后端期望一个前端没有发送的请求字段;必填/可选不匹配 | 可能导致验证失败 |
| **Info** | 另一侧忽略的额外字段 | 无害但值得关注 |
### 置信度评分
每个 Diff 结果都包含一个置信度分数 (0–100),反映了比较结果的可信程度:
- 每存在一种来源类型(后端、前端、运行时)**+20**
- 当所有三种来源都存在时(三重验证)额外**+20**
- 每个严重 **-10**
- 每个警告 **-3**
- 限制在 0–100 之间
### 结果状态
| 状态 | 含义 |
|--------|---------|
| `match` | 未发现不匹配 —— 所有来源达成一致 |
| `partial` | 仅有警告或信息级别的问题 |
| `violation` | 至少有一个严重不匹配 |
## 实时抓包
实时抓包 允许您观察流经应用程序的真实 HTTP 流量,然后从中推断出运行时 schema。这为您提供了除静态分析之外的第三个事实来源。
### 工作原理
```
flowchart LR
subgraph Sources["Traffic Sources"]
Self["Self-Capture Middleware"]
Proxy["Reverse Proxy"]
Ingest["POST /api/live/ingest"]
end
subgraph Service["Live Service"]
Buffer["Circular Buffer (200/project)"]
SSE["SSE Broadcaster"]
Infer["Runtime Inference"]
end
Self --> Buffer
Proxy --> Buffer
Ingest --> Buffer
Buffer --> SSE -->|real-time events| UI["Frontend"]
Buffer --> Infer --> SchemaIR["Schema IR (runtime-observed)"]
```
### 捕获流量的三种方式
**1. 自我捕获** — 记录 Cohesion 自身的 API 流量。通过 `POST /api/live/capture/start` 启动。中间件会拦截每一个请求/响应(除了 `/api/live/*` 路径以避免递归),并将其以 `source: "self"` 添加到缓冲区中。
**2. 反向代理** — 配置一个代理目标,并通过 Cohesion 路由外部流量。每个请求都会被转发到真实的服务,并且完整的请求/响应对会被自动捕获。请参阅[双重来源](#dual-sources--reverse-proxy)。
**3. 外部接入** — 在您自己的应用程序中添加一个中间件,将捕获的流量 POST 到 `POST /api/live/ingest`。适用于任何语言或框架。
### SSE 流式传输
实时页面通过 Server-Sent Events 连接到 `GET /api/live/stream?project_id={id}`。每个捕获的请求都会实时广播:
```
{ "type": "request", "payload": { "id": "...", "path": "/api/users", "method": "GET", ... }, "source": "self" }
```
当缓冲区被清空时,会发送一个 `"clear"` 事件。
### Schema 推断
调用 `POST /api/live/infer` 将缓冲的流量转换为 Schema IR:
1. 请求按 `method:path` 分组
2. 对于每个 endpoint,将跨观测结果的请求体和响应体进行合并
3. 在每个请求中都出现的字段被标记为**必填**;在部分请求中出现的字段被标记为**可选**,并附带一个置信度分数
4. 生成的 schema 被存储为 `runtime-observed`,并出现在 endpoint 视图和 Diff 中
### 视图模式
实时页面有四个标签页:
| 标签页 | 用途 |
|-----|---------|
| **统一** | 所有捕获请求的单个按时间顺序排列的流,不论来源。点击任何请求以检查完整的请求/响应体。从整个缓冲区推断 schema。 |
| **双重来源** | 来自两个不同来源的流量的并排视图。标签栏中的来源选择器允许您选择要比较的两个来源。 |
| **实时 Diff (Live Diff)** | 计算两个来源的推断 schema 之间的 schema 差异。请参阅[实时 Diff](#live-diff)。 |
| **实时握手** | 三列握手可视化,展示前端和后端 schema 在运行时如何对齐。请参阅[实时握手](#live-handshake)。 |
## 双重来源与反向代理
双重来源模式允许您同时捕获和比较来自两个不同来源的流量。
### 什么是来源?
每个捕获的请求都会被标记上一个 `source` 标签:
- `"self"` — 由 Cohesion 自身中间件捕获的流量
- 任何自定义标签 — 通过配置的反向代理捕获或在从外部接入时打上标签的流量
### 设置反向代理
```
flowchart LR
Client["Your Client"] -->|request| Proxy["Cohesion Proxy
/api/live/proxy/{project}/{label}/*"] Proxy -->|forward| Target["Target Service
(e.g. localhost:3001)"] Target -->|response| Proxy Proxy -->|response| Client Proxy -->|capture| Buffer["Live Buffer
(source = label)"] ``` **配置代理:** ``` curl -X POST http://localhost:8080/api/live/proxy/configure \ -H "Content-Type: application/json" \ -d '{ "project_id": "PROJECT_ID", "label": "staging-api", "target_url": "http://localhost:3001" }' ``` 这会在 `http://localhost:8080/api/live/proxy/PROJECT_ID/staging-api/` 注册一个代理。发送到此 URL 的任何请求都会被转发到 `http://localhost:3001`,并且完整的请求/响应对会以 `source: "staging-api"` 被捕获。 ### 工作原理 1. 客户端向代理 URL 发送请求 2. Cohesion 读取并缓冲请求体 3. 请求使用原始的 method、headers 和 body 被转发到目标服务 4. 目标的响应被读取并缓冲 5. 创建一个 `LiveRequest`,带有标签作为来源、完整的请求/响应体、状态码和持续时间 6. 请求被接入实时缓冲区并通过 SSE 广播 7. 原始响应原封不动地返回给客户端 ### 使用双重视图 在实时页面中,点击 **双重来源** 标签页。两列并排显示,每一列展示来自一个来源的流量。使用来源选择器选择要比较的来源(例如 `self` 与 `staging-api`)。 **代理来源** 配置面板允许您直接从 UI 添加、查看和移除代理目标。每个配置的代理都会为其代理 URL 显示一个复制按钮。 ## 实时 Diff 实时 Diff 比较两个流量来源的运行时推断 schema。它不比较静态代码分析,而是比较两个服务在运行时*实际发送和接收*的内容。 ### 工作原理 ``` flowchart TD BufferA["Source A Requests"] --> InferA["Infer Schemas
(group by method:path)"] BufferB["Source B Requests"] --> InferB["Infer Schemas
(group by method:path)"] InferA --> Tag["Tag as backend-static"] InferB --> Tag2["Tag as frontend-static"] Tag --> Match["Match endpoints
by method + path"] Tag2 --> Match Match --> DiffEngine["Diff Engine
(field-by-field comparison)"] DiffEngine --> Results["Per-endpoint DiffResults
with mismatches + severity"] ``` **详细步骤:** 1. **按来源推断** — 后端按 `method:path` 将每个来源的缓冲请求进行分组,并根据观察到的主体推断出 schema。在每个请求中都出现的字段是必填的;在部分请求中出现的字段是可选的。 2. **标记 schema** — 来源 A 的 schema 被标记为 `backend-static`,来源 B 的被标记为 `frontend-static`。这使得现有的 Diff 引擎的方向逻辑能够正确应用。 3. **匹配 endpoint** — 通过 method 和 path 在两组之间匹配 endpoint。 4. **计算不匹配项** — 对于每个匹配的 endpoint,Diff 引擎比较请求和响应字段,检测缺失字段、类型不匹配、必填/可选冲突以及额外字段。 5. **显示结果** — UI 在左侧显示带有状态图标的 endpoint 列表,在右侧显示完整的不匹配详情。 ### 用例 | 场景 | 如何设置 | |----------|-----------------| | **比较环境** | 代理 staging 和 production 环境。进行 Diff 以发现行为漂移。 | | **比较 API 版本** | 代理 `/v1` 和 `/v2`。实时 Diff 展示版本之间更改了哪些字段。 | | **验证迁移** | 将流量路由到新旧服务。如果实时 Diff 显示全部匹配,则新服务在行为上是等效的。 | | **运行时的前端与后端对比** | 捕获前端调用(通过代理)和后端响应(通过自我捕获)。进行 Diff 以找出前端实际发送的内容与后端实际返回的内容之间的差异。 | ### API ``` curl -X POST http://localhost:8080/api/live/diff \ -H "Content-Type: application/json" \ -d '{ "project_id": "PROJECT_ID", "source_a": "self", "source_b": "staging-api" }' ``` 响应: ``` { "source_a": "self", "source_b": "staging-api", "endpoint_count": 3, "results": [ { "endpoint": "/api/users", "method": "GET", "status": "partial", "sources_compared": ["backend-static", "frontend-static"], "mismatches": [ { "path": "response.200.avatar_url", "type": "missing", "severity": "warning", "description": "Field present in source_a but missing in source_b" } ] } ] } ``` ## 实时握手 实时握手提供了一个三列的、逐字段的视图可视化,展示前端和后端的 API 契约在运行时是如何对齐的。虽然实时 Diff 告诉你*什么*是不同的,但实时握手向你展示了*双方如何看待*每个 endpoint——并排显示,并内联高亮显示不匹配之处。 ### 工作原理 ``` flowchart TD FE["Frontend Source Traffic"] --> InferFE["Infer Schemas"] BE["Backend Source Traffic"] --> InferBE["Infer Schemas"] InferFE --> Diff["Diff Engine"] InferBE --> Diff Diff --> Map["Build Endpoint Map
(FE schema + BE schema + diff)"] Map --> Render["Three-Column Handshake View"] ``` 1. **按来源推断 schema** — 从捕获的流量中为前端和后端来源推断 schema。 2. **计算 Diff** — Diff 引擎匹配两组之间的 endpoint,并逐个字段进行比较。 3. **构建握手映射** — 每个 endpoint 被组装成一个条目包含前端 schema、后端 schema 和 Diff 结果。 4. **渲染** — UI 在左侧显示带有状态图标的 endpoint 列表,在右侧显示三列的握手视图(前端 / 协议一致 / 后端)。 ### Endpoint 状态 | 图标 | 状态 | 含义 | |------|--------|---------| | ✓ | **匹配** | 前端和后端 schema 在所有字段上达成一致 | | ○ | **部分** | 某些字段匹配,但存在不匹配项(例如,可选与必填) | | ✕ | **违规** | 严重的契约分歧 —— 缺少字段或类型不匹配 | | • | **未知** | 只有一方有此 endpoint 的流量 | ### 实时握手与实时 Diff 的对比 | | 实时 Diff | 实时握手 | |-|-----------|----------------| | **输出** | 每个 endpoint 的不匹配列表 | 三列 schema 叠加视图 | | **最适合** | 快速发现差异 | 理解完整的契约结构 | | **显示的字段** | 仅显示不匹配的字段 | 显示双方的所有字段 | | **用例** | CI 检查、回归检测 | 设计评审、调试契约缺口 | ## GitHub App 集成 Cohesion 支持通过 GitHub App 连接 GitHub 账户以访问仓库。这提供了一种比个人访问令牌更安全的替代方案,并支持组织级别的安装。 ### 工作原理 1. **安装 GitHub App** — 在“设置”页面,点击“连接账户”以在您的 GitHub 账户或组织上安装 Cohesion GitHub App。 2. **安装回调** — 安装完成后,GitHub 会携带一个安装 ID 重定向回 Cohesion。前端会将其保存到后端。 3. **经过身份验证的仓库访问** — 在扫描 GitHub 仓库时,Cohesion 可以使用 App 安装令牌而不是个人访问令牌。App 令牌的作用域限定为用户授予访问权限的仓库。 4. **加密存储** — 安装数据存储在 PostgreSQL 中。敏感令牌和 API 密钥在静态存储时使用 AES-256-GCM 进行加密。 ### 管理连接 设置页面显示所有已连接的 GitHub 账户及其: - 账户名称和类型(用户或组织) - 用于移除安装的断开连接按钮 - 对于未安装 App 的账户,回退使用个人访问令牌 ### 配置 GitHub App 需要以下环境变量: ``` GITHUB_APP_ID=123456 GITHUB_APP_PRIVATE_KEY_PATH=./github-app-private-key.pem GITHUB_APP_CLIENT_ID=Iv1.abc123 GITHUB_APP_CLIENT_SECRET=secret GITHUB_APP_SLUG=cohesion FRONTEND_URL=http://localhost:3000 ``` ## 前端 UI ### 技术栈 Next.js 16 (App Router, Turbopack), TypeScript, Tailwind CSS, Zustand, React Flow, D3.js, Framer Motion, Clerk (auth), Lucide icons, Sonner (toasts). ### 页面 ``` flowchart LR Dashboard["/ Dashboard"] --> Project["/projects/:id"] Project --> Endpoint["/projects/:id/endpoints/:id"] Dashboard --> Live["/live"] Dashboard --> Docs["/docs"] Dashboard --> Settings["/settings"] Live --> Unified["Unified View"] Live --> Dual["Dual Sources"] Live --> Diff["Live Diff"] Live --> Handshake["Live Handshake"] Endpoint --> Flow["Flow View"] Endpoint --> List["List View"] Endpoint --> Code["Code View"] Endpoint --> HandshakeView["Handshake View"] ``` ### 仪表盘 (`/`) 项目卡片显示 endpoint 数量、schema 来源标记和契约健康状况。面向新用户的引导清单。全局统计数据(匹配 / 部分 / 违规)。 ### 项目详情 (`/projects/:id`) 包含方法标记、路径、来源指示器和状态的 endpoint 表格。通过扫描(本地或 GitHub)或手动粘贴 JSON 上传 schema。删除项目。 ### Endpoint 详情 (`/projects/:id/endpoints/:id`) 分栏布局: - **左侧面板** — 四种模式下的 Schema 可视化: - **Flow** — 展示请求/响应字段连接的交互式 React Flow 图 - **List** — 结构化的字段树状视图 - **Code** — 原始 Schema IR JSON - **Handshake** — 三列视图(前端意图 / 协议一致 / 后端能力) - **右侧面板** — 包含不匹配列表、严重程度标记和建议的 Diff 分析 - **来源标签页** — 在 backend-static、frontend-static、runtime-observed、handshake 之间切换 ### 实时抓包 (`/live`) 四种视图模式(统一 / 双重来源 / 实时 Diff / 实时握手)、项目选择器、捕获控制、代理来源配置。实时 SSE 流式传输。Schema 推断。 ### 文档 (`/docs`) 七个文档标签页,包含交互式代码示例、分步指南以及带有滚动跟踪的“本页目录”侧边栏: 1. **导入代码库** — 项目创建和 schema 扫描入门 2. **Schema 与握手** — Schema 来源和可视化模式 3. **Diff 引擎** — Diff 引擎如何工作及不匹配类型 4. **实时抓包** — 中间件集成指南 (Node.js, Python, Go)、SSE 流式传输、接入 API 5. **双重来源** — 代理配置和并排流量比较 6. **实时 Diff (Live Diff)** — 两个来源之间的运行时 schema 差异比对 7. **实时握手** — 来自实时流量的三列握手可视化 ### 设置 (`/settings`) - **AI 配置** — 用于 AI 驱动分析的 Gemini API 密钥和模型选择 - **GitHub 集成** — 通过 Cohesion GitHub App 连接 GitHub 账户,回退使用个人访问令牌 - **已连接账户** — 按账户/组织查看和管理 GitHub App 安装 ## API 参考 ### 项目 | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/projects` | 创建项目 | | `GET` | `/api/projects` | 列出所有项目 | | `GET` | `/api/projects/{id}` | 获取项目 | | `DELETE` | `/api/projects/{id}` | 删除项目 | ### Endpoint | Method | Path | 描述 | |--------|------|-------------| | `GET` | `/api/endpoints?project_id={id}` | 列出项目的 endpoint | | `GET` | `/api/endpoints/{id}` | 获取带有 schema 的 endpoint | ### Schema 分析 | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/analyze/backend` | 上传后端 schema | | `POST` | `/api/analyze/frontend` | 上传前端 schema | | `POST` | `/api/analyze/runtime` | 上传运行时 schema | | `POST` | `/api/analyze/scan` | AI 扫描本地代码库 | | `POST` | `/api/analyze/github` | AI 扫描 GitHub 仓库 | ### Diff | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/diff/{endpointId}` | 计算所有来源的 Diff | | `GET` | `/api/stats` | 聚合的匹配/部分/违规计数 | ### 实时抓包 | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/live/ingest` | 接入捕获的请求 | | `GET` | `/api/live/requests?project_id={id}` | 获取缓冲的请求 | | `GET` | `/api/live/stream?project_id={id}` | 实时事件的 SSE 流 | | `POST` | `/api/live/infer` | 从缓冲区推断 schema | | `POST` | `/api/live/clear` | 清空缓冲区 | | `POST` | `/api/live/capture/start` | 启动自我捕获中间件 | | `POST` | `/api/live/capture/stop` | 停止自我捕获中间件 | | `GET` | `/api/live/sources?project_id={id}` | 列出不同的来源标签 | | `GET` | `/api/live/schemas?project_id={id}&source={s}` | 获取某个来源的推断 schema | | `POST` | `/api/live/diff` | 对比两个来源的推断 schema | | `POST` | `/api/live/proxy/configure` | 注册反向代理目标 | | `*` | `/api/live/proxy/{projectId}/{label}/*` | 反向代理直通 | ### GitHub 集成 | Method | Path | 描述 | |--------|------|-------------| | `GET` | `/api/github/status` | 检查 GitHub App 是否已配置,获取安装 URL | | `POST` | `/api/github/installations` | 保存 GitHub App 安装 | | `GET` | `/api/github/installations` | 列出已连接的 GitHub 账户 | | `DELETE` | `/api/github/installations/{installationID}` | 移除 GitHub 安装 | ### 用户设置 | Method | Path | 描述 | |--------|------|-------------| | `GET` | `/api/user/settings` | 获取设置(密钥已掩码) | | `PUT` | `/api/user/settings` | 保存 Gemini 密钥、模型、GitHub token | ## 本地开发 ### 前置条件 - Go 1.22+ - Node 18+ - PostgreSQL - (可选) 用于 AI 驱动分析的 Gemini API 密钥 - (可选) 用于仓库扫描的 GitHub App 或个人访问令牌 ### 环境变量 ``` # Backend (cohesion_backend/.env) DATABASE_URL=postgres://user:pass@localhost:5432/cohesion PORT=8080 ENVIRONMENT=development GEMINI_API_KEY=your-gemini-api-key GEMINI_MODEL=gemini-2.0-flash CLERK_SECRET_KEY=sk_test_... CLERK_PUBLISHABLE_KEY=pk_test_... ENCRYPTION_KEY= # Required in production — 32-byte hex key for encrypting stored secrets (app will refuse to start without it when ENVIRONMENT=production) # GitHub App (可选) GITHUB_APP_ID=123456 GITHUB_APP_PRIVATE_KEY_PATH=./github-app-private-key.pem GITHUB_APP_CLIENT_ID=Iv1.abc123 GITHUB_APP_CLIENT_SECRET=secret GITHUB_APP_SLUG=cohesion FRONTEND_URL=http://localhost:3000 # Frontend (cohesion_frontend/.env) NEXT_PUBLIC_API_URL=http://localhost:8080 NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... NEXT_PUBLIC_CLERK_SIGN_IN_URL=/ NEXT_PUBLIC_GITHUB_APP_SLUG=cohesion ``` ### 后端 ``` cd cohesion_backend go run ./cmd/server # 默认运行在 :8080 ``` ### 前端 ``` cd cohesion_frontend npm install npm run dev # 默认运行在 :3000 ``` ### 前端分析器 (可选) ``` cd cohesion_fe_analyzer npm install npm run build ``` ### 快速开始 1. 启动后端和前端 2. 从仪表盘创建一个项目 3. 上传或扫描 schema (后端 + 前端) 4. 打开一个 endpoint 查看握手视图和 Diff 5. 前往实时抓包,启动自我捕获,浏览 UI,然后推断 schema 以获取运行时数据 6. 切换到实时握手以查看前端和后端契约如何对齐 ## 扩展系统 ### 添加新的分析器 生成 Schema IR 并 POST 到 `/api/analyze/{backend,frontend,runtime}`。Diff 引擎和 UI 将原封不动地工作 —— 它们只消费 Schema IR。 ### 添加新的可视化 消费 `/api/endpoints/{id}` (schema) 和 `/api/diff/{id}` (不匹配项)。该 IR 被特意设计得简单且具有确定性。 ### 添加新的运行时来源 任何能够将捕获的请求/响应对 POST 到 `/api/live/ingest` 的服务都可以参与。`pkg/runtime` 中的 Go 中间件只是参考实现。Express、FastAPI 和 Go 中间件的示例位于 docs 页面。 ### 添加新的代理目标 向 `POST /api/live/proxy/configure` 发送带有标签和目标 URL 的请求。通过代理路由的流量会被自动捕获并打上标签。无需更改代码。 ## 安全与隐私 - 运行时捕获是选择启用的 —— 必须显式启动 - 静态分析不执行代码(仅限 AST / AI) - 请求/响应体在内存中缓冲,每个项目拥有一个 200 个请求的环形缓冲区 - API 密钥和令牌在静态存储时使用 AES-256-GCM 进行加密,并在 API 响应中进行了掩码处理。生产环境中必须提供 `ENCRYPTION_KEY` —— 服务器将在没有它的情况下拒绝启动 - GitHub App 安装使用作用域受限的安装令牌,而非宽泛的个人访问令牌 - 自我捕获排除了 `/api/live/*` 路径,以防止递归捕获 - 所有受保护的路由均通过 Clerk 进行身份验证 - 后端已配置 CORS —— 请针对生产部署进行调整 *使用 Go、Next.js 构建,并秉持 API 契约应当可见、可检查且可证明的信念。*
/api/live/proxy/{project}/{label}/*"] Proxy -->|forward| Target["Target Service
(e.g. localhost:3001)"] Target -->|response| Proxy Proxy -->|response| Client Proxy -->|capture| Buffer["Live Buffer
(source = label)"] ``` **配置代理:** ``` curl -X POST http://localhost:8080/api/live/proxy/configure \ -H "Content-Type: application/json" \ -d '{ "project_id": "PROJECT_ID", "label": "staging-api", "target_url": "http://localhost:3001" }' ``` 这会在 `http://localhost:8080/api/live/proxy/PROJECT_ID/staging-api/` 注册一个代理。发送到此 URL 的任何请求都会被转发到 `http://localhost:3001`,并且完整的请求/响应对会以 `source: "staging-api"` 被捕获。 ### 工作原理 1. 客户端向代理 URL 发送请求 2. Cohesion 读取并缓冲请求体 3. 请求使用原始的 method、headers 和 body 被转发到目标服务 4. 目标的响应被读取并缓冲 5. 创建一个 `LiveRequest`,带有标签作为来源、完整的请求/响应体、状态码和持续时间 6. 请求被接入实时缓冲区并通过 SSE 广播 7. 原始响应原封不动地返回给客户端 ### 使用双重视图 在实时页面中,点击 **双重来源** 标签页。两列并排显示,每一列展示来自一个来源的流量。使用来源选择器选择要比较的来源(例如 `self` 与 `staging-api`)。 **代理来源** 配置面板允许您直接从 UI 添加、查看和移除代理目标。每个配置的代理都会为其代理 URL 显示一个复制按钮。 ## 实时 Diff 实时 Diff 比较两个流量来源的运行时推断 schema。它不比较静态代码分析,而是比较两个服务在运行时*实际发送和接收*的内容。 ### 工作原理 ``` flowchart TD BufferA["Source A Requests"] --> InferA["Infer Schemas
(group by method:path)"] BufferB["Source B Requests"] --> InferB["Infer Schemas
(group by method:path)"] InferA --> Tag["Tag as backend-static"] InferB --> Tag2["Tag as frontend-static"] Tag --> Match["Match endpoints
by method + path"] Tag2 --> Match Match --> DiffEngine["Diff Engine
(field-by-field comparison)"] DiffEngine --> Results["Per-endpoint DiffResults
with mismatches + severity"] ``` **详细步骤:** 1. **按来源推断** — 后端按 `method:path` 将每个来源的缓冲请求进行分组,并根据观察到的主体推断出 schema。在每个请求中都出现的字段是必填的;在部分请求中出现的字段是可选的。 2. **标记 schema** — 来源 A 的 schema 被标记为 `backend-static`,来源 B 的被标记为 `frontend-static`。这使得现有的 Diff 引擎的方向逻辑能够正确应用。 3. **匹配 endpoint** — 通过 method 和 path 在两组之间匹配 endpoint。 4. **计算不匹配项** — 对于每个匹配的 endpoint,Diff 引擎比较请求和响应字段,检测缺失字段、类型不匹配、必填/可选冲突以及额外字段。 5. **显示结果** — UI 在左侧显示带有状态图标的 endpoint 列表,在右侧显示完整的不匹配详情。 ### 用例 | 场景 | 如何设置 | |----------|-----------------| | **比较环境** | 代理 staging 和 production 环境。进行 Diff 以发现行为漂移。 | | **比较 API 版本** | 代理 `/v1` 和 `/v2`。实时 Diff 展示版本之间更改了哪些字段。 | | **验证迁移** | 将流量路由到新旧服务。如果实时 Diff 显示全部匹配,则新服务在行为上是等效的。 | | **运行时的前端与后端对比** | 捕获前端调用(通过代理)和后端响应(通过自我捕获)。进行 Diff 以找出前端实际发送的内容与后端实际返回的内容之间的差异。 | ### API ``` curl -X POST http://localhost:8080/api/live/diff \ -H "Content-Type: application/json" \ -d '{ "project_id": "PROJECT_ID", "source_a": "self", "source_b": "staging-api" }' ``` 响应: ``` { "source_a": "self", "source_b": "staging-api", "endpoint_count": 3, "results": [ { "endpoint": "/api/users", "method": "GET", "status": "partial", "sources_compared": ["backend-static", "frontend-static"], "mismatches": [ { "path": "response.200.avatar_url", "type": "missing", "severity": "warning", "description": "Field present in source_a but missing in source_b" } ] } ] } ``` ## 实时握手 实时握手提供了一个三列的、逐字段的视图可视化,展示前端和后端的 API 契约在运行时是如何对齐的。虽然实时 Diff 告诉你*什么*是不同的,但实时握手向你展示了*双方如何看待*每个 endpoint——并排显示,并内联高亮显示不匹配之处。 ### 工作原理 ``` flowchart TD FE["Frontend Source Traffic"] --> InferFE["Infer Schemas"] BE["Backend Source Traffic"] --> InferBE["Infer Schemas"] InferFE --> Diff["Diff Engine"] InferBE --> Diff Diff --> Map["Build Endpoint Map
(FE schema + BE schema + diff)"] Map --> Render["Three-Column Handshake View"] ``` 1. **按来源推断 schema** — 从捕获的流量中为前端和后端来源推断 schema。 2. **计算 Diff** — Diff 引擎匹配两组之间的 endpoint,并逐个字段进行比较。 3. **构建握手映射** — 每个 endpoint 被组装成一个条目包含前端 schema、后端 schema 和 Diff 结果。 4. **渲染** — UI 在左侧显示带有状态图标的 endpoint 列表,在右侧显示三列的握手视图(前端 / 协议一致 / 后端)。 ### Endpoint 状态 | 图标 | 状态 | 含义 | |------|--------|---------| | ✓ | **匹配** | 前端和后端 schema 在所有字段上达成一致 | | ○ | **部分** | 某些字段匹配,但存在不匹配项(例如,可选与必填) | | ✕ | **违规** | 严重的契约分歧 —— 缺少字段或类型不匹配 | | • | **未知** | 只有一方有此 endpoint 的流量 | ### 实时握手与实时 Diff 的对比 | | 实时 Diff | 实时握手 | |-|-----------|----------------| | **输出** | 每个 endpoint 的不匹配列表 | 三列 schema 叠加视图 | | **最适合** | 快速发现差异 | 理解完整的契约结构 | | **显示的字段** | 仅显示不匹配的字段 | 显示双方的所有字段 | | **用例** | CI 检查、回归检测 | 设计评审、调试契约缺口 | ## GitHub App 集成 Cohesion 支持通过 GitHub App 连接 GitHub 账户以访问仓库。这提供了一种比个人访问令牌更安全的替代方案,并支持组织级别的安装。 ### 工作原理 1. **安装 GitHub App** — 在“设置”页面,点击“连接账户”以在您的 GitHub 账户或组织上安装 Cohesion GitHub App。 2. **安装回调** — 安装完成后,GitHub 会携带一个安装 ID 重定向回 Cohesion。前端会将其保存到后端。 3. **经过身份验证的仓库访问** — 在扫描 GitHub 仓库时,Cohesion 可以使用 App 安装令牌而不是个人访问令牌。App 令牌的作用域限定为用户授予访问权限的仓库。 4. **加密存储** — 安装数据存储在 PostgreSQL 中。敏感令牌和 API 密钥在静态存储时使用 AES-256-GCM 进行加密。 ### 管理连接 设置页面显示所有已连接的 GitHub 账户及其: - 账户名称和类型(用户或组织) - 用于移除安装的断开连接按钮 - 对于未安装 App 的账户,回退使用个人访问令牌 ### 配置 GitHub App 需要以下环境变量: ``` GITHUB_APP_ID=123456 GITHUB_APP_PRIVATE_KEY_PATH=./github-app-private-key.pem GITHUB_APP_CLIENT_ID=Iv1.abc123 GITHUB_APP_CLIENT_SECRET=secret GITHUB_APP_SLUG=cohesion FRONTEND_URL=http://localhost:3000 ``` ## 前端 UI ### 技术栈 Next.js 16 (App Router, Turbopack), TypeScript, Tailwind CSS, Zustand, React Flow, D3.js, Framer Motion, Clerk (auth), Lucide icons, Sonner (toasts). ### 页面 ``` flowchart LR Dashboard["/ Dashboard"] --> Project["/projects/:id"] Project --> Endpoint["/projects/:id/endpoints/:id"] Dashboard --> Live["/live"] Dashboard --> Docs["/docs"] Dashboard --> Settings["/settings"] Live --> Unified["Unified View"] Live --> Dual["Dual Sources"] Live --> Diff["Live Diff"] Live --> Handshake["Live Handshake"] Endpoint --> Flow["Flow View"] Endpoint --> List["List View"] Endpoint --> Code["Code View"] Endpoint --> HandshakeView["Handshake View"] ``` ### 仪表盘 (`/`) 项目卡片显示 endpoint 数量、schema 来源标记和契约健康状况。面向新用户的引导清单。全局统计数据(匹配 / 部分 / 违规)。 ### 项目详情 (`/projects/:id`) 包含方法标记、路径、来源指示器和状态的 endpoint 表格。通过扫描(本地或 GitHub)或手动粘贴 JSON 上传 schema。删除项目。 ### Endpoint 详情 (`/projects/:id/endpoints/:id`) 分栏布局: - **左侧面板** — 四种模式下的 Schema 可视化: - **Flow** — 展示请求/响应字段连接的交互式 React Flow 图 - **List** — 结构化的字段树状视图 - **Code** — 原始 Schema IR JSON - **Handshake** — 三列视图(前端意图 / 协议一致 / 后端能力) - **右侧面板** — 包含不匹配列表、严重程度标记和建议的 Diff 分析 - **来源标签页** — 在 backend-static、frontend-static、runtime-observed、handshake 之间切换 ### 实时抓包 (`/live`) 四种视图模式(统一 / 双重来源 / 实时 Diff / 实时握手)、项目选择器、捕获控制、代理来源配置。实时 SSE 流式传输。Schema 推断。 ### 文档 (`/docs`) 七个文档标签页,包含交互式代码示例、分步指南以及带有滚动跟踪的“本页目录”侧边栏: 1. **导入代码库** — 项目创建和 schema 扫描入门 2. **Schema 与握手** — Schema 来源和可视化模式 3. **Diff 引擎** — Diff 引擎如何工作及不匹配类型 4. **实时抓包** — 中间件集成指南 (Node.js, Python, Go)、SSE 流式传输、接入 API 5. **双重来源** — 代理配置和并排流量比较 6. **实时 Diff (Live Diff)** — 两个来源之间的运行时 schema 差异比对 7. **实时握手** — 来自实时流量的三列握手可视化 ### 设置 (`/settings`) - **AI 配置** — 用于 AI 驱动分析的 Gemini API 密钥和模型选择 - **GitHub 集成** — 通过 Cohesion GitHub App 连接 GitHub 账户,回退使用个人访问令牌 - **已连接账户** — 按账户/组织查看和管理 GitHub App 安装 ## API 参考 ### 项目 | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/projects` | 创建项目 | | `GET` | `/api/projects` | 列出所有项目 | | `GET` | `/api/projects/{id}` | 获取项目 | | `DELETE` | `/api/projects/{id}` | 删除项目 | ### Endpoint | Method | Path | 描述 | |--------|------|-------------| | `GET` | `/api/endpoints?project_id={id}` | 列出项目的 endpoint | | `GET` | `/api/endpoints/{id}` | 获取带有 schema 的 endpoint | ### Schema 分析 | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/analyze/backend` | 上传后端 schema | | `POST` | `/api/analyze/frontend` | 上传前端 schema | | `POST` | `/api/analyze/runtime` | 上传运行时 schema | | `POST` | `/api/analyze/scan` | AI 扫描本地代码库 | | `POST` | `/api/analyze/github` | AI 扫描 GitHub 仓库 | ### Diff | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/diff/{endpointId}` | 计算所有来源的 Diff | | `GET` | `/api/stats` | 聚合的匹配/部分/违规计数 | ### 实时抓包 | Method | Path | 描述 | |--------|------|-------------| | `POST` | `/api/live/ingest` | 接入捕获的请求 | | `GET` | `/api/live/requests?project_id={id}` | 获取缓冲的请求 | | `GET` | `/api/live/stream?project_id={id}` | 实时事件的 SSE 流 | | `POST` | `/api/live/infer` | 从缓冲区推断 schema | | `POST` | `/api/live/clear` | 清空缓冲区 | | `POST` | `/api/live/capture/start` | 启动自我捕获中间件 | | `POST` | `/api/live/capture/stop` | 停止自我捕获中间件 | | `GET` | `/api/live/sources?project_id={id}` | 列出不同的来源标签 | | `GET` | `/api/live/schemas?project_id={id}&source={s}` | 获取某个来源的推断 schema | | `POST` | `/api/live/diff` | 对比两个来源的推断 schema | | `POST` | `/api/live/proxy/configure` | 注册反向代理目标 | | `*` | `/api/live/proxy/{projectId}/{label}/*` | 反向代理直通 | ### GitHub 集成 | Method | Path | 描述 | |--------|------|-------------| | `GET` | `/api/github/status` | 检查 GitHub App 是否已配置,获取安装 URL | | `POST` | `/api/github/installations` | 保存 GitHub App 安装 | | `GET` | `/api/github/installations` | 列出已连接的 GitHub 账户 | | `DELETE` | `/api/github/installations/{installationID}` | 移除 GitHub 安装 | ### 用户设置 | Method | Path | 描述 | |--------|------|-------------| | `GET` | `/api/user/settings` | 获取设置(密钥已掩码) | | `PUT` | `/api/user/settings` | 保存 Gemini 密钥、模型、GitHub token | ## 本地开发 ### 前置条件 - Go 1.22+ - Node 18+ - PostgreSQL - (可选) 用于 AI 驱动分析的 Gemini API 密钥 - (可选) 用于仓库扫描的 GitHub App 或个人访问令牌 ### 环境变量 ``` # Backend (cohesion_backend/.env) DATABASE_URL=postgres://user:pass@localhost:5432/cohesion PORT=8080 ENVIRONMENT=development GEMINI_API_KEY=your-gemini-api-key GEMINI_MODEL=gemini-2.0-flash CLERK_SECRET_KEY=sk_test_... CLERK_PUBLISHABLE_KEY=pk_test_... ENCRYPTION_KEY= # Required in production — 32-byte hex key for encrypting stored secrets (app will refuse to start without it when ENVIRONMENT=production) # GitHub App (可选) GITHUB_APP_ID=123456 GITHUB_APP_PRIVATE_KEY_PATH=./github-app-private-key.pem GITHUB_APP_CLIENT_ID=Iv1.abc123 GITHUB_APP_CLIENT_SECRET=secret GITHUB_APP_SLUG=cohesion FRONTEND_URL=http://localhost:3000 # Frontend (cohesion_frontend/.env) NEXT_PUBLIC_API_URL=http://localhost:8080 NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... NEXT_PUBLIC_CLERK_SIGN_IN_URL=/ NEXT_PUBLIC_GITHUB_APP_SLUG=cohesion ``` ### 后端 ``` cd cohesion_backend go run ./cmd/server # 默认运行在 :8080 ``` ### 前端 ``` cd cohesion_frontend npm install npm run dev # 默认运行在 :3000 ``` ### 前端分析器 (可选) ``` cd cohesion_fe_analyzer npm install npm run build ``` ### 快速开始 1. 启动后端和前端 2. 从仪表盘创建一个项目 3. 上传或扫描 schema (后端 + 前端) 4. 打开一个 endpoint 查看握手视图和 Diff 5. 前往实时抓包,启动自我捕获,浏览 UI,然后推断 schema 以获取运行时数据 6. 切换到实时握手以查看前端和后端契约如何对齐 ## 扩展系统 ### 添加新的分析器 生成 Schema IR 并 POST 到 `/api/analyze/{backend,frontend,runtime}`。Diff 引擎和 UI 将原封不动地工作 —— 它们只消费 Schema IR。 ### 添加新的可视化 消费 `/api/endpoints/{id}` (schema) 和 `/api/diff/{id}` (不匹配项)。该 IR 被特意设计得简单且具有确定性。 ### 添加新的运行时来源 任何能够将捕获的请求/响应对 POST 到 `/api/live/ingest` 的服务都可以参与。`pkg/runtime` 中的 Go 中间件只是参考实现。Express、FastAPI 和 Go 中间件的示例位于 docs 页面。 ### 添加新的代理目标 向 `POST /api/live/proxy/configure` 发送带有标签和目标 URL 的请求。通过代理路由的流量会被自动捕获并打上标签。无需更改代码。 ## 安全与隐私 - 运行时捕获是选择启用的 —— 必须显式启动 - 静态分析不执行代码(仅限 AST / AI) - 请求/响应体在内存中缓冲,每个项目拥有一个 200 个请求的环形缓冲区 - API 密钥和令牌在静态存储时使用 AES-256-GCM 进行加密,并在 API 响应中进行了掩码处理。生产环境中必须提供 `ENCRYPTION_KEY` —— 服务器将在没有它的情况下拒绝启动 - GitHub App 安装使用作用域受限的安装令牌,而非宽泛的个人访问令牌 - 自我捕获排除了 `/api/live/*` 路径,以防止递归捕获 - 所有受保护的路由均通过 Clerk 进行身份验证 - 后端已配置 CORS —— 请针对生产部署进行调整 *使用 Go、Next.js 构建,并秉持 API 契约应当可见、可检查且可证明的信念。*
标签:AES-256-GCM, API契约, API安全, API文档, API测试, API网关, CISA项目, GitHub App, Go语言, JSON输出, Schema IR, 云安全监控, 代码审查, 前后端数据一致性, 反向代理, 可视化工具, 后端开发, 威胁情报, 实时处理, 差异对比引擎, 开发者工具, 微服务架构, 数据加密, 日志审计, 流量捕获, 流量监控, 测试用例, 程序破解, 系统边界, 网络协议分析, 网络拓扑, 运行时行为分析, 防御绕过, 静态分析