nanohype/incident-response

GitHub: nanohype/incident-response

面向中型 SaaS 企业的 Slack 事件响应自动化服务,将 Grafana OnCall 告警自动转化为作战室组建、审批门控发布和 Linear 复盘草稿的全流程编排。

Stars: 0 | Forks: 0

# 事件响应 ![Build](https://static.pigsec.cn/wp-content/uploads/repos/cas/99/993938d8ce5e902ccfb9d6747725c320d855dea3235ed9a304cedf0d94c9321f.svg) ![License](https://img.shields.io/badge/License-Apache--2.0-green) ![Node](https://img.shields.io/badge/Node-%3E%3D24-339933?logo=node.js) ![Kubernetes](https://img.shields.io/badge/Kubernetes-Tenant-326CE5?logo=kubernetes) 面向中型企业 SaaS 的仪式性事件指挥官(IC)助手。将 P1 告警到作战室组建的平均耗时从约 20 分钟缩短至 ≤5 分钟。对所有面向客户的状态消息实行 100% 的 IC 审批门控。解决事件后 2 分钟内在 Linear 中生成复盘草稿。内部服务句柄为 `incident-response`(npm 包、OTel `service.namespace` / `agents.platform`、`/incident-response` 斜杠命令 + Slack 应用,以及 `incident-response//*` 密钥前缀)。 **AI 客户端 / 代理请从这里开始:** [`AGENTS.md`](AGENTS.md)。如需全局技术栈视图,请参阅[平台参考](https://github.com/nanohype/nanohype/blob/main/docs/platform-reference.md)。 ## 这是什么 一个 protohype 项目,将 nanohype 模板(ts-service、infra-aws、agentic-loop、prompt-library、module-llm)组合成一个长期运行的 Slack socket-mode daemon。位于 ingress-nginx 后方的 webhook Deployment 负责接收 Grafana OnCall 告警;另一个 processor Deployment 运行 Slack socket-mode 单例。 **这不是一个模板** —— 这是一个独立的服务。Helm chart 位于 `chart/`,应用代码位于 `src/`,测试套件位于 `test/`,权威产出物位于 `artifacts/`。 ## 工作原理 ``` Grafana OnCall webhook ──► ingress-nginx ──► webhook Deployment (HMAC verify, idempotent DDB write) │ ▼ SQS FIFO (incident-events) │ ▼ processor Deployment ── Slack socket-mode (singleton, Recreate) │ ├── WarRoomAssembler (WorkOS + Grafana OnCall + Grafana Cloud, parallel) │ ├── StatuspageApprovalGate (two-phase commit, ConsistentRead:true) │ ├── NudgeScheduler (EventBridge Scheduler, 15-min) │ └── CommandRegistry (/incident-response status|resolve|silence|checklist|help) │ ▼ DynamoDB (incident-response-incidents + incident-response-audit; PITR on, 366-day TTL) ``` **核心不变式:** `StatuspageApprovalGate.approveAndPublish()` 是唯一允许调用 `StatuspageClient.createIncident()` 的代码路径。该约束在以下三个层面强制执行: 1. **应用层** —— IC 必须在 Slack Block Kit 中点击“Approve & Publish”(带有确认对话框)。 2. **数据库层** —— `verifyApprovalBeforePublish()` 在任何 Statuspage API 调用之前,使用 `ConsistentRead: true` 查询 `incident-response-audit`;如果缺少审批事件,则抛出 `AutoPublishNotPermittedError`。 3. **CI 层** —— `.github/workflows/ci.yml` 会使用 grep 检查门控文件外部是否出现 `createIncident()`,如果发现新的调用点,则构建失败。此外还有其他 grep 门控:适配器外部禁止使用 `new WebClient`、HTTP 客户端外部禁止使用裸 `fetch()`、镜像或清单中禁止硬编码密钥(仅限 ExternalSecret),以及针对 seeder、`secrets.template.json` 和 chart 的 `externalsecret.yaml` remoteRefs 进行密钥清单漂移检查。 ## 架构 - **src/handlers/webhook-ingress.ts** —— webhook 入站处理器(由 webhook Deployment 提供服务)。执行 HMAC-SHA256 验证(时间安全)、Zod 负载校验、通过 DynamoDB 条件写入实现幂等性,并排入 SQS FIFO 队列。HMAC 密钥按 `VersionId` 缓存,TTL 为 5 分钟,并在验证失败时强制刷新(处理轮转竞态)。 - **src/services/war-room-assembler.ts** —— 组建事件作战室:创建 Slack 私有频道,通过 WorkOS Directory Sync + Grafana OnCall 升级链解析响应人员,附加 Grafana Cloud (Mimir/Loki/Tempo) 上下文快照,置顶清单,并安排 15 分钟提醒。通过 `withTimeoutOrDefault` 实现单次调用的 Slack 超时控制,确保卡住的 Slack 调用不会阻塞组装过程。 - **src/services/statuspage-approval-gate.ts** —— 两阶段提交:写入 `STATUSPAGE_DRAFT_APPROVED` → `verifyApprovalBeforePublish` (ConsistentRead) → Statuspage.io createIncident → 写入 `STATUSPAGE_PUBLISHED`。强制达到 100% 分支覆盖率。 - **src/services/nudge-scheduler.ts** —— 每个事件独有的 EventBridge Scheduler 规则(在 pod 重启后依然存活)。IC 静默状态 → DISABLED,而不是删除,并附加审计事件。 - **src/services/sqs-consumer.ts** —— 针对事件 + 提醒队列的长轮询消费者;DLQ 安全(失败时不删除)。 - **src/services/command-registry.ts**、**src/services/event-registry.ts** —— 类型化分发器。添加斜杠命令或 SQS 事件类型只需一个 handler 文件 + 一行注册代码;无需修改 `index.ts`。 - **src/commands/** —— 每个 `/incident-response` 子命令(`status`、`resolve`、`silence`、`checklist`、`help`)对应一个文件。`resolve.ts` 驱动完整的 9 步解决流程:加载事件 → 获取最近提交 → Bedrock 复盘 → 创建 Linear issue → 删除提醒 → 脉冲评分模块 → 翻转状态 + 审计 → 公开发布 → 归档频道。频道范围命令(`status`、`checklist`、`silence`、`resolve`)通过 `src/utils/incident-lookup.ts` 中的 `slack-channel-index` GSI 解析频道 → 事件;`help` 可在任何频道下使用。 - **src/events/** —— 每个 SQS 事件类型(`ALERT_RECEIVED`、`ALERT_RESOLVED`、`STATUS_UPDATE_NUDGE`、`SLA_CHECK`)对应一个文件。 - **src/clients/** —— 轻量级适配器:`workos-client`(单实例 5 分钟缓存、过期回退、熔断器;游标分页 + 用户映射委托给内置的 `src/vendor/runtime/workos-directory.ts`,上限为 50 页 / 5k 成员 —— 这是与 IdP 无关的 `DirectoryUser` port 的具体实现)、`grafana-oncall-client`、`grafana-cloud-client`(只读、硬编码)、`statuspage-client`、`linear-client` (@linear/sdk)、`github-client`(CODEOWNERS + 用于部署时间线的最近提交)。 - **src/ai/incident-response-ai.ts** —— Bedrock 封装。使用 `claude-sonnet-4-6` 生成草稿 + 复盘,使用 `claude-haiku-4-5` 进行消息分类。对 system prompt 应用 Anthropic prompt 缓存。对生成的每份状态草稿应用基于内置全联合目录(`src/vendor/runtime/pii.ts` —— 密钥/token、SSN/信用卡、薪酬、人力资源、健康信息、出生日期、联系方式、AWS 账户、客户 + 基础设施标识符)的 PII 脱敏,并使用类型化 token(`[EMAIL]`、`[CUSTOMER_ID]`,……)以便 IC 能看到被移除的内容。 - **src/utils/http-client.ts** —— 5 秒硬超时、2 次重试硬上限、带抖动的指数退避。基于 AbortController 实现。 - **src/utils/metrics.ts** —— OTel Metrics API(`assembly_duration_ms`、`approval_gate_latency_ms`、`directory_lookup_failure_count`、`statuspage_publish_count{outcome}`、`incident_resolved_count`、`postmortem_created_count`)。通过 OTLP 导出到集群的 `grafana-agent.monitoring.svc.cluster.local:4318`,再由其转发至 Grafana Cloud Mimir。非阻塞。 - **src/utils/tracing.ts** —— OTel 追踪辅助工具:`withSpan` 包装器,SQS MessageAttributes ↔ W3C trace-context 辅助工具。自动注入功能配置了 http/fetch/aws-sdk;`WarRoomAssembler.assemble` 中的手动 span 提供每步耗时统计(create_channel、resolve_responders、invite_responders、post_context、pin_checklist、schedule_nudge)。trace context 可跨 webhook Deployment → SQS → processor Deployment 跳跃传播。 - **src/utils/logger.ts** —— 结构化 JSON logger(stdout/stderr)。当存在活跃的 OTel span 时,会标记 `trace_id` + `span_id`,从而实现 Grafana 的 Tempo → Loki 一键跳转。两个 Deployment 均将 JSON 写入 stderr;集群日志转发器将其发送至 Grafana Cloud Loki。无每个 pod 的 sidecar。 - **src/utils/audit.ts** —— 审计日志写入器。所有写入操作均被 AWAITED。使用 ConditionExpression `attribute_not_exists(SK)` 保证幂等性。自带 `auditApprovalGateViolations()` 用于合规性扫描。 - **src/utils/with-timeout.ts** —— `withTimeout`(从内置的弹性模块重新导出)+ 应用侧的 `withTimeoutOrDefault`。用于包裹非关键的 Slack 调用。 - **src/vendor/runtime/** —— 内置的 `@nanohype/runtime` 模块(`circuit-breaker`、`resilience`、`pii`、`workos-directory`)。与 `nanohype/library/runtime/src/*` 字节完全相同的副本 —— 使用方式与内置的 `chart/charts/tenant-chart-base` 相同。`npm run sync:vendored` 会从 nanohype 检出中重新拷贝;CI 会运行 `--check` 模式,因此副本发生漂移会导致构建失败。行为变更首先在上游落地,并附带其测试。 - **chart/** —— Helm chart:webhook Deployment + Service + 公共 Ingress(位于 `src/bin/webhook-server.ts` 的 `node:http` 包装器)、processor Deployment(Slack socket-mode 单例,Recreate 策略)、名为 `incident-response` 的共享 ServiceAccount,通过 EKS Pod Identity 关联绑定到 landing-zone 的 `incident-response-platform` IAM 角色(无 role-arn 注解)、NetworkPolicy(ingress-nginx → webhook + 出口 DNS + HTTPS)、聚合了 `grafana-oncall-hmac` + `app-secrets` + `grafana-cloud` 的 ExternalSecret、包含三个 SLO 告警的 PrometheusRule、Grafana 仪表盘 ConfigMap。完整模板说明请参阅 [`chart/README.md`](chart/README.md)。 - **platform.yaml** —— Platform CR (`platform.nanohype.dev/v1alpha1`),声明 incident-response 为 `protohype` 团队的一个租户,并共同声明了一个 BudgetPolicy(`governance.nanohype.dev/v1alpha1`;每月 2500 美元软上限、开启熔断开关、在 50/80/100% 时告警)。设置 `identity.allowedModelFamilies: ["anthropic"]` 以便在 operator 协调的 IAM 角色上获得 Bedrock 访问权限(供 AgentFleet pod 使用,如果/当存在时);incident-response 自身的应用 pod 通过 EKS Pod Identity 关联直接代入由 landing-zone 拥有的角色。 - **gitops/applicationset-entry.yaml** —— 用于 `nanohype/eks-gitops` ArgoCD 调和的 ApplicationSet 条目。 - **src/bin/webhook-server.ts** —— `node:http` 包装器,将来自 `src/handlers/webhook-ingress.ts` 的 `APIGatewayProxyHandlerV2` 挂载到一个 POST 端点,外加用于 k8s 探针的 `/health`。这是 webhook Deployment 运行的入口点。无新的 runtime 依赖。 ## 本地运行 ``` npm install cp .env.example .env # fill in values — see "Configuration" below npm run dev # ts-node-dev against local Slack socket-mode ``` `npm run dev` 需要有效的 Slack socket-mode 凭证(在开发期间使用测试工作区 + bot 应用)。DynamoDB + SQS URL 可以指向预发环境资源;生产集成没有仅限本地的模式。 ## 测试 ``` npm test # all suites (unit + integration) npm run test:unit # unit — adapters, breaker, audit, approval gate, handlers npm run test:integration # requires dynamodb-local on :8000 npm run test:integration:docker # spins up Docker container, runs integration, cleans up npm run typecheck npm run lint npm run format:check npm run check # typecheck + lint + format:check + test:unit (CI parity) ``` `audit.ts` 和 `statuspage-approval-gate.ts` 被锁定在 100% 的 分支 / 行 / 函数覆盖率 —— 出现任何回退 CI 都会失败。有关 Kent-Dodds-trophy 测试分布及执行验证实验,请参阅[§ 测试](#testing)。 ## 构建 ``` npm run build # tsc → dist/ ``` ## 部署 在 [`eks-agent-platform`](https://github.com/nanohype/eks-agent-platform) operator 上呈现为 Platform 租户。该 chart 会生成两个工作负载(带有公共 Ingress 的 webhook Deployment,用于接收 Grafana OnCall HMAC POST 请求;采用 Recreate 策略的 processor Deployment,用于 Slack socket-mode 单例),外加一个用于三个 SLO 告警的 PrometheusRule 和一个 Grafana 仪表盘 ConfigMap。遥测数据通过由 `eks-gitops` 安装的集群级 OTel Collector + 日志转发器发送至 Grafana Cloud —— 无需每个 pod 配置 sidecar。 Secrets Manager 条目由 operator 通过 `npm run seed:{env}` 进行预配置,并在 runtime 期间由 External Secrets Operator 使用 —— 镜像或清单中不包含任何密钥;ExternalSecret 将 `incident-response//*` 投射到一个 ks Secret 中,通过 `envFrom` 使用。资源名称、密钥路径、IAM 策略以及 OTel `deployment.environment` 属性均按环境划分范围(`incident-response/staging/*` 对比 `incident-response/production/*`)。预发环境的 IAM 角色无法读取生产环境的密钥,反之亦然。 ``` npm run chart:lint # helm lint chart npm run chart:template:staging # render chart with staging values npm run chart:template:production npm run seed:staging # seed Secrets Manager entries # ArgoCD 负责执行 rollout — 在 chart/values-{env}.yaml 中更新 image.tag, # 执行 commit 和 push。初始 tenant 设置请遵循 chart/README.md # (执行 apply platform.yaml → 等待 Ready → 注册 ApplicationSet entry)。 ``` 首次部署者应先搭建好预发环境,运行脚本化演练(`npm run drill:staging`),然后在向生产环境推出之前,执行 [`artifacts/incident-drill-playbook.md`](artifacts/incident-drill-playbook.md) 中的演练 2。 **为不同的客户 Fork IncidentResponse** —— 在不触碰应用代码的情况下,切换密钥、Slack 工作区、Linear 项目和 Grafana 租户 —— 参阅 [`docs/forking-for-a-new-client.md`](docs/forking-for-a-new-client.md)。 **首次设置:** 涵盖 AWS 前置条件(Bedrock 模型访问权限 + 推理配置文件注意事项)、各环境的第三方账号、Secrets Manager 数据播种(注意:`linear/team-id` 必须是 UUID,而不是团队 key)、Grafana OnCall webhook 连线以及通往生产环境的晋升路径的预发环境优先演练指南 —— 参阅 [`docs/deployment-guide.md`](docs/deployment-guide.md)。 **密钥播种 + 轮转** —— 环境维度的清单(`incident-response/staging/*`、`incident-response/production/*`)、`put-secret-value` 命令、轮转周期 —— 参阅 [`docs/secrets.md`](docs/secrets.md)。 **夜间演练** —— `.github/workflows/nightly-drill.yml` 按计划(也可通过 `workflow_dispatch` 按需触发)针对预发环境运行 `scripts/ci-drill.sh`。受 `INCIDENT_RESPONSE_DRILL_ENABLED` 仓库变量保护 —— 在你配置好 OIDC 角色之前,它会保持关闭状态。 ## 配置 所有配置均通过环境变量进行。必需变量在启动时由 `src/utils/env.ts` 进行断言;带默认值的变量由位于 `src/config/` 中经过 zod 校验的配置进行解析。在生产环境中,密钥值来自 AWS Secrets Manager,由 ExternalSecret 投射到 k8s Secret 中,通过 `envFrom` 使用;`.env.example` 仅用于本地开发。完整清单及来源请参阅 [`docs/secrets.md`](docs/secrets.md)。 | 变量 | 来源 | 用途 | |----------|--------|---------| | `SLACK_BOT_TOKEN` | 密钥 `incident-response/slack/bot-token` | Slack bot OAuth (chat:write, channels:manage 等) | | `SLACK_SIGNING_SECRET` | 密钥 `incident-response/slack/signing-secret` | Slack 请求签名验证 | | `SLACK_APP_TOKEN` | 密钥 `incident-response/{env}/slack/app-token` | Slack 应用级 socket-mode token (`xapp-…`) | | `GRAFANA_ONCALL_TOKEN` | 密钥 `incident-response/grafana/oncall-token` | Grafana OnCall REST API (只读) | | `GRAFANA_CLOUD_TOKEN`, `GRAFANA_CLOUD_ORG_ID` | 密钥 `incident-response/grafana/cloud-token`, `.../cloud-org-id` | Mimir/Loki/Tempo (只读) | | `STATUSPAGE_API_KEY`, `STATUSPAGE_PAGE_ID` | 密钥 `incident-response/statuspage/api-key`, `.../page-id` | Statuspage.io | | `LINEAR_API_KEY`, `LINEAR_PROJECT_ID`, `LINEAR_TEAM_ID` | 密钥 `incident-response/linear/*` | Linear 复盘目标位置 | | `WORKOS_API_KEY`, `WORKOS_DIRECTORY_ID`, `WORKOS_TEAM_GROUP_MAP` | ExternalSecret 中的 key;directory ID + map 来自 chart 的 `env.*` | WorkOS Directory Sync —— 响应人员解析范围限定在单个 directory | | `GITHUB_TOKEN`, `GITHUB_ORG_SLUG`, `GITHUB_REPO_NAMES` | token 来自 ExternalSecret;其余来自 chart 的 `env.*` | 为复盘提供部署时间线补充信息 | | `INCIDENTS_TABLE_NAME`, `AUDIT_TABLE_NAME` | 来自 chart 的 `tenantInfra.*` (landing-zone 输出) | DynamoDB 表名 | | `INCIDENT_EVENTS_QUEUE_URL`, `NUDGE_EVENTS_QUEUE_URL`, `SLA_CHECK_QUEUE_URL` | 来自 chart 的 `tenantInfra.*` (landing-zone 输出) | SQS URL | | `SCHEDULER_ROLE_ARN`, `AWS_REGION` | 来自 chart 的 `tenantInfra.*` (landing-zone 输出) | EventBridge Scheduler | | `GRAFANA_ONCALL_HMAC_SECRET_ID` | 来自 chart 的 `externalSecret.hmacSecret` | `incident-response//grafana-oncall-hmac` 的名称 —— handler 会动态获取该值,因此轮转无需重启 pod | | `BEDROCK_SONNET_MODEL_ID`, `BEDROCK_HAIKU_MODEL_ID` | 可选;默认值位于 `src/config/` | Bedrock 模型 ID(Sonnet 负责生成草稿,Haiku 负责分类)—— 覆盖以锁定快照或跨区域推理 profile | JSON 结构的密钥 `incident-response/{env}/grafana-cloud/otlp-auth` 在一个 payload 中携带 Grafana Cloud 遥测凭证。与其他密钥一样由 operator 进行配置 —— 如果你省略 JSON 中的内容,seeder 会自动根据 `instance_id` + `api_token` 计算 `basic_auth`。集群的 OTel Collector + 日志转发器 (eks-gitops) 拥有导出路径;应用只需发出 OTLP + JSON。请参阅 [`docs/secrets.md`](docs/secrets.md) § “关于 `incident-response/{env}/grafana-cloud/otlp-auth` 密钥”。 ## 仪表盘 + 告警 两者均作为 Kubernetes 资源自 chart 发布 —— 无需手动导入步骤。`chart/templates/prometheusrule.yaml` 中的 PrometheusRule 携带了三个告警(组装 P99 > 5 分钟、目录查找失败激增、Statuspage 发布失败),并由 `eks-gitops` 附带的 kube-prometheus-stack operator sidecar 将其调和至 Mimir 中。`chart/templates/grafana-dashboard.yaml` 中的 Grafana 仪表盘 ConfigMap 取自 `chart/dashboards/incident-response.json`,并由 Grafana sidecar 通过 `grafana_dashboard: "1"` 标签选择器自动导入。 ## 规范 根据根目录 `protohype/CLAUDE.md` 的规定:使用 TypeScript、ESM(`.js` 导入后缀)、Node 24、2 空格缩进、严格的 TS(`exactOptionalPropertyTypes: true`)、系统边界处使用 Zod、向 stderr/stdout 输出结构化 JSON 日志、使用 Vitest 进行测试、使用 ESLint + typescript-eslint。 IncidentResponse 特定规范: - **统一语言。** 使用 `WarRoomAssembler`、`StatuspageApprovalGate`、`NudgeScheduler`、`CommandRegistry` —— 而不是 `DataProcessor` 或 `ExternalServiceAdapter`。 - **注册优于分支判断。** 斜杠命令和 SQS 事件通过 `CommandRegistry` / `EventRegistry` 分发。`src/index.ts` 保持在 80 行代码以内。 - **禁止静默占位。** 任何未将其操作执行到底的命令,都必须向用户明确说明。只回复 `respond({ text: 'triggered' })` 但实际上并未触发被视为 Bug。 - **指标失败永不阻塞流程。** `MetricsEmitter` 会将错误吞没并记入 warn 日志。这会导致运维可见性下降;但不影响事件处理流程。 ## 测试 单元测试套件涵盖适配器、熔断器、审计写入器、审批网关、命令/事件注册表、HMAC 缓存、追踪传播、Slack 校验。集成测试套件使用 `amazon/dynamodb-local` 测试 `ConsistentRead` 语义、幂等性以及跨事件隔离。`npm run test:unit` 会在每个 PR 上运行;集成测试则作为单独的 CI 任务,搭配 DDB-local 服务容器运行。 ### 覆盖率阈值 | 文件 | 分支 | 函数 | 行 | |------|----------|-----------|-------| | `src/utils/audit.ts` | **100%** | **100%** | **100%** | | `src/services/statuspage-approval-gate.ts` | **100%** | **100%** | **100%** | | 全局 | 55% | 75% | 75% | 安全关键的阈值是承载性指标 —— 它们为审批网关不变式把关。全局阈值反映了当前的测试覆盖面;将覆盖率扩大到 80/85 已被作为后续任务进行跟踪。 ### 证明执行是有效的 永远不失败的阈值只是形式主义。为了证明 100% 门控确实能拦截 CI,请翻转 `src/utils/audit.ts` 中的一个分支(例如将 `ConsistentRead: true` 更改为 `false`)并运行 `npm run test:unit`。预期结果:`Vitest exit code: 1`,`AUDIT-006: uses ConsistentRead: true` 测试失败。还原更改后重新运行:退出码为 0。该实验记录在 PR 评论历史中,并应在阈值配置发生更改时重新运行。 ### 添加测试 - 单元测试:模拟外部依赖。关键不变式(审计完整性、审批网关排序)保留在 100% 阈值要求的文件中。 - 集成测试:使用真实的 `AuditWriter` 对接 dynamodb-local。dynamodb-local 容器用于测试那些针对 mock 毫无意义的内容 —— `ConsistentRead` 语义、`ConditionExpression` 强制执行、GSI 投影。 ## 依赖 - `@slack/bolt` + `@slack/web-api` —— Slack socket mode + Web API。 - `@aws-sdk/client-*` —— DynamoDB, SQS, Secrets Manager, Scheduler, Bedrock, Bedrock Runtime。 - `@opentelemetry/api` + `@opentelemetry/auto-instrumentations-node` + `@opentelemetry/sdk-node` —— 通过 OTLP 进行追踪 + 指标。Traces 进入 Grafana Cloud Tempo;指标进入 Mimir。 - `@linear/sdk` —— 复盘 issue 创建。 - `zod` —— webhook 负载校验。 - `aws-sdk-client-mock` + `aws-sdk-client-mock-vitest` —— AWS SDK 模拟 + 单元测试的自定义匹配器。 ## 边界 本仓库拥有该应用程序的所有权 —— 事件 pipeline、作战室组建、审批网关不变式,以及部署它的租户三元组。它**不**拥有: - AWS 基础设施(DynamoDB 表、SQS + DLQ、EventBridge Scheduler 组、S3 审计/产出物存储桶、`incident_response_irsa` 角色) → 归属于 [`landing-zone`](https://github.com/nanohype/landing-zone) 中的 `incident-response-platform` 组件。其输出通过 `tenantInfra.*` 提供给 chart。 - 账户级控制 —— 同样是 `landing-zone` 的职责,而非应用代码。 - 集群插件 → [`eks-gitops`](https://github.com/nanohype/eks-gitops)。 ## 产出物 + 参考文档 面向运维人员: | 文档 | 路径 | |----------|------| | 部署指南(首次、按部就班) | [docs/deployment-guide.md](docs/deployment-guide.md) | | Slack 应用配置(每个环境一次性操作) | [docs/slack-app-setup.md](docs/slack-app-setup.md) | | 密钥清单 + 播种 + 轮转 | [docs/secrets.md](docs/secrets.md) | | 演练 + “我该如何查看其工作状态” | [docs/drills.md](docs/drills.md) | | 故障排查目录 | [docs/troubleshooting.md](docs/troubleshooting.md) | | 为新客户 Fork IncidentResponse | [docs/forking-for-a-new-client.md](docs/forking-for-a-new-client.md) | | 更新日志 | [CHANGELOG.md](CHANGELOG.md) | | SRE 手册(day-2,事件响应) | [artifacts/runbook.md](artifacts/runbook.md) | | 事件演练剧本(推演 + 实战) | [artifacts/incident-drill-playbook.md](artifacts/incident-drill-playbook.md) | | 从 JSON 播种密钥 | [scripts/seed-secrets.sh](scripts/seed-secrets.sh) | | 合成 webhook 演练 | [scripts/fire-drill.sh](scripts/fire-drill.sh) | | 事件状态观察器 | [scripts/observe-incident.sh](scripts/observe-incident.sh) | | 邀请自己加入演练频道 | [scripts/join-drill-channel.sh](scripts/join-drill-channel.sh) | | CI 演练(由夜间工作流使用) | [scripts/ci-drill.sh](scripts/ci-drill.sh) | 设计 / 范围界定: | 文档 | 路径 | |----------|------| |D | [artifacts/prd-incident-response.md](artifacts/prd-incident-response.md) | | 架构 | [artifacts/architecture.md](artifacts/architecture.md) | | 测试计划 | [artifacts/test-plan.md](artifacts/test-plan.md) | | 安全威胁模型 | [artifacts/threat-model.md](artifacts/threat-model.md) |
标签:GNU通用公共许可证, Grafana, MITM代理, Node.js, Slack机器人, 子域名突变, 用户代理, 网络调试, 自动化, 自动化攻击, 运维