连接一个源
本页解释通用的连接器模型,以及如何把一个真实的源接入引擎。如果你只想连接一个编码代理,请从 连接 Claude Code 开始——那是协作路径上的一个具体的源,而本页是 它底下的模型。
一个源只做一件事:它观测一个外部系统并发出归一化的观测结果。它从不位于数据路径上、从不 代理(proxy)流量,也从不读取载荷。R/RW access map 是由源所报告的内容构建的,而非由拦截流经的 内容构建的。
具体而言,一个源实现一个小接口——Open(一次性配置)、Gather(运行,发出)、Close(释放)——
并在 Gather 期间通过一个 sink 一次一条地把观测结果交给引擎。引擎掌握调度:流式源(日志 tail、
接收端)在 Gather 中阻塞并持续发出,直到被取消;批处理源完成其工作后返回,由引擎决定何时再次
运行它。连接器从不拥有自己的计时器。
源可以发出的观测结果恰好只有三种:
| 观测结果 | 它携带什么 | 由谁使用 |
|---|---|---|
edge | 某个发起方(代理 / 身份 / 会话)以读/写模式触及了某个资源 | R/RW access map |
cost | 模型/提供方用量成本 | FinOps |
finding | 一项 guardrail / 红队 / 取证发现 | 安全 |
这个集合是经设计封闭的——第三方无法引入新的观测种类。引擎将每条发出的观测结果提升(lift) 到进程内事件总线上,模块在那里消费它,而无需与产生它的源耦合。具体到 access map,引擎会把连接器 的字符串引用解析为实体,并把观测结果合并进一条持久化的 access edge。
连接器采用 Apache-2.0 且从不导入 core
Section titled “连接器采用 Apache-2.0 且从不导入 core”一个连接器导入连接器 SDK,并且不从产品中导入其他任何东西。它从不导入 /core(AGPL 引擎)。
该边界在 CI 中强制执行,正是它让连接器得以在 Apache-2.0 下发布,也让第三方得以构建自己的连接器
而无需面对 copyleft 的摩擦。同一个连接器二进制无论在进程内还是通过 gRPC 在进程外运行,行为完全一致。
完整边界参见 开放内核与许可。
来源与置信度:为什么源很重要
Section titled “来源与置信度:为什么源很重要”每条 edge 都记录是哪个源产生了它以及一个置信度级别,且产品同时展示二者,而不是把它们
合并掉。一条 pg_audit READ 与一条 mcp_annotation 提示并非同等证据,绝不会被当作同等看待。
这两个置信度级别是诚实的,而非粉饰:
attributed——该访问被牢固地系到其发起方上(例如,审计轨迹中存在的某个每代理身份)。approximate——归因是推断出的或有损的(共享的服务账户,或一个其审计无法干净地区分调用者 的存储)。
访问模式是 unknown、read、write、readwrite 之一。unknown 是显式的、从不臆测——产品宁可
显示“我们无法对此分类”,也不会编造一个读/写标签。
第一方源的类别,按信号划分
Section titled “第一方源的类别,按信号划分”第一方源因其携带的信号而不同。请按你所观测的系统能够诚实地告诉你的内容来选择源。
pg_audit——PostgreSQL READ/WRITE
Section titled “pg_audit——PostgreSQL READ/WRITE”pgAudit 源 tail PostgreSQL 自身的结构化审计日志,并为每一次受审计的数据访问发出一条 edge。读/写
模式逐字取自 pgAudit 的 CLASS 字段(READ、WRITE、DDL)——从不从 SQL 文本中推断。发起方是日志将
该访问归因到的角色或 application_name。该连接器对日志文件是只读的;它从不连接到数据库,也从不
向数据库写入。这是干净层:一个在其原生轨迹中对访问进行分类的对象/关系型存储。
cloudtrail——AWS S3 readOnly
Section titled “cloudtrail——AWS S3 readOnly”CloudTrail 源读取 CloudTrail 日志文件并为每个 S3 事件发出一条 edge。读/写模式逐字取自 CloudTrail
的 readOnly 字段,从不推断。发起方是 CloudTrail 将该调用归因到的 IAM 主体。一个被许多调用者共享
的 assumed role 会被刻意标记为 approximate,因为轨迹无法区分其背后真正的调用者。
otel——协作式代理
Section titled “otel——协作式代理”这是协作路径:一个发出 OpenTelemetry 工具遥测的代理报告它做了什么,引擎将其摄取。Claude Code 是 这里的标准第一方源,它把 OTLP 遥测与 MCP 内省结合起来——参见 连接 Claude Code。协作式遥测在存在时是保真度最高的信号,但它 取决于代理是否协作,这正是为什么存在一个内核兜底。
ebpf——Tetragon 内核兜底(非协作路径)
Section titled “ebpf——Tetragon 内核兜底(非协作路径)”eBPF 源是这张图的反规避一半:协作路径看到代理报告了什么,而这一半看到内核实际做了什么——文件 读/写和网络连接——即使在某个代理关闭了自己的遥测时也能看到。它运行在代理的控制之外。
两条诚实的约束界定了它:
- 它不自行加载 eBPF 程序。内核捕获由 Tetragon 完成,后者作为一个单独的、经加固的服务部署; 本源是 Tetragon 事件流的只读消费者,自身不需要任何内核能力。
- 它对 TLS 体是盲的。它观测访问关系,绝不观测载荷。
它的 edge 始终是 approximate,原因很具体:内核把一次访问归因到一个进程或容器——一个运行时身份——
而非一个已解析的代理。访问本身是 ground truth(系统调用确实发生了);置信度限定的是归因,一旦
access-map 模块把该身份系到某个代理上,归因便会被升级。
mcp_annotation——不可信
Section titled “mcp_annotation——不可信”MCP 内省源列出一个服务器的工具、资源和提示词,并从每个工具的 readOnlyHint / destructiveHint
推导出一个读/写提示。按照 MCP 规范,除非服务器本身可信,否则客户端必须把这些注解视为不可信,
且其默认值是非对称的。因此这个信号是一个声明的能力提示,绝非已观测的访问:每一条这样的 edge
都是 approximate,且被标记为既非已观测也非已许可。它提供用于做差异比对的能力表面——而不是任何
事情确实发生过的证据。它必须由一个已观测的源加以佐证,绝不能单独信任。
硬性依赖:每代理身份
Section titled “硬性依赖:每代理身份”归因的优劣只取决于底层系统所记录的身份。原生审计把一次访问归因到一个凭据或角色,而非一个代理。
如果许多代理共享一个服务账户或一个连接池,每一次已观测的访问都会塌缩到那单一身份上,归因便变成
approximate——产品会如实说明,而不是假装它能区分这些代理。
要获得 attributed 的 edge,请给每个代理各自的身份。这是通往治理的桥梁:签发或强制执行每代理身份
正是让 access map 变得锐利的关键。
分层覆盖——务实一点
Section titled “分层覆盖——务实一点”覆盖按一个系统的审计表面能诚实支持到何种程度来分层:
- 干净(Clean)——原生地对访问分类的 SQL 数据库、对象存储和数仓(Postgres、S3 及同类)。读/写 逐字取用。
- 有损(Lossy)——其审计无法干净地区分读与写、或区分调用者与调用者的存储(文档存储和向量存储)。
edge 仍会落地,但常为
approximate。 - 被动方式不可能(Impossible passively)——没有可用被动审计表面的系统(内存缓存、嵌入式单文件 数据库)。没有诚实的 read-first 信号可供捕获;产品不会假装不是这样。
请有意地挑选层级。一个具备每代理身份的干净层存储,是 access map 最锐利之处。
连接一个真实的源
Section titled “连接一个真实的源”真实(非演示)源通过一个名为环境变量 OLIVARES_SOURCES_CONFIG 的单一运维配置文件连接,该文件
在引擎启动之前被读取。该配置是一个 JSON 文档;密钥存放于该文件中(按值引用),且从不由引擎
持久化。
该文档声明一个源的列表。每个源条目按 kind 选择一个连接器,命名其观测结果所属的租户,并携带连接器 自身的设置。其总体形态为:
{ "sources": [ { "name": "prod-postgres", "kind": "pgaudit", "tenant": "acme", "config": { "...": "connector-specific settings" } } ]}每连接器 config 块之上的字段——一个源名称、连接器 kind、所属 tenant,以及批处理源的一个可选
轮询间隔——构成稳定的连接契约。
一个未配置的源会如实告警
Section titled “一个未配置的源会如实告警”当什么都没连接时,引擎是 fail safe,而非大声崩溃:
- 如果
OLIVARES_SOURCES_CONFIG未设置,引擎在没有任何源的情况下启动。 - 如果该文件缺失、不可读或不是有效 JSON,引擎会告警并继续,没有任何源——它不会在启动时崩溃。
- 如果源列表为空,引擎会告警:没有连接器会进行摄取,并且该 estate 正在没有任何实时流量的情况下 运行。
在每种情形下,启动日志都会明白地告诉你没有连接任何真实数据源,而不是带着一张空 map 静默地显得健康。 如实告警就是这套设计:一张空的 access map 绝不应当看起来像一张干净的 map。
这在哪里运行
Section titled “这在哪里运行”数据平面——运行这些源的采集器——始终运行在客户基础设施上,无论 control plane 是单个 self-hosted 二进制、分布式部署,还是 air-gapped。源在本地观测,引擎进行摄取。产品没有强制遥测,控制平面默认也 不产生出站流量。只有你明确配置为跨越边界的内容才会跨越你的边界——对你的模型 API 的调用、你接入的 SIEM/webhook 输出,以及你配置时使用的外部嵌入提供商。部署拓扑参见 自托管 与 气隙安装。
- 连接 Claude Code——端到端的协作式
otel路径。 - 模块概览——消费这些观测结果的模块(清单、R/RW access map、 FinOps、安全)。
- 架构概览——连接器 SDK、事件总线与 access map 在设计中 所处的位置。