Webhook 通知
Webhook 让您在 Archyl 工作区中发生任何变更时,实时接收 HTTP POST 通知。创建一个 Webhook,将其指向您的 URL,选择您关注的事件,Archyl 将在这些事件触发时通知您的端点。
概述
当事件发生时——例如系统被创建、发布被部署、ADR 被更新——Archyl 会向每个订阅了该事件的 Webhook 发送 HTTP POST 请求。您的端点会收到一个 JSON 负载,描述发生了什么、谁触发的以及属于哪个项目。
典型用例:
- Slack 或 Teams 通知:当架构变更发生时发送通知
- CI/CD 触发:当新发布被创建时触发流水线
- 审计日志:将事件记录到外部系统
- 自定义仪表盘:根据架构事件实时响应
- 自动化流水线:当发现完成时运行自动化任务
支持的事件
架构元素
| 类别 | 事件 |
|---|---|
| 系统 | system.created, system.updated, system.deleted |
| 容器 | container.created, container.updated, container.deleted |
| 组件 | component.created, component.updated, component.deleted |
| 代码 | code.created, code.updated, code.deleted |
| 关系 | relationship.created, relationship.updated, relationship.deleted |
| 覆盖层 | overlay.created, overlay.updated, overlay.deleted |
项目管理
| 类别 | 事件 |
|---|---|
| 项目 | project.created, project.updated, project.deleted |
| 发布 | release.created, release.updated, release.deployed |
| 请求 | request.created, request.merged, request.closed |
文档
| 类别 | 事件 |
|---|---|
| ADR | adr.created, adr.updated, adr.deleted |
| 文档 | documentation.created, documentation.updated, documentation.deleted |
| 流程 | flow.created, flow.updated, flow.deleted |
| API 契约 | api_contract.created, api_contract.updated |
协作与分析
| 类别 | 事件 |
|---|---|
| 评论 | comment.created |
| 白板 | whiteboard.created |
| 事件通道 | event_channel.created |
| 发现 | discovery.completed |
| 洞察 | insight.generated |
创建 Webhook
- 前往 组织设置,选择 Webhooks 选项卡
- 点击 新建 Webhook
- 填写配置:
| 字段 | 必填 | 描述 |
|---|---|---|
| 名称 | 是 | 描述性标签(如 "Slack — 架构变更") |
| URL | 是 | 接收 POST 请求的 HTTPS 端点 |
| 密钥令牌 | 否 | 用于签名负载以进行验证的共享密钥 |
| 事件 | 是 | 选择哪些事件触发此 Webhook |
| 项目 | 否 | 可选择限制到特定项目 |
- 点击 创建
Webhook 创建后立即开始接收事件。
负载格式
每次 Webhook 投递都会发送以下结构的 JSON 负载:
{
"event": "system.created",
"timestamp": "2026-03-10T14:30:00Z",
"data": {
"entityType": "system",
"entityName": "Payment Service",
"action": "created",
"userName": "vincent",
"projectId": "a1b2c3d4-...",
"projectName": "My Project"
}
}
| 字段 | 描述 |
|---|---|
event |
事件类型字符串(如 container.updated、release.deployed) |
timestamp |
事件发生时的 ISO 8601 时间戳 |
data.entityType |
发生变更的实体类型 |
data.entityName |
受影响实体的名称 |
data.action |
执行的操作 |
data.userName |
触发事件的用户 |
data.projectId |
事件所在项目的 UUID |
data.projectName |
可读的项目名称 |
Content-Type 头始终为 application/json。
安全
请求头
每次 Webhook 投递都包含以下请求头:
| 请求头 | 示例 | 描述 |
|---|---|---|
Content-Type |
application/json |
始终为 JSON |
User-Agent |
Archyl-Webhook/1.0 |
标识该请求来自 Archyl |
X-Archyl-Event |
system.created |
触发本次投递的事件类型 |
X-Archyl-Signature |
sha256=a1b2c3... |
HMAC-SHA256 签名(仅在设置了密钥令牌时包含) |
HMAC-SHA256 签名验证
如果您在创建 Webhook 时设置了密钥令牌,Archyl 会使用 HMAC-SHA256 对每个负载进行签名。签名通过 X-Archyl-Signature 头发送,格式如下:
sha256=<十六进制编码的 HMAC-SHA256 摘要>
验证投递的步骤:
- 读取原始请求体(精确的字节内容,在任何 JSON 解析之前)
- 读取
X-Archyl-Signature头并去除sha256=前缀以获取十六进制签名 - 使用您的密钥令牌作为密钥,对原始请求体计算 HMAC-SHA256 哈希
- 将结果进行十六进制编码,并与步骤 2 中的签名进行常量时间比较
- 如果不匹配,则拒绝该请求
Go 示例:
func verifyArchylWebhook(r *http.Request, secret string) ([]byte, error) {
body, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
header := r.Header.Get("X-Archyl-Signature")
if !strings.HasPrefix(header, "sha256=") {
return nil, fmt.Errorf("missing or invalid signature header")
}
signature := strings.TrimPrefix(header, "sha256=")
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
expected := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(expected), []byte(signature)) {
return nil, fmt.Errorf("signature mismatch")
}
return body, nil
}
Node.js 示例:
const crypto = require("crypto");
function verifyArchylWebhook(req, secret) {
const header = req.headers["x-archyl-signature"] || "";
if (!header.startsWith("sha256=")) {
throw new Error("Missing or invalid signature header");
}
const signature = header.slice("sha256=".length);
const body = req.rawBody; // use raw body, not parsed JSON
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
throw new Error("Signature mismatch");
}
return JSON.parse(body);
}
Python 示例:
import hmac
import hashlib
def verify_archyl_webhook(body: bytes, header: str, secret: str) -> dict:
if not header.startswith("sha256="):
raise ValueError("Missing or invalid signature header")
signature = header.removeprefix("sha256=")
expected = hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
raise ValueError("Signature mismatch")
return json.loads(body)
始终使用常量时间比较(hmac.Equal、crypto.timingSafeEqual、hmac.compare_digest)以防止时序攻击。始终针对原始请求体进行验证——解析并重新序列化 JSON 可能会改变字节表示,从而导致签名验证失败。
投递历史
每个 Webhook 都会保留近期投递的日志。查看方法:
- 前往 组织设置 > Webhooks
- 点击 Webhook 名称
- 打开 投递 选项卡
每条投递记录显示:
| 字段 | 描述 |
|---|---|
| 事件 | 触发投递的事件类型 |
| 状态码 | 端点返回的 HTTP 响应码 |
| 时间戳 | 投递发送的时间 |
| 耗时 | 请求花费的时间 |
| 请求负载 | 发送的完整 JSON 内容 |
| 响应内容 | 端点返回的响应 |
投递记录保留 7 天,之后自动清除。
绿色标记表示投递成功(2xx 响应)。红色表示失败(非 2xx 或超时)。
测试
在生产环境中使用 Webhook 之前,请先验证其工作正常:
- 打开 Webhook 详情页面
- 点击 发送测试
- Archyl 会向您的端点发送一个测试负载,事件为
event: "webhook.test" - 查看投递选项卡以确认接收并检查响应
测试投递使用与真实事件相同的签名机制,因此您可以同时验证签名验证逻辑。
重试策略
当投递失败(非 2xx 响应或网络超时)时,Archyl 会自动重试:
| 尝试次数 | 延迟 |
|---|---|
| 第 1 次重试 | 1 分钟 |
| 第 2 次重试 | 5 分钟 |
| 第 3 次重试 | 30 分钟 |
经过 3 次失败重试后,投递将被标记为失败。您可以在投递选项卡中点击 重试 手动重新触发任何失败的投递。
如果 Webhook 持续失败 24 小时,Archyl 将禁用该 Webhook 并向组织管理员发送通知。问题解决后,在 Webhook 设置中重新启用即可。
按项目过滤
默认情况下,Webhook 会接收组织中所有项目的事件。如需缩小范围:
- 编辑 Webhook
- 在 项目 下,选择一个或多个项目
- 保存
只有来自所选项目的事件才会触发投递。当不同团队管理不同项目且只需要接收各自工作的通知时,这非常有用。
您可以随时更新项目过滤条件,无需重新创建 Webhook。
最佳实践
快速响应
您的端点应在 10 秒 内返回 2xx 响应。如果需要进行大量处理,请先接受 Webhook,然后在后台任务中异步处理。
验证签名
始终设置密钥令牌并验证 X-Archyl-Signature 头。这可以确保负载确实来自 Archyl 且未被篡改。
使用 HTTPS
始终使用 HTTPS 端点。Archyl 不会向纯 HTTP URL 投递 Webhook。
按项目过滤
如果您的组织有许多项目,请将 Webhook 限定到您关注的项目。这可以减少噪音并避免端点进行不必要的处理。
处理重复
在少数情况下(网络重试、基础设施故障转移),您的端点可能会多次收到相同的事件。使用 timestamp 和 event 字段进行检测和去重。
监控投递状态
定期检查投递选项卡。持续的失败模式可能表明端点问题、防火墙规则或您端凭据已过期。
后续步骤
- Marketplace 集成 — 连接外部服务并在仪表盘上显示实时数据
- 发布管理 — 跨架构跟踪部署
- 架构洞察 — 自动检测架构问题