Webhook 通知 - Archyl Docs

当架构变更发生时,实时接收 HTTP 通知

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

  1. 前往 组织设置,选择 Webhooks 选项卡
  2. 点击 新建 Webhook
  3. 填写配置:
字段 必填 描述
名称 描述性标签(如 "Slack — 架构变更")
URL 接收 POST 请求的 HTTPS 端点
密钥令牌 用于签名负载以进行验证的共享密钥
事件 选择哪些事件触发此 Webhook
项目 可选择限制到特定项目
  1. 点击 创建

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.updatedrelease.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 摘要>

验证投递的步骤:

  1. 读取原始请求体(精确的字节内容,在任何 JSON 解析之前)
  2. 读取 X-Archyl-Signature 头并去除 sha256= 前缀以获取十六进制签名
  3. 使用您的密钥令牌作为密钥,对原始请求体计算 HMAC-SHA256 哈希
  4. 将结果进行十六进制编码,并与步骤 2 中的签名进行常量时间比较
  5. 如果不匹配,则拒绝该请求

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.Equalcrypto.timingSafeEqualhmac.compare_digest)以防止时序攻击。始终针对原始请求体进行验证——解析并重新序列化 JSON 可能会改变字节表示,从而导致签名验证失败。

投递历史

每个 Webhook 都会保留近期投递的日志。查看方法:

  1. 前往 组织设置 > Webhooks
  2. 点击 Webhook 名称
  3. 打开 投递 选项卡

每条投递记录显示:

字段 描述
事件 触发投递的事件类型
状态码 端点返回的 HTTP 响应码
时间戳 投递发送的时间
耗时 请求花费的时间
请求负载 发送的完整 JSON 内容
响应内容 端点返回的响应

投递记录保留 7 天,之后自动清除。

绿色标记表示投递成功(2xx 响应)。红色表示失败(非 2xx 或超时)。

测试

在生产环境中使用 Webhook 之前,请先验证其工作正常:

  1. 打开 Webhook 详情页面
  2. 点击 发送测试
  3. Archyl 会向您的端点发送一个测试负载,事件为 event: "webhook.test"
  4. 查看投递选项卡以确认接收并检查响应

测试投递使用与真实事件相同的签名机制,因此您可以同时验证签名验证逻辑。

重试策略

当投递失败(非 2xx 响应或网络超时)时,Archyl 会自动重试:

尝试次数 延迟
第 1 次重试 1 分钟
第 2 次重试 5 分钟
第 3 次重试 30 分钟

经过 3 次失败重试后,投递将被标记为失败。您可以在投递选项卡中点击 重试 手动重新触发任何失败的投递。

如果 Webhook 持续失败 24 小时,Archyl 将禁用该 Webhook 并向组织管理员发送通知。问题解决后,在 Webhook 设置中重新启用即可。

按项目过滤

默认情况下,Webhook 会接收组织中所有项目的事件。如需缩小范围:

  1. 编辑 Webhook
  2. 项目 下,选择一个或多个项目
  3. 保存

只有来自所选项目的事件才会触发投递。当不同团队管理不同项目且只需要接收各自工作的通知时,这非常有用。

您可以随时更新项目过滤条件,无需重新创建 Webhook。

最佳实践

快速响应

您的端点应在 10 秒 内返回 2xx 响应。如果需要进行大量处理,请先接受 Webhook,然后在后台任务中异步处理。

验证签名

始终设置密钥令牌并验证 X-Archyl-Signature 头。这可以确保负载确实来自 Archyl 且未被篡改。

使用 HTTPS

始终使用 HTTPS 端点。Archyl 不会向纯 HTTP URL 投递 Webhook。

按项目过滤

如果您的组织有许多项目,请将 Webhook 限定到您关注的项目。这可以减少噪音并避免端点进行不必要的处理。

处理重复

在少数情况下(网络重试、基础设施故障转移),您的端点可能会多次收到相同的事件。使用 timestampevent 字段进行检测和去重。

监控投递状态

定期检查投递选项卡。持续的失败模式可能表明端点问题、防火墙规则或您端凭据已过期。

后续步骤