关于 Web Resource Ledger
Web Resource Ledger(WRL)是可自托管的网页取证服务,为页面生成截图、渲染后的 HTML、HTTP 响应头及签名 WACZ 归档。其可分享的验证页面和离线验证 CLI 用于检查证据完整性。
主要功能
- 01捕获页面截图、HTML 和响应头
- 02生成 Ed25519 签名的 WACZ
- 03提供可分享的验证页面
- 04签发捕获过程认证 PDF
- 05提供离线验证 CLI
适用场景
- 01保存网页在特定时间的内容证据
- 02分享可供他人验证的网页捕获记录
- 03使用 CLI 离线核验 WACZ 归档
MCP 相关
WRL 将捕获、获取、列表和验证四项操作作为 MCP 工具提供,供兼容的 Agent 或 IDE 调用。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://api.webresourceledger.com/mcpclaude mcp add --transport http benpeter-web-resource-ledger https://api.webresourceledger.com/mcp{"mcpServers":{"benpeter-web-resource-ledger":{"type":"http","url":"https://api.webresourceledger.com/mcp"}}}在 Cursor 中打开{"servers":{"benpeter-web-resource-ledger":{"type":"http","url":"https://api.webresourceledger.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"benpeter-web-resource-ledger":{"type":"http","url":"https://api.webresourceledger.com/mcp"}}}{"mcpServers":{"benpeter-web-resource-ledger":{"serverUrl":"https://api.webresourceledger.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://api.webresourceledger.com/mcp需要授权工具
详细介绍
Web Resource Ledger(WRL)
为网页内容提供密码学证据——记录页面呈现的样子和时间,并提供任何人都能验证的证明。
提交一个 URL,即可获取截图、渲染后的 HTML、HTTP 响应头和经过 Ed25519 签名的 WACZ 捆绑包。任何人都能使用验证 URL,无需账号。部署在你自己的基础设施上;捕获内容、密钥和证据都由你掌控。
WRL 几乎完全由大模型(Claude)构建,由人类指挥工作。从 MVP 到生产环境的每个阶段,都记录在 docs/evolution/ 中。提示词、Agent 讨论、决策和结果全部公开。
如需身份验证、验证、批量捕获和 MCP 集成的完整指南,请参阅 docs.webresourceledger.com。
状态: 生产服务,采用单运营方部署。路线图的三个阶段均已完成。API 尚未达到 1.0 版本,但功能可用,已部署并承载真实流量。
你将获得什么
一次 API 调用即可生成:
- 双重截图(PNG)——分别记录关闭和未关闭 Cookie 同意提示后的页面,因此既保留提示横幅,也保留底层页面内容
- 渲染后的 HTML ——JavaScript 执行后的 DOM
- HTTP 响应头 ——捕获时服务器返回的响应
- 已签名的 WACZ 捆绑包 ——打包所有制品、计算哈希并使用 Ed25519 签名
- 验证 URL ——可分享的链接,任何人都可用来确认真实性
- FRE 902(13) 认证 PDF ——
GET /v1/captures/{captureId}/certificate返回一份经过签名的 PDF,说明捕获过程和完整性证据,旨在支持 Rule 902(13) 自我认证依据
内容安全
WRL 会在开始捕获前,使用威胁情报数据库筛查每个提交的 URL:
- 被识别为威胁(恶意软件、网络钓鱼等)的 URL 会在提交时被拒绝,并返回 422 响应。
- 每天重新扫描已有的捕获记录。未能通过重新筛查的捕获记录会被隔离:元数据仍可访问,制品下载则返回 451。
- 即使威胁情报服务不可用,筛查功能也会平稳降级,捕获照常进行。捕获记录上的
threatCheck字段会反映结果:pass、fail或unavailable。
通过环境中的 GOOGLE_WEB_RISK_API_KEY 配置服务(见下文的步骤 8b)。此密钥为可选项;不提供时将停用筛查,所有捕获记录的 threatCheck 均为 unavailable。
使用方法
需要运行中的 WRL 实例。请参阅下文的设置。
export WRL_API_KEY=your_tenant_api_key
租户密钥通过管理 API 创建(见步骤 8a)。对于使用旧版静态密钥的部署,WRL_API_KEY 是你的 CAPTURE_API_KEY 值。
以下示例使用 api.webresourceledger.com。本地开发时请替换为 localhost:8787;自托管时则替换为你自己的部署 URL。
步骤 1:提交捕获请求
curl -X POST https://api.webresourceledger.com/v1/captures \
-H "Authorization: Bearer $WRL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
{
"id": "cap_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"statusUrl": "https://api.webresourceledger.com/v1/captures/cap_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6/status",
"note": "Use GET /v1/captures to list and search your captures."
}
你始终可以访问自己的捕获记录。使用 GET /v1/captures 列出记录,或保存捕获 ID 以便直接访问。
步骤 2:轮询完成状态
curl https://api.webresourceledger.com/v1/captures/cap_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6/status
持续轮询,直到 status 为 complete 或 failed。完成后,响应中会包含 captureUrl。
步骤 3:获取制品
curl https://api.webresourceledger.com/v1/captures/cap_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
返回元数据和已签名的制品 URL(screenshot、html、headers、wacz),以及 verifyUrl。
步骤 4:验证存档包
curl https://api.webresourceledger.com/v1/verify/cap_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
返回包含最多四项检查的 JSON 验证结果:artifactHashes、bundleHash、signature,以及(对于新捕获)timestamp。时间戳检查会验证在捕获时获取的 RFC 3161 独立时间戳。旧版捕获会返回三项检查。第 3 步中的 verifyUrl 也会在浏览器中显示为易于阅读的页面。
捕获 URL 可直接分享——任何拥有捕获 ID 的人都可以访问该捕获及其构件。无需令牌。
分享: 捕获 URL 可直接分享。任何拥有该 URL 的人都可以访问捕获记录及其所有构件。若要证明真实性,请分享
verifyUrl,它会显示易于阅读的验证页面。
离线验证
若要进行独立的离线验证(包括完整的 CMS/PKCS#7 证书链验证),请使用 CLI 工具:
npx @w-r-l/verify capture.wacz --origin https://api.webresourceledger.com
详情请参阅 packages/verify/。
查找捕获
GET /v1/captures 会列出你的捕获(需要 API 密钥)。可用它浏览并找回捕获 ID。
curl https://api.webresourceledger.com/v1/captures \
-H "Authorization: Bearer $WRL_API_KEY"
{
"data": [
{
"id": "cap_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"status": "complete",
"url": "https://example.com",
"createdAt": "2024-01-15T10:30:00.000Z",
"completedAt": "2024-01-15T10:30:45.123Z"
}
],
"pagination": {
"cursor": null,
"hasMore": false,
"limit": 20
}
}
可选查询参数:limit(1-100,默认值为 20)、cursor(用于分页)、status(pending、complete、failed 或 quarantined)。
每个 IP 每分钟最多可进行 10 次捕获。每个 IP 每分钟最多可进行 60 次验证。错误响应采用 RFC 9457 application/problem+json 格式。完整详情请参阅 openapi.yaml。
设置
前提条件
- 已安装并完成身份验证的 Wrangler CLI
- Node.js 22+(参见
.nvmrc) - 已启用 R2 和 Browser Rendering 的 Cloudflare 帐户
1. 安装依赖项
npm install
2. 创建 D1 数据库
wrangler d1 create wrl-metadata
在 wrangler.toml 的 [[d1_databases]] 下,将 database_id 更新为返回的 ID。然后应用迁移:
wrangler d1 migrations apply wrl-metadata
2a. 创建 KV 命名空间(速率限制)
KV 仅用于存储速率限制计数器。创建命名空间:
wrangler kv namespace create wrl-kv
使用返回的 id 和 preview_id 更新 wrangler.toml。
3. 创建 R2 存储桶
wrangler r2 bucket create wrl-captures
wrangler r2 bucket create wrl-captures-preview
4. 配置捕获 API 密钥(旧版回退方案)
CAPTURE_API_KEY 是一个静态 Bearer 令牌;当在 D1 中找不到租户密钥时,它会作为回退方案使用。对于新的部署,可以考虑设置管理 API(步骤 8a)并改为创建租户密钥。对于现有部署,在迁移期间此密钥仍可继续使用。
在上面的使用示例中,它对应 $WRL_API_KEY。
生成密钥:
openssl rand -hex 32
设置生产环境密钥:
wrangler secret put CAPTURE_API_KEY
对于本地开发,将其添加到 .dev.vars:
CAPTURE_API_KEY=<hex string from the command above>
安全: 切勿将此值提交到版本控制中。.dev.vars 已列入 .gitignore。
5. 配置签名密钥
WRL 使用 Ed25519 对 WACZ 存档包签名。签名密钥为可选项——如果未设置 SIGNING_KEY,捕获仍会成功完成,但不会生成 WACZ 存档包(截图、HTML 和标头仍会保存)。
生成密钥对:
node scripts/generate-signing-key.js
该脚本会输出私钥(PKCS8 DER,base64)以及对应的公钥(原始格式,base64)。公钥会自动嵌入每个已签名的存档包中以供验证——无需单独分发。
设置生产环境密钥:
wrangler secret put SIGNING_KEY
# Paste the private key (PKCS8 DER, base64) when prompted
对于本地开发,将其添加到 .dev.vars:
SIGNING_KEY=<base64 string from the script>
安全: 切勿将私钥提交到版本控制中。.dev.vars 已列入 .gitignore。
6. 配置 IP 哈希种子(推荐)
IP_HASH_SEED 是一个 HMAC 种子,用于在 IP 地址写入日志前对其进行哈希处理。若未设置该值,日志条目将无法关联 IP,因而无法用于滥用行为分析。
生成种子:
openssl rand -hex 32
设置生产环境密钥:
wrangler secret put IP_HASH_SEED
对于本地开发,将其添加到 .dev.vars:
IP_HASH_SEED=<hex string from the command above>
7. 配置 Coralogix 日志摄取(生产环境可观测性必需)
CORALOGIX_SEND_KEY 是用于向 Coralogix 摄取结构化日志的 API 密钥。没有此密钥,Worker 仍会正常运行,但日志只会输出到控制台,不会进行结构化日志摄取。不使用 Coralogix 的分支开发者实际上可以不配置此密钥。
在 Coralogix 控制面板的 Settings > Send Your Data > API Keys 下查找发送密钥。
设置生产环境密钥:
wrangler secret put CORALOGIX_SEND_KEY
本地开发时,结构化日志会输出到控制台。运行 wrangler dev 无需密钥。
8. 配置 CORS 来源(可选)
CORS_ORIGINS 是允许用于 CORS 预检响应的来源列表,多个来源以逗号分隔。只有基于浏览器的客户端会直接调用 API 时才需要配置。
将其设为 wrangler.toml 中的环境变量(不是密钥):
[vars]
CORS_ORIGINS = "https://app.example.com,https://www.example.com"
如果未设置,浏览器发起的跨域请求会被阻止。服务器到服务器的请求不受影响。
8a. 配置管理员密钥(管理租户密钥必需)
ADMIN_KEY 是管理员 API(/v1/admin/keys)的 bearer token。它授予创建、列出和撤销租户 API 密钥的权限,但不授予捕获或读取权限。
生成密钥:
openssl rand -hex 32
设置生产环境密钥:
wrangler secret put ADMIN_KEY
本地开发时,将其添加到 .dev.vars:
ADMIN_KEY=<hex string from the command above>
部署后,创建第一个租户密钥:
curl -X POST https://api.webresourceledger.com/v1/admin/keys \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"tenantId": "default", "scopes": ["capture"], "name": "default-key"}' | jq .
后续将返回的 key 值用作 $WRL_API_KEY。完整的迁移操作手册请参阅 OPERATIONS.md。
**安全:**切勿将此值提交到版本控制中。.dev.vars 已列入 .gitignore。
8b. 配置内容安全筛查(可选)
GOOGLE_WEB_RISK_API_KEY 可在捕获之前和每日重新扫描期间启用 URL 威胁筛查。没有此密钥,所有捕获都会报告 threatCheck: unavailable,且不会屏蔽任何 URL。
在启用 Web Risk API 的 Google Cloud Console 中获取密钥,然后设置生产环境密钥:
wrangler secret put GOOGLE_WEB_RISK_API_KEY
本地开发时,将其添加到 .dev.vars:
GOOGLE_WEB_RISK_API_KEY=<your api key>
**安全:**切勿将此值提交到版本控制中。.dev.vars 已列入 .gitignore。
9. 部署
wrangler deploy
步骤 1 至 9 是一次性设置。初次部署后,每次向 main 推送时,CD 流水线都会自动处理 staging 和 production 部署。有关完整部署流程、环境配置、回滚流程,以及密钥在 Worker 运行时、GitHub CI 和本地开发环境之间的映射方式,请参阅 OPERATIONS.md。
MCP 服务
WRL 将全部四项核心操作——捕获、检索、列出和验证——作为 MCP 工具提供。任何兼容 MCP 的 Agent 或 IDE 都可以捕获网页并验证证据,无需编写 HTTP 客户端代码。
有关设置说明和工作流示例,请参阅 MCP Server Guide。本地参考文档 docs/mcp.md 涵盖 Claude Code、Cursor、Windsurf 和通用客户端,并提供完整的工具参考。
Web UI
WRL 提供基于浏览器的界面,可提交捕获任务并浏览
结果。访问 WRL 部署上的 /ui 即可使用。身份验证需要具备 capture 和 read 范围的 WRL API 密钥。
UI 由 Worker 直接提供服务,无需单独托管或配置 CORS。
开发
有关本地开发设置、测试约定和贡献指南,请参阅 CONTRIBUTING.md。
有关部署、回滚和环境设置,请参阅 OPERATIONS.md。
Staging
wrangler.toml 包含一个 [env.staging] 配置,其中有独立的 R2 存储桶、D1 数据库和 KV 命名空间(仅用于速率限制)。部署前,必须在自己的 Cloudflare 账户中创建这些资源(与上文第 2–3 步相同,但作用于 staging 环境)。
创建 staging D1 数据库:
wrangler d1 create wrl-metadata-staging
更新 wrangler.toml 中 [[env.staging.d1_databases]] 下的 database_id,然后应用迁移:
wrangler d1 migrations apply wrl-metadata-staging --env staging
创建 staging KV 命名空间(仅用于速率限制):
wrangler kv namespace create KV --env staging
使用返回的 ID 更新 wrangler.toml 中 [env.staging.kv_namespaces] 下的 id 字段。
创建 staging R2 存储桶:
wrangler r2 bucket create wrl-captures-staging
然后部署到 staging:
wrangler deploy --env staging
合并到 main 后,staging 会通过 deploy-staging.yml 自动部署。必须单独为 staging 环境设置密钥:
wrangler secret put CAPTURE_API_KEY --env staging
wrangler secret put SIGNING_KEY --env staging
# repeat for any other secrets
冒烟测试会针对线上部署运行。设置 SMOKE_URL 和 SMOKE_API_KEY,然后执行:
npm run smoke
路线图
WRL 遵循三幕式开发计划。三幕均已完成:
- 坚实基础(已完成)——列表端点、密钥版本管理、CORS、安全加固。弥合了单运营者使用中的信任缺口。
- 可验证证据(已完成)——RFC 3161 时间戳、每租户密钥、审计日志。使存档能够独立验证。
- 基础设施(已完成)——MCP 服务、Web UI、批量存档、定时存档、文档站点、落地页、用量计量、Webhooks。将 WRL 扩展为一个平台。
持续更新的待办事项请参阅 docs/backlog.md,详细追踪请参阅 GitHub issues。
WRL 的构建过程
WRL 是一项面向生产环境的 Web 证据服务,也是一项有文档记录的 LLM 驱动软件开发实验。由人类定义构建内容并做出产品决策;LLM(Claude)编写了几乎所有代码、测试、基础设施和文档。
完整的构建历史记录位于 docs/evolution/——涵盖 60 多个阶段,包括架构决策、Agent 之间的分歧以及人类的覆盖决策。如果你想了解 LLM 驱动开发在生产规模下的实际情况,可以从这里开始。
参考
密钥轮换
密钥轮换是安全的——轮换后,旧存档仍可验证。每次对存档签名时,签名密钥都会自动归档。每个密钥由 keyId 标识:原始 32 字节公钥的 SHA-256 哈希值的前 8 个十六进制字符。keyId 存储在 WACZ 包的 signedData.signatures 数组(v0.2.0)或 signedData 本身(v0.1.0 旧版)中,也存储在 D1 存档记录中。验证时,系统会通过 keyId 查找对应的历史密钥,而不会默认使用当前密钥。
轮换步骤:
- 生成新的密钥对:
node scripts/generate-signing-key.js - 更新生产环境密钥:
wrangler secret put SIGNING_KEY - 更新
.dev.vars中的本地开发密钥(如适用)
新存档会使用新密钥签名。现有存档会使用签署它们的归档密钥进行验证。/.well-known/signing-keys 端点会列出完整的密钥归档,供第三方验证者使用。
公钥端点
GET /.well-known/signing-key 会返回当前的 Ed25519 公钥。第三方验证者可以获取该密钥,而无需信任嵌入在各个 WACZ 包中的 publicKey。响应会在边缘缓存 1 小时。
{
"algorithm": "Ed25519",
"publicKey": "<base64-encoded raw 32-byte key>",
"keyId": "<8-char hex fingerprint>"
}
keyId 是原始公钥字节的 SHA-256 哈希值的前 8 个十六进制字符。验证历史存档时,可用它与密钥归档中的条目匹配。
密钥归档端点
GET /.well-known/signing-keys 会列出所有历史签名密钥。使用此端点验证由任意密钥签名的捕获内容,而不仅限于当前密钥。
{
"keys": [
{
"keyId": "<8-char hex fingerprint>",
"algorithm": "Ed25519",
"publicKey": "<base64-encoded raw 32-byte key>",
"archivedAt": "<ISO 8601 timestamp>"
}
]
}
第三方验证器:将 WACZ 包的 signedData(v0.1.0)或 signedData.signatures 数组(v0.2.0)中的 keyId 与此列表匹配,以获取用于签名验证的正确公钥。此端点的速率限制与单个密钥端点相同。
健康状态端点
GET /health 会返回当前服务状态、法律文档 URL 和构建身份元数据。
{
"status": "ok",
"legal": { "terms": "<url>", "policy": "<url>" },
"build": { "commit": "<sha>", "version": "<semver>", "env": "production", "deployedAt": "<iso8601>" }
}
通过 CI 部署时会包含 build 对象(通过 wrangler --define 在构建时注入)。本地开发时不会包含此对象。适用于正常运行时间监控、冒烟测试和部署验证。
响应标头
所有响应都包含:
Link-- 指向服务条款 URL,带有rel="terms-of-service"。每个响应中都会包含。Strict-Transport-Security-- 包含preload和includeSubDomains。每个响应中都会包含。X-RateLimit-Limit-- 端点的速率限制上限。来自受速率限制的端点(捕获、验证、签名密钥端点)的响应中会包含。
法律条款
使用此 API 即表示您同意服务条款。
许可证
PolyForm Shield 1.0.0 -- 可获取源代码。您可以出于任何目的使用、修改和自托管 WRL,但不得提供具有竞争关系的网页捕获服务。完整条款请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。