# Prophet HTTP API

[English](API.md)

Node 服务与 Cloudflare Worker 提供相同的 JSON 接口，响应均使用 `Cache-Control: no-store`。浏览器请求必须同源；跨站请求返回 403，接口不开放跨域权限。商家后端可以不带 `Origin` 请求服务。

个人 IP 自查、电商 IP 质量调查与网站防滥用调查使用同一套观测和证据分析核心。结果描述出口、环境差异与证据缺口，不提供经过校准的 IP 信誉或欺诈分数。

## 浏览器 SDK

在被检测的浏览器中，从 `https://prophet.offfold.com/sdk/prophet.js` 导入 `detect`、`analyze`、`verify`；导入不会启动采集。将采集绑定到已说明范围的用户操作，首页范围与外部目的服务见[隐私与检测说明](/privacy.html)。

```js
const controller = new AbortController();
const detections = await detect({
  publicNetwork: true,
  stun: true,
  behavior: { durationMs: 8_000 },
  signal: controller.signal,
});
```

| `detect()` 选项 | 默认值 | 作用 |
| --- | --- | --- |
| `network` | `true` | 读取接入网站自身同源的 `/api/network`；未部署时关闭 |
| `integrity` | `true` | 在临时 iframe 与 Worker 中比较环境声明 |
| `diagnostics` | `true` | 其他采集完成后执行临时渲染、存储、调度与文档实验 |
| `publicNetwork` | `false` | 请求固定的公网 HTTP 观测服务 |
| `stun` | `false` | 将本地 ICE 采集替换为固定 STUN 观测 |
| `behavior` | `false` | 采集前台事件聚合，接受 `{ durationMs }` |

`signal` 用于取消，`onDetection` 流式接收观测。主动诊断在被动与交互采集之后执行，避免临时存储写入影响先前的用量读取；新增模块不请求浏览器权限弹窗。

默认采集注册 283 项检查，其中跨环境一致性观测 31 项、主动诊断 30 项。示例与首页完整流程相同，最多登记 302 项观测，全部 15 项可选边缘字段均提供时为 317 项。这是采集项上限，不保证全部可读。`verify()` 默认启用公网 HTTP 与 15 秒交互采样，返回 `{ detections, analysis, evidenceGraph, observedAt }`，STUN 仍需主动开启；相同选项可用于调整或关闭模块。

| 接口 | 用途 | 模型凭据 |
| --- | --- | --- |
| `GET /api/network` | 观测到达本站的连接及白名单请求头 | 不需要 |
| `POST /api/detections/analyze` | 执行确定性关联检查，生成证据图 | 不需要，不调用模型 |
| `GET /api/agent/status` | 查询 BYOK 模式与运营方显式配置状态 | 不需要 |
| `POST /api/agent/analyze` | 执行有上限的模型与工具调查 | 调用者自己的模型 API Key |

## 网络观测

`GET /api/network` 返回 `peer`、`httpVersion`、`transport`、`headers`、`observedAt`；Cloudflare 提供边缘元数据时，Worker 还可返回 `edge` 数组。Node 信任套接字地址；Worker 仅在边缘运行环境边界归属 `CF-Connecting-IP`。转发地址声明与凭据不进入观测结构。这些数据描述到达本站的连接，不代表经过独立认证的身份。

## 检测结果分析

发送 `Content-Type: application/json`，无需 `Authorization` 或模型配置。

```http
POST /api/detections/analyze
Content-Type: application/json

{"detections":[{"id":"device.platform","group":"device","label":"Platform","value":"Windows","source":"navigator.platform","status":"info"}],"observedAt":"2026-11-02T00:00:00.000Z"}
```

请求接收 `detections`、可选的同结构 `previous` 和 ISO 8601 格式的 `observedAt`。每份快照最多 600 个不重复的信号 ID，当前结果不能为空。单条检测包含 `id`、`group`、`label`、`value`、`source`、`status`，可选 `note`、`sensitive`。状态为 `ok`、`warn`、`info`、`unsupported` 或 `error`，分组见[共享结构](../src/probes/types.ts)。HTTP 请求体上限为 512 KiB，同时受字段长度和报告总长度限制。

响应字段：

```ts
{
  schemaVersion: 1,
  observedAt: string,        // 调用者提供的采集时间
  serverObservedAt: string,  // 服务端处理时间
  receivedSignals: number,
  trust: 'client-observations',
  analysis: AnalysisResult,
  evidenceGraph: EvidenceGraph
}
```

`analysis` 包含 22 条确定性关联规则的结果和覆盖汇总；`evidenceGraph` 包含真实信号节点、稀疏的支持／冲突／上下文／缺失关系、假设、缺失证据及截断数量，最多保留 500 个节点、32 个检查假设，见[分析类型](../src/lib/analysis.ts)与[证据图类型](../src/lib/evidence-graph.ts)。缺失和读取失败表示证据不足；IPv4 与 IPv6 观测不会自动构成冲突。接口不请求模型，并忽略请求体中的模型、密钥和提供方地址字段。

图谱还返回 `priorities`，包含 `environment`、`ip-quality`、`anti-abuse` 三种调查侧重。其 `basis` 为 `configured-investigation-priority`，`calibrated` 为 `false`，`aggregation` 为 `maximum-per-evidence-family`。来源方式和可用证据覆盖用于调整配置优先级；同一证据家族内的重复字段与派生检查不累加。它用于排列调查顺序，不作商家准入决策或风险评分。

客户端观测可以被伪造。用户点击验证按钮只会开始采集；此响应不证明真人、身份、设备完整性或验证通过。商家应用需要依据返回的证据及其限制，在自己的服务端制定并执行业务决策。

## BYOK Agent 分析

Prophet 不内置预选或推荐的供应商与模型。浏览器 SDK `analyze()` 要求调用者明确提供 `apiKey`、`baseUrl`、`model`，不继承 HTTP 服务的运营配置。例如，使用前自行将 `https://your-provider.example/v1`、`your-model-id` 占位符替换为调用者选择的地址与模型。

运营方未配置上游与模型时，`GET /api/agent/status` 返回 `{"mode":"byok","requiresApiKey":true,"model":null,"providerConfigured":false}`。`model` 是显式配置的 `AGENT_MODEL` 值或 `null`；`providerConfigured` 表示运营方是否设置了非空 `AGENT_BASE_URL`。不要向状态接口发送模型密钥。

`POST /api/agent/analyze` 在上述检测请求体基础上增加非空 `question`，最多 2,000 字符。可选 `history` 最多六条 `{role: 'user' | 'assistant', content: string}`，每条最多 2,000 字符，只传用户已经可见的对话内容。

```http
Authorization: Bearer <caller-model-key>
X-Prophet-Model: your-model-id
Content-Type: application/json
```

每次请求必须提供调用者自己的模型密钥，仅允许可打印 ASCII 字符，最多 4,096 字符，不回退到共享服务端密钥。除非运营方显式配置 `AGENT_MODEL`，否则必须通过 `X-Prophet-Model` 指定模型，允许 1–200 个 ASCII 字母、数字或 `. / : @ _ -`。提供方地址只能由运营方显式设置 `AGENT_BASE_URL`，没有默认值，请求体与客户端请求头不能选择提供方。运营配置示例仅为 `AGENT_BASE_URL=https://your-provider.example/v1`、`AGENT_MODEL=your-model-id`，不是可直接使用或推荐的服务配置。模型额度归调用者的提供方账户。

先检查调用者认证：缺少 Key 时始终返回 401，即使提供方尚未配置。已认证的请求在缺少提供方地址时返回 503，不发起模型请求。提供方地址已配置、但请求头和运营配置均未指定模型时返回 400。检测结果分析不依赖这些配置。

成功返回 `AgentAnalysisResponse`，包含 `runId`、`model`、`summary`、`findings`、`nextChecks`、真实工具 `steps`、`durationMs` 及可选 `usage`，见[数据结构](../src/agent/types.ts)。工具证据有输出上限，推断不构成身份或恶意性裁决。

首页等待完整采集流程结束后，才运行使用者已配置的可选 Agent。公共模型配置初始为空，会话测试 Key 不作为产品预设或共享凭据。

## 限制与错误

两个 POST 分析接口共享每来源 IP 滚动一分钟最多四次已接收分析的限制。同一 IP、同一调用者密钥最多一个进行中的 Agent 请求，不同密钥可在 IP 总预算内独立并发。状态最多保存 512 个 IP，按 Node 进程或 Worker isolate 保存在内存中。429 响应包含 `Retry-After: 60`。

错误结构为 `{"error":"..."}`：400 输入结构无效或模型名缺失／无效；401 调用者模型密钥缺失、格式错误或认证失败（仅 Agent）；403 浏览器请求不同源；405 方法错误；413 请求过大；415 请求不是 JSON；429 超出频率；499 已取消；502 模型输出无效；503 未配置提供方地址或模型服务不可用；504 模型超时。检测处理异常返回 500。网络和检测接口不依赖模型凭据。
