关于 Spurvik EU AI Act
Spurvik EU AI Act 是面向开发者的合规工作控制基础设施,提供风险分类、审计记录与人工监督接口。其 MCP 工具可扫描 URL、生成多语言 Art. 50 标识并辅助检查 SDK 与审计记录;它不构成认证或法律意见。
主要功能
- 01实时 URL 扫描与风险分类
- 02生成 24 种欧盟语言标识
- 03检查 HMAC 收据与审计记录
- 04查找未包装的调用
- 05提供设置片段和标记说明
适用场景
- 01扫描线上 URL 并检查 AI Act 风险
- 02生成多语言 Art. 50 透明度标识
- 03解释 HMAC 收据并检查调用记录
MCP 相关
提供远程 Streamable HTTP MCP 服务,无需 API Key,包含 URL 扫描、风险分类、Art. 50 标识生成及 SDK 和审计辅助工具。另提供本地 stdio MCP 服务。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://console.spurvik.com/api/mcpclaude mcp add --transport http com-spurvik-eu-ai-act https://console.spurvik.com/api/mcp{"mcpServers":{"com-spurvik-eu-ai-act":{"type":"http","url":"https://console.spurvik.com/api/mcp"}}}在 Cursor 中打开{"servers":{"com-spurvik-eu-ai-act":{"type":"http","url":"https://console.spurvik.com/api/mcp"}}}在 VS Code 中打开{"mcpServers":{"com-spurvik-eu-ai-act":{"type":"http","url":"https://console.spurvik.com/api/mcp"}}}{"mcpServers":{"com-spurvik-eu-ai-act":{"serverUrl":"https://console.spurvik.com/api/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
Spurvik
Spurvik 是一个开发者控制平面,支持你开展 EU AI Act 相关工作:哈希链式记录保存、人类监督接口和透明度声明。它是基础设施,不是合规性评估、认证或法律建议。
Regulation (EU) 2024/1689 是法律文件。以下日期依据 AI Omnibus 时间表和欧盟委员会《AI 生成内容透明度行为守则》。请咨询法律顾问,确认这些规定如何适用于特定系统。
实时沙盒、托管式欧盟控制台和入门模板
不是开发者?在 Lovable、Bolt、Replit 或 WordPress 中进行氛围编程? 获取 24 小时《AI 法案》代办设置服务(一次性收费 €199,包含完整 1 年 Pro,价值 €190):我们会在 24 小时内为你安装支持 24 种语言的第 50 条声明、服务器调用日志记录和人工审批关卡。自助结账:console.spurvik.com/signup?plan=concierge。
| 界面 | URL | 说明 |
|---|---|---|
| 交互式沙盒和本地代码检查 | console.spurvik.com/sandbox | 无需登录、无 Cookie——预览 <AIDisclosureLabel />(支持 24 种欧盟语言),检查 HMAC 回执,并在浏览器中离线运行技术栈和代码片段检查。 |
| 24 种语言的第 50 条标签工作室 | console.spurvik.com/labels | 实时交互式预览,涵盖全部 5 种第 50 条场景、24 种欧盟官方语言和可选的欧盟 AI 图标——一键导出 spurvik/react JSX 或 badge.js <script>。 |
托管式欧盟控制台(法兰克福 fra1) | console.spurvik.com/signup | 开放自助注册:免费 €0/月(每月 10k 个事件,保留 30 天)· Pro €19/月或 €190/年(每月 250k 个事件,保留 90 天,托管式人工审核队列,DPO .md 和附件 IV 草稿导出)· Team €79/月或 €790/年 · 24 小时《AI 法案》代办设置服务 €199 一次性收费,含 1 年 Pro(结账)(不含增值税 · 仅限 B2B)。 |
| 免费欧盟《AI 法案》风险检查和第 50(2) 条 C2PA 检查器 | console.spurvik.com/risk-check · console.spurvik.com/c2pa | 无需登录。回答几个问题即可自评《AI 法案》风险等级,并检查图像是否带有 C2PA 来源信息。不能替代法律建议。 |
Agent 技能(skills.sh)和官方 MCP 注册表(7 个免密钥工具) | npx skills add spurvik/skills · com.spurvik/eu-ai-act → https://console.spurvik.com/api/mcp | 远程 Streamable HTTP,无需 API 密钥:spurvik_scan_live_url、spurvik_classify_ai_act_risk、spurvik_generate_art50_badge,以及 4 个 SDK/审计工具(spurvik_setup_snippet、spurvik_find_unwrapped_calls、spurvik_explain_receipt、spurvik_marking_hooks)。技能源码:spurvik/skills。 |
WordPress、Framer 和 shadcn/v0 资源 | spurvik-eu-ai-act-wp.zip · spurvik-framer-badge.tsx · article-50-badge.json | WordPress 插件(上传插件)、Framer 代码组件,以及 npx shadcn@latest add https://spurvik.com/r/article-50-badge.json。它们都会渲染相同的 badge.js 声明;data-attribution="false"(React:attribution={false})可为 Pro/代办服务白标隐藏 “Art. 50 · Spurvik” 链接。 |
| 文档和框架指南 | spurvik.com/docs | 可复制粘贴的配置指南,适用于 Next.js / Vercel AI SDK、LangGraph、Mastra、OpenAI Agents、Lovable / Replit、WordPress / Shopify / Webflow、Cursor / Claude Code MCP,以及 n8n。 |
| 一键 n8n 入门工作流 | spurvik.com/r/n8n-art50-starter.json | 在可自托管的 n8n 中直接导入 URL(Import from URL),并使用 [email protected]。 |
| 一键 GitHub Actions PR 关卡 | spurvik.com/r/github-action-spurvik-check.yml | 放入 .github/workflows/spurvik-check.yml,即可使用 spurvik-mcp check . --ci 离线扫描 PR。 |
此代码仓库包含的内容
里程碑 1–4,面向欧盟市场。
| 部件 | 作用 |
|---|---|
packages/sdk | 面向 OpenAI、Anthropic 和 Gemini 风格客户端的 withSpurvik() 包装器、适用于 Vercel AI SDK 的 spurvikMiddleware(),以及 Mastra、OpenAI Agents 和 LangGraph 适配器。 |
packages/react | 始终可见的第 50 条标签,支持全部 24 种欧盟语言。 |
packages/core | 哈希、来源签名、文本标记钩子、审计链检查、Webhook 签名。 |
packages/mcp | 本地 stdio MCP 服务。设置代码片段、未包装调用扫描、HMAC 回执说明、标记钩子说明、实时第 50(1) 条 URL 扫描、欧盟《AI 法案》风险等级映射,以及支持 24 种语言的第 50 条徽章生成器。以 [email protected](MIT)发布到 npm。工作区软件包 packages/mcp(1.0.5)。 |
packages/n8n-nodes-spurvik | 原生 n8n 社区节点(SpurvikEuAiActGuard)和可导入的 Make.com 蓝图(make-com-blueprint.json),用于第 50(1) 条通知,以及高风险 AI 系统的第 12 条 HMAC-SHA256 摘要和第 14 条 ask_human() 关卡;可选择与 console.spurvik.com 同步,另提供无需密钥的 扫描实时域名(第 50 条和客户简报) 操作。软件包版本 [email protected](MIT)。 |
examples/ | 可运行的开发者模板:Next.js + Vercel AI SDK(nextjs-vercel-ai-sdk)、LangGraph + Mastra + OpenAI Agents(langgraph-mastra-openai-agents)、9 渠道 ask_human() 路由器(slack-telegram-linear-ask-human 和 multi-channel-hitl.ts)、n8n 和 Make.com 工作流(n8n-make-import),以及 GitHub Actions CI 检查(github-actions-ci-check)。 |
为支持远程生物识别系统(附件 III 第 1(a) 点;高风险要求自 2027 年 12 月 2 日起适用)第 12(3) 条日志记录而设计的功能位于控制平面中。双人确认是一项产品设置,会检查是否由两个不同的成员账户确认了该决定。图像标记支持位于 packages/c2pa。请从源代码构建该目录。它不是已发布的 npm 软件包。其 package.json 设置了 "private": true 和 "license": "MIT"。
快速入门
许可。
packages/sdk(以spurvik和spurvik-sdk发布)以及packages/react(以spurvik/react导出项发布)采用 MIT 许可证(版权所有 (c) 2026 EyeTea Solutions ApS (CVR 37093378)),且不提供任何担保。packages/core需从源代码构建,并打包在上述已发布的软件包中。packages/mcp以spurvik-mcp-server发布。packages/c2pa需从源代码构建,设置了"private": true和"license": "MIT",且未在 npm 上发布。https://console.spurvik.com 上的控制台是托管服务。其源代码不在此代码仓库中,MIT 许可证也不涵盖该服务。请参阅下文的 商标。
操作指南见 docs/quickstart.md。测试过程中遇到的错误见 docs/troubleshooting.md。通俗易懂的概述见 docs/onboarding-startups-smes.md。
指南:docs/quickstart.md、docs/5-minute-quickstart.md、docs/sandbox-first-5-minutes.md、docs/langgraph-quickstart.md、docs/hitl-approval-mapping.md、docs/console-onboarding.md、docs/adapters-quick-cards.md、docs/claude-code-plugin.md、docs/faq-additions.md、docs/faq-sandbox-2x2.md、docs/faq-console-and-quickstart.md、docs/faq-hitl-and-plugin.md,以及 docs/faq-art50-marking-and-pl-locale.md。
获取软件包。 从 npm 安装实时 MIT 软件包。此前在 spurvik.com/sdk/latest.tgz 提供的构建版本不是此 SDK,不受支持,切勿依赖它来检查记录。
(a) npm:
npm install [email protected] [email protected]
spurvik 和 spurvik-sdk 发布的是同一个 SDK。请将其导入为 spurvik。子路径包括 spurvik/ai、spurvik/mastra、spurvik/langgraph、spurvik/openai-agents、spurvik/channels 和 spurvik/react。
(b) 本地 MCP 服务。自 1.0.3 起,必须指定 --root:
npm i -D [email protected]
./node_modules/.bin/spurvik-mcp-server --root .
在你的应用中(这是一个 ES 模块项目,因为示例使用了顶层 await):
npm pkg set type=module
npm install openai [email protected]
包装调用并检查记录:
import OpenAI from "openai";
import { provenanceOf, verifyProvenanceSignature, withSpurvik } from "spurvik";
const ai = withSpurvik(new OpenAI(), {
apiKey: process.env.SPURVIK_API_KEY!, // spurvik_live_…
signingSecret: process.env.SPURVIK_SIGNING_SECRET!,
contentHash: { mode: "keyed", secret: process.env.SPURVIK_CONTENT_HASH_SECRET! },
baseUrl: process.env.SPURVIK_BASE_URL!, // the SDK throws without it when NODE_ENV is production
riskTier: "limited_art50", // Sample value. Set your own classification (as provider or deployer); Spurvik does not classify your use case.
article50Disclosure: false, // set true only when an interaction notice is shown
onTelemetryError: (error) => console.error("Spurvik telemetry not delivered:", error),
});
const completion = await ai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
});
const record = await provenanceOf(completion);
// Argument order: record first, signing secret second. Swapped arguments return false.
const matches = await verifyProvenanceSignature(record!, process.env.SPURVIK_SIGNING_SECRET!);
await ai._spurvik.shutdown(); // scripts: send queued telemetry before exit
provenanceOf(res) 会返回附加到非流式响应的已签名来源记录。对于流,它会返回一个记录 Promise:读取流,然后 await provenanceOf(stream)。存在记录意味着可以检查签名。这并非符合性评估。
当已签名字段与使用该密钥生成的签名相匹配时,matches 为 true。任何已签名字段发生更改,都会导致检查返回 false,除非修改者也使用同一密钥重新签名。因此,匹配表明已签名字段仍与使用该密钥生成的签名相匹配。任何持有该密钥的人都能生成匹配的签名,因此请限制密钥持有者。
密钥和环境变量。 项目 API 密钥的格式为 spurvik_live_ 后接至少 32 个 base64url 字符。它会作为 Bearer token 发送,服务器只存储其 SHA-256 哈希值。SPURVIK_SIGNING_SECRET 和 SPURVIK_CONTENT_HASH_SECRET 保留在调用方,不会发送到控制平面。请妥善保管这些密钥:丢失密钥后,将无法再检查使用该密钥签名的记录。这些密钥均没有内置默认值。SDK 不会自行读取 SPURVIK_API_KEY、SPURVIK_SIGNING_SECRET 或 SPURVIK_CONTENT_HASH_SECRET;你的代码需要将它们传入。项目密钥使用 spurvik_live_ 前缀。披露密钥使用 spurvik_pub_ 前缀。已发布的 spurvik 和 spurvik-sdk 软件包在运行时不会读取 SPURVIK_* 或 AEGIS_* 环境变量。请在代码中传入 apiKey、signingSecret、contentHash.secret 和 baseUrl。这些读取仅存在于此代码库中:packages/core/src/telemetry-policy.ts 中的 vendorTelemetryMode() 会读取 SPURVIK_TELEMETRY,然后读取 AEGIS_TELEMETRY,而已发布的软件包不会调用它。packages/c2pa/src/index.ts 会先读取 SPURVIK_C2PA_CERT_PEM,再读取 AEGIS_C2PA_CERT_PEM;并先读取 SPURVIK_C2PA_KEY_PEM,再读取 AEGIS_C2PA_KEY_PEM。该目录用于从源代码构建,不包含在已发布的 tarball 中。packages/sdk/src/telemetry-exit.child.ts 是代码库中的测试脚本,只会读取 SPURVIK_BASE_URL。packages/sdk/tsup.config.ts 会在代码库构建期间读取 SPURVIK_SDK_DIST。packages/mcp 会读取 SPURVIK_MCP_ROOT 和 SPURVIK_SIGNING_SECRET。这些读取不会出现在 spurvik 或 spurvik-sdk 中。
baseUrl 是 SDK 遥测数据和 halt 流的发送地址。对于托管控制台工作区,该地址为 https://console.spurvik.com。在生产环境中,如果省略此参数,SDK 会抛出错误。在开发和测试中,默认地址仍为 http://127.0.0.1:43123。
**如果 baseUrl 无法访问,**封装后的模型调用仍会成功并返回其记录(high_annex3 除外;该模式会在故障时拒绝执行)。在短脚本中,遥测事件会丢失:onTelemetryError 被调用一次,await shutdown() 返回,进程以退出码 0 退出。长时间运行的进程会调用一次 onTelemetryError。在此构建版本中,刷新失败后排队的事件会保留在内存中(最多 500 个事件;优先丢弃最早的事件),并在之后刷新时发送:下次执行封装后的调用时、执行 await ai._spurvik.shutdown() 时,或进程自行结束时发送一次。不会通过定时器重试。已经刷新失败的事件不会在进程自行结束时再次尝试,除非此后又有事件排队;调用 process.exit() 或使用 Ctrl+C 等信号会跳过最后一次刷新。在进程退出前调用 await ai._spurvik.shutdown(),可让排队的事件再尝试发送一次(默认最长等待 8 秒)。对于 high_annex3,超时的停止检查会抛出 SpurvikOversightTimeoutError(一种 SpurvikHaltedError);控制平面的错误响应则会抛出 SpurvikApiError,它是 SpurvikError,而不是 SpurvikHaltedError;这两种情况下都不会调用提供方。请参阅 docs/troubleshooting.md。在此版本中,不要将控制平面作为这些事件的唯一副本。也请自行留存记录。
article50Disclosure 默认为 false。只有在你明确说明已显示第 50(1) 条交互告知时,才将其设为 true。此标志用于配置,并不代表已确认显示该告知,也不代表该告知已充分。
riskTier 是你自己的分类(作为提供方或部署方);Spurvik 不会对你的用例进行分类。
minimal—— 默认不配置透明度或高风险控制。limited_art50—— 第 50 条透明度支持(交互告知、可选标记钩子)。high_annex3—— 适用于附件 III 下的高风险用途。封装器会在推理前检查人工停止信号。
第 12 条(记录保存)以及第 11 条和附件 IV(技术文档)自 2027 年 12 月 2 日 起适用于高风险(附件 III)系统。自 2027 年 12 月 2 日起,第 14 条适用于附件 III 所列的高风险 AI 系统。嵌入受监管产品的附件 I 系统适用 2028 年 8 月 2 日,且在此处不属于单独的等级。
文档
| 指南 | 内容 |
|---|---|
| 完整快速入门 | 安装已发布的 SDK,并封装一次模型调用。 |
| 5 分钟快速入门 | 封装一次模型调用,保留来源记录,并检查其 HMAC 签名。 |
| 沙盒前 5 分钟 | 设置密钥前,先体验公开的 2x2 沙盒控制台。 |
| 控制台入门 | 沙盒和托管控制台。 |
| LangGraph 快速入门 | 封装编译后的 LangGraph 工作流(spurvik/langgraph),读取 HMAC 回执,渲染 <AIDisclosureLabel />(包括波兰语 locale="pl" 文案),并将 interrupt() / Command({ resume }) 映射到 /api/v1/hitl。 |
| HITL 审批映射 | 将 Vercel AI SDK 的 interrupted、OpenAI Agents 的 needsApproval 和 LangGraph 的 interrupt() 映射到 Spurvik 的人工监督队列。 |
| 适配器速查卡 | withSpurvikMastra、withSpurvikModel / withSpurvikModelProvider 和 withSpurvikLangGraph。 |
| Claude Code 插件 | /spurvik:check、/spurvik:wrap 和 /spurvik:engineering-summary。 |
| FAQ 补充 | 定价、安装、MCP 工具、HITL、波兰语 locale="pl" 和第 50(2) 条标记问题。 |
| FAQ:沙盒 2x2 | 沙盒控制台行为和 Shell 环境优先级。 |
| FAQ:控制台和快速入门 | 注册、密钥和 5 分钟快速入门流程。 |
| FAQ:HITL 和插件 | 工具审批、检查点暂停/恢复,以及 Claude Code 插件安装。 |
| FAQ:第 50(2) 条标记和波兰语区域设置 | 2026 年 12 月 2 日之前的第 50(2) 条标记(第 111(4) 条)、波兰语 locale="pl" 文案和 LangGraph。 |
| Claude Code 提交草案 | 分阶段目录提交草案。 |
| 网站市场清单 | 为 spurvik.com/.claude-plugin/marketplace.json 准备的网站市场清单。 |
来源信息不等于第 50(2) 条标记
provenanceOf(res) 从 spurvik 导出。它会读取来源记录:时间戳、模型 ID、带键指纹、第 50(1) 条披露标志、上游标记状态以及 HMAC-SHA-256 签名。markingApplied 和 evidenceTrailerAttached 包含在该签名中。同一值也位于 res._spurvik_provenance 上。provenanceOf 也会读取较早版本响应中的旧来源属性。使用 verifyProvenanceSignature 检查签名。匹配表示签名字段仍与使用你的签名密钥生成的 HMAC-SHA-256 签名一致。这并不能证明已显示声明、输出已添加标记,或你的系统符合该法案。
withSpurvik 是包装器。该函数的旧名称已移除;请使用 withSpurvik。旧名称并不代表被包装的客户端符合该法案。
API 对象上的字段在对象被丢弃后不会随内容传递,因此它本身并不是第 50(2) 条所指的机器可读标记。
标记模块是一个钩子:
signed-trailer会将来源记录嵌入文本。这是应用层绑定,不是 C2PA 清单,也不代表已判定符合第 50(2) 条。packages/c2pa(从源代码构建;未发布到 npm)为 PNG 和 JPEG 实现了MediaMarkingHook。POST /api/v1/provenance/verify会读取清单。匹配的签名可验证该清单,但这不是符合性评估。私有 CA 会报告为not_on_trust_list。
第 50 条的透明度义务自 2026 年 8 月 2 日起适用。对于该日期之前投放市场的 AI 系统,第 50(2) 条规定的标记和检测义务将持续至 2026 年 12 月 2 日。Code of Practice on Transparency of AI-generated Content 的签署方承诺在 2027 年 2 月 2 日前采用互操作解决方案进行检测。
假名化指纹
提示词和输出内容的哈希方式可配置:
contentHash.mode | 行为 |
|---|---|
keyed(默认) | 使用客户端持有的密钥或盐值进行 HMAC-SHA-256。服务端无法重新计算。 |
on | 不加盐的 SHA-256。 |
off | 不计算或存储指纹。 |
与可识别个人相关的文本指纹仍可能属于 GDPR 下的个人数据。keyed 模式旨在支持假名化(GDPR 第 4(5) 条):附加信息 HMAC 密钥由客户端持有。这并非匿名化。请勿将这些值描述为非个人数据。
遥测请求正文包含指纹、模型版本、温度和延迟。只有在嵌入了 C2PA 清单、水印钩子更改了内容,或上游状态为 provider_confirmed(响应或标记标头表明存在标记)时,contentMarkingApplied / markingApplied 才为 true。对于已签名的文本尾注、元数据钩子、仅发出请求、根据支持表进行推断、未知模型以及失败的调用,该值为 false。evidenceTrailerAttached 单独记录尾注或元数据钩子,也包含在来源签名中。记录上的状态为 upstreamMarking:requested(请求中包含标记参数)、provider_confirmed、not_requested(请求或响应表明未启用标记)、inferred(模型 ID 在有日期的支持表中,且 SDK 对象没有相关信号)或 unknown。默认值为 unknown。这并不表明标记具有抗篡改性、可检测性,也不表明其符合第 50(2) 条的要求。旧的接收布尔字段名在一个次要版本内仍可使用,并会存储为 contentMarkingApplied。重命名前封存的记录仍能匹配:同一个布尔值曾使用旧字段名进行哈希。接收路由会拒绝提示词或输出文本。
packages/sdk/README.md 列出了 withSpurvik 会记录以及不会处理的方法。嵌入、图像生成、语音、内容审核、批处理和文件上传均不会生成来源记录。Chat、messages、responses、Gemini generateContent 和 Gemini chat sendMessage 均会被包装,包括该表所涵盖的流式辅助函数。spurvik/ai 导出供 wrapLanguageModel 使用的 spurvikMiddleware。spurvik/mastra 会将该中间件传递给 wrapLanguageModel,用于 Mastra Agent 模型。spurvik/openai-agents 会包装 Agents SDK 的 Model 和 ModelProvider。抛出异常的提供方调用不会生成记录。遥测会排队并批量发送,也会在调用 shutdown() 时以及进程退出时发送一次。单次调用本身不会清空队列。
除非集成方将 beacon.consent 设为 true,否则披露标签不会写入浏览器存储。网站运营方负责获取该同意。未获得同意时,标签仍会渲染,但不会发送任何内容。服务端记录某个包含该标签的页面已被提供,不会使用信标。
上游标记证据
封装第三方模型的部署方,只有在能够证明标记有效时,才能依赖该提供商的输出标记。withSpurvik 会为每次封装调用记录一个签名证据事件。该事件会存储提供商、模型、模态、请求和响应实际公开的标记设置,以及 upstreamMarking。设置仅从 SDK 对象携带的标志和标头中读取(watermark、synthid、c2pa、溯源标头,以及 metadata、generationConfig 或 withResponse() 正文中的同名字段)。如果公开的 SDK 对象没有这类字段,状态就为 unknown,包括 OpenAI 文本(没有逐请求参数)、日期标注的帮助中心表格未列出的 Anthropic 模型、Gemini 文本和 Mistral。不会根据一方支持表推断云合作伙伴路由(Bedrock、Vertex、Foundry、Azure)。packages/core/src/upstream-support.ts 中的支持表标注了日期,并在每一行列出来源 URL。
证据使用客户端持有的签名密钥进行 HMAC-SHA-256 签名,并与审计链一同存储。它不属于记录哈希的一部分。每个事件都会记录 routeKind(direct、bedrock、vertex、azure 或 foundry)和 markingSource(response、request、header 或 none)。如果 SDK 路径不包含路由名称,请在 withSpurvik 上设置 upstreamRoute。控制平面会检查载荷结构以及事件 ID 是否匹配。它不持有密钥,因此不会重新计算签名。已发布的 [email protected] 软件包没有导出用于验证此签名的函数。该功能旨在支持你开展 EU AI Act 相关工作。
packages/core/src/marking-registry.ts 列出了用于文本、图像、音频和视频的 OpenAI、Anthropic、Google、Mistral 和开放权重模型。每个条目都有来源 URL 和读取该来源的日期(sourceReadOn)。公开页面变更时,请编辑该列表。
项目页面 Marking 会为文本输出撰写一份关于文档化限制的声明,说明为何存储的 SDK 信号无法证明存在稳健标记,并按模型和模态列出覆盖情况。可从该页面下载 JSON。所有者项目导出中也包含相同的行。删除项目会将其移除。
人类监督
人类审核队列已内置于此控制平面。监督页面和 submitHumanDecision() 会写入相同的决策行。任何组织成员都可以在控制台中暂停或作出决定。通过 API 作出决定需要审核者令牌,该令牌只能由组织所有者签发。由你选择组织中负责执行人类监督的人员(《条例》第 26(2) 条,适用于高风险 AI 系统)。第 14 条适用于自 2027 年 12 月 2 日起列于附件 III 的高风险 AI 系统。
对于高风险系统,第 14 条要求的不只是批准/拒绝关卡,还包括覆盖系统以及中断系统的能力。
-
requireHumanApproval(actionName, payload)会创建一条待处理记录,并轮询/api/v1/hitl/:id,直到状态不再是pending和pending_confirmation,或等待结束。从 1.0.7 起,requireHumanApproval在状态为rejected和overridden时会抛出SpurvikHitlRejectedError;只有在返回状态approved时才继续。 -
submitHumanDecision(id, { status, reason })会记录一项 API 决策。decisionSource为api。控制台设置为console。批准、拒绝和覆盖都需要提供原因。原因会保留在决策记录中,不会作为输入参与记录哈希的计算。 -
最终决策,以及双人确认中的第一项确认,都会追加一条
human_decision哈希链记录。该记录会存储批准 ID、状态和来源。在此字段加入之前封存的记录不包含该字段,因此其哈希仍然匹配。 -
overrideHumanDecision(id, { reason })会记录人工撤销。调用方是reviewerToken,而不是自由文本 ID。 -
engageKillSwitch({ reason, actionName })会暂停整个项目或某项操作,releaseKillSwitch({ reason, actionName })会解除暂停(针对整个项目时省略actionName)。两者都需要reviewerToken,并会发送x-spurvik-reviewer。在 SDK 中,两者的reason都是可选的。务必始终传入原因。接续上方 quickstart 中的ai绑定。此片段不是独立文件:await ai._spurvik.releaseKillSwitch({ reason: "Operator released the stop." });存储的原因是由某人输入的自由文本。Spurvik 不会检查它。
-
当原因缺失或为空白时,SDK 会改为发送
Halted via SDK (no reason given)或Released via SDK (no reason given)。控制平面不会补上该值:直接调用POST /api/v1/oversight时,如果原因缺失或为空白,会返回 HTTP 400reason_required(“Halting a project or action requires a reason.” 或 “Enter a reason for releasing.”)。你也可以在控制台中暂停或解除暂停:在项目的监督页面输入原因,然后选择 Engage stop 或 Release stop。 -
SDK 会随这些调用发送
reasonSource:传入原因时为caller,替换为上述句子时为sdk_default。该值由客户端声明,服务器不会验证。控制台写入的值为 NULL。省略该字段的原始 API 调用会存储 NULL。暂停响应会将previousReason设为 null。已签名的oversight.changedwebhook 会发送该写入:reason是新原因;暂停时previousReason为 null,解除暂停时则为暂停原因。 -
解除暂停响应中的
reason是刚刚存储的解除原因。生效中的暂停原因则是previousReason。在GET /api/v1/oversight响应中,previousReason为null,而reason是最近一次暂停的原因;解除暂停后也是如此。projectHalted和actionHalted表示暂停是否生效。 -
暂停已处于暂停状态的对象会返回 HTTP 409
already_halted(“This is already halted. Release it first to change the reason.”);首次暂停及其原因会保持不变。解除未处于暂停状态的对象会返回 HTTP 409not_halted(“This is not halted.”);不会发生任何变化。 -
对于
high_annex3,包装后的推理会检查最近一次已知的暂停状态,并在无法确认时默认拒绝。oversight.cacheMs设置缓存窗口(0表示每次调用都刷新)。启用暂停强制执行时,oversight.pushInvalidation(默认开启)会监听GET /api/v1/oversight/stream并清除缓存。该流仅限单进程。已签名的oversight.changedwebhook 可覆盖其他实例。invalidateHaltCache()会直接清除缓存。 任何组织成员都可以在控制台中暂停或作出决定。通过 API 作出决定需要审核者令牌,且只有组织所有者可以签发该令牌。由你选择组织中负责人工监督的人员(针对高风险 AI 系统,依据第 26(2) 条)。控制台会将审核者作为组织成员登录。摄取决策需要使用项目所属组织成员的spurvik_reviewer_令牌,并通过x-spurvik-reviewer发送。存储的审核者 ID 是该成员的用户 ID。会话 Cookie 为spurvik_session。
双人确认是一项产品设置。它会检查是否由两个不同的成员账户确认了决定。对于标记为 Annex III point 1(a) 远程生物识别(high_annex3 和向导标志)的项目,批准和覆盖操作都要等待另一位不同的成员确认(pending_confirmation)。一位成员可以拒绝。组织所有者可以在监督页面为就业类别项目开启相同的双人确认。开启后,批准和覆盖操作都要等待另一位不同的成员确认。一位成员可以拒绝。这是一项可选设置,不是生物识别规则。执法部门在公共场所进行的实时远程生物识别属于第 5(1)(h) 条禁止的实践。向导会将其标记为“禁止”,并且不会生成 SDK 设置。
项目页面可以为该项目签发 provenance HMAC 密钥和 content-fingerprint HMAC 密钥。每个明文只会显示一次。控制平面会存储 SHA-256 值和最后四个字符,无法重新计算任一 HMAC。每个项目都应使用一组不同的密钥。
第 12(3) 条所述的引用信息(使用期间、参考数据库、输入引用以及检查结果的成员 ID)可以随遥测事件发送。存在时会纳入记录哈希;不存在时则省略。请发送 URI 或带密钥的指纹,而不是样本、图像、嵌入向量或模板。
项目可以设置 webhook URL。决策和暂停状态变更会以规范 JSON 格式通过 POST 发送。x-spurvik-signature 的值为 v1= 加上 `${timestamp}.${body}` 的 HMAC-SHA-256,x-spurvik-timestamp 为 Unix 秒数。请使用 verifyHitlWebhook 进行验证。匹配表示时间戳和请求正文仍与使用 webhook 密钥生成的 HMAC-SHA-256 签名相符,且时间戳与本地时钟相差不超过五分钟(默认值)。这并不能证明你的监督措施符合适用于高风险 AI 系统的第 14 条。若投递失败,状态路由仍是事实来源。保存 webhook 时,签名密钥只会显示一次。新保存的密钥会在 SPURVIK_WEBHOOK_KEK 下存储为 AES-256-GCM 信封(spurvik-enc:v1),密钥长度为 32 字节(base64url、hex 或 32 字节 utf8)。每种模式下都必须提供该密钥。若未提供,应用将拒绝启动或封存密钥。唯一例外是在非生产环境中设置 SPURVIK_ALLOW_TEST_KEYS=1:此时应用会为该进程生成一个随机密钥并警告一次;使用该密钥封存的密钥在重启后将无法解封。该标志仅用于本地测试,不提供完整性保护,并且当 NODE_ENV 或 VERCEL_ENV 为 production 时会被拒绝。使用旧开发回退机制封存的 webhook 密钥将无法解封。请重新输入每个 webhook 密钥。本次变更前以明文存储的密钥仍可用于签名。
人工审批摘要采用 spurvik.payload_summary.v1:规范 JSON,字段名须符合标识符格式(最多 32 个,每个最长 64 个字符),并可包含可选的十六进制指纹。长度最多为 500 个字符。不包含字段值。请勿在字段名中放入个人数据。摄取路由会拒绝自由文本。旧记录中可能仍有自由文本;新写入的数据不允许包含自由文本。
对于 high_annex3,队列满时遥测数据不会被丢弃。SDK 会先将事件同步写入磁盘缓冲区(或你传入的 DurableTelemetryBuffer / KvTelemetryBuffer),然后才将调用视为已在本地记录。如果写入失败,enqueue 会因 SpurvikTelemetryBufferError 而被拒绝。其他层级在队列满时仍会丢弃最早的内存事件。同一进程的 clientSeq 跳号会作为 chain_gap 行存入哈希链,因此账本可以显示缺失的序列号。删除磁盘缓冲区会移除尚未确认的事件。
运行 SDK
SDK 和 MCP 服务采用 MIT 许可证,可在你自己的技术栈中运行。
https://console.spurvik.com 上的托管控制台是一项托管服务。其源代码不在此代码库中,MIT 许可证也不涵盖它。
生成由客户端持有的密钥(不要将这些密钥发送给 Spurvik):
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
数据接收路由
这些路由都需要 Authorization: Bearer spurvik_live_…。
POST /api/v1/telemetryPOST /api/v1/hitl和GET /api/v1/hitl/:idPOST /api/v1/hitl/:id/decisionGET /api/v1/oversight和POST /api/v1/oversightPOST /api/v1/disclosure也接受可发布的spurvik_pub_密钥。GET不接受。
审计行按项目形成链。追加操作会对 audit_chain_heads 加行锁,因此同一项目的并发插入不会导致链分叉。账本中的 Verify hash chain 按钮会重新计算每条记录的哈希,并检查 prev_log_hash。匹配表示已存储的行仍然相连。这并不代表对 AI 系统的认证。
日志保留
保留期限为(计划中)。此代码库不会应用这些期限。
| 计划 | 默认保留期限(计划中) |
|---|---|
| Developer(免费) | 30 天 |
| Team | 90 天 |
| Business | 12 个月 |
| Enterprise | 按项目设置的期限,以天为单位。未设置期限的 Enterprise 项目会保留 365 天,直到所有者设置期限。 |
Business 是介于 Team 和 Enterprise 之间的计划。这些规则为(计划中)。该计划将适用于整个组织。对于记录为 high_annex3 的项目,计划的最低期限为六个月。在所有者确认风险层级之前,计划规则会将该项目按 high_annex3 处理,以确定保留期限。第 19 条和第 26(6) 条要求至少保留日志这么长时间,除非其他法律另有规定。层级确认后,所有者可以用简短备注记录该其他法律,此后便不再应用最低期限。Spurvik 不会核查该法律。这是一项产品规则,并非认定该项目符合上述条款。
清除功能已经存在。Spurvik 操作员会在托管控制平面上手动运行该功能。没有任何机制会安排其运行。表中的保留期限为(计划中)。检查点匹配表示该检查点的字段(项目、序列号、该哈希和清除时间)仍与使用操作员检查点密钥生成的 HMAC-SHA-256 签名相符。这并非认定你的系统符合该法案。清除并不等于删除整个项目。
项目导出和删除
组织所有者可以下载 GET /dashboard/projects/:id/export。JSON 包含项目资料、审计日志、人类决策、监督信息、披露信息、API 密钥元数据(类型、末四位字符、撤销时间)、清除检查点以及 webhook URL。它不包含 webhook 密钥和 API 密钥哈希。删除项目会移除项目行。相关日志、密钥和检查点会随之级联删除。成员帐户和审核者令牌会保留。该删除操作与保留期限清除是分开的。
调用去向
SDK 遥测数据和停止流会发送到 baseUrl。对于托管控制台工作区,该地址为 https://console.spurvik.com。披露信标会发送到你传入的端点。Webhook 会发送到项目 Webhook URL。没有许可证 ping、错误报告器、更新检查或分析调用。除非 SPURVIK_TELEMETRY 的值为 off,否则它会被忽略;GET /api/v1/health 会报告 vendorTelemetry: "off"。没有任何开关可以启用供应商接收端。控制台使用系统字体栈,因此构建时不会向字体主机发起请求。
披露标签
import { AIDisclosureLabel, AIDisclosureDetails } from "spurvik/react";
export function DisclosureExample() {
return (
<>
<AIDisclosureLabel
notice="interaction" // or "generated" | "deepfake" | "public-interest"
presentation="inline" // pill; "block" is the default
locale="de" // all 24 EU languages, or registerDisclosureLocale
euIcon // optional Commission icon; always paired with visible text
// attribution is off by default; pass attribution to show an "Art. 50 · Spurvik" link
beacon={{ endpoint: "https://your-endpoint.example/beacon", apiKey: process.env.NEXT_PUBLIC_SPURVIK_PUB_KEY! }}
/>
<AIDisclosureDetails riskTier="limited_art50" modelSummary="gpt-4o" provenance={{ signature: "unchecked" }} />
</>
);
}
示例值。请自行设置分类(作为提供者或部署者);Spurvik 不会对你的用例进行分类。
页面上无需点击即可看到标签文本。对话框仅作补充说明。IntersectionObserver 报告标签显示在屏幕上后,每个会话会触发一次信标。请传入 spurvik_pub_…,而非实时密钥。欧盟图标(基础、AI 生成、AI 修改)是欧盟委员会针对第 50(4) 条提供的可选标记。使用其中之一并不意味着单凭此举就满足第 50 条。
attribution 默认关闭。在 <AIDisclosureLabel /> 上传入 attribution={true},即可在披露文本后显示一个小型“Art. 50 · Spurvik”链接,指向 https://spurvik.com。披露文本仍然排在前面且始终可见。该链接不带查询参数,也不会设置 Cookie 或发起网络调用。
/labels 会呈现各个变体,包括适用于第 50(3) 条的 AIArticle50Section3Notice。控制台位于 /login。
操作员控制台
组织成员使用电子邮件地址和 scrypt 密码登录。任何组织成员都可以在控制台中触发停止或作出决定。通过 API 作出决定需要审核者令牌,该令牌仅组织所有者可以签发。由你选择组织中负责人工监督的人员(高风险 AI 系统适用第 26(2) 条)。只有组织所有者可以创建、轮换或撤销实时密钥和披露密钥。成员可以撤销自己的审核者令牌。只有组织所有者可以签发审核者令牌。保留期限为(计划中)。清除功能已经存在,但需要操作员手动运行。没有任何任务会自动安排清除。你可以运行欧盟风险向导、阅读旨在支持第 12 条记录保存要求的哈希链日志、查看上游标记覆盖情况、处理人工监督队列、启动停止操作、以 Markdown 或 PDF 格式下载 Annex IV 技术文档(草案),并以所有者身份导出或删除项目。数据清单页面会列出所有者可以导出的内容和不予提供的内容。本软件不收取切换费用。
向导会询问系统是否投放于欧盟市场、第 5 条中的做法是否属于禁止行为、附件 III 中哪些领域适用,以及哪些第 50 条触发条件适用。对于禁止行为的回答不会生成 SDK 代码片段。社会评分涵盖公共和私人主体(第 5(1)(c) 条)。未经同意的私密深度伪造(第 5(1)(ba) 条)和生成儿童性虐待材料(第 5(1)(bb) 条)也包括在内,并自 2026 年 12 月 2 日起适用。记录的风险等级由你的回答决定。
附件 IV 文件是根据项目字段和账本计数汇编的草案。第 2 节包含系统描述,包括向导中的回答。第 5 节,即第 9 条风险管理系统,标注为“由提供者补充”。合格评定、欧盟符合性声明和 CE 标志均为独立步骤,不会由导出功能生成。
非法律建议
Spurvik 可帮助团队实施与第 12、14 和 50 条部分内容以及附件 III/第 50 条产品分类相对应的技术措施。使用它并不意味着系统符合要求。它不会执行符合性评估、签发欧盟符合性声明、加贴 CE 标志、运行质量管理体系,也不会在欧盟数据库中注册系统。附件 IV 下载内容是草稿。风险向导会记录你的回答,并将第 5 条所列做法标记为 Prohibited,但不会判定某种用途是否属于第 6 条规定的高风险用途。
本代码库不声称数据会留在欧盟。网络弹性法案(CRA)报告流程草案见 docs/cra-article-14-reporting.md。数据法案导出说明见 docs/data-act.md。开源软件包根据 MIT License 发布([email protected]、[email protected]、[email protected]、[email protected]),并同步至 https://github.com/spurvik/spurvik;参见 LICENSE。
MCP 服务
spurvik/ai 导出供 Vercel AI SDK(ai 7)使用的 spurvikMiddleware。将其传给 wrapLanguageModel。它会记录调用并附加 HMAC 来源凭证,但不会标记内容。标记钩子由调用方提供。
| 组件 | MCP 设置 |
|---|---|
packages/mcp | 已作为 [email protected](MIT)发布到 npm;在此代码库中,工作区软件包 packages/mcp 在版本 1.0.5 下仍为 "private": true。只读工具:spurvik_setup_snippet、spurvik_find_unwrapped_calls、spurvik_explain_receipt、spurvik_marking_hooks、spurvik_scan_live_url(唯一会使用网络的工具:访问 console.spurvik.com 上的一个公开 URL)、spurvik_classify_ai_act_risk 和 spurvik_generate_art50_badge。plugins/spurvik/.mcp.json 会运行 node ${CLAUDE_PLUGIN_ROOT}/bin/spurvik-mcp.mjs --root ${CLAUDE_PROJECT_DIR};该文件通过 node packages/mcp/scripts/bundle-plugin.mjs 从 packages/mcp 1.0.5 打包而来。 |
plugins/spurvik | Claude Code 插件。相同的七个只读工具为 spurvik_setup_snippet、spurvik_find_unwrapped_calls、spurvik_explain_receipt、spurvik_marking_hooks、spurvik_scan_live_url(唯一会使用网络的工具:访问 console.spurvik.com 上的一个公开 URL)、spurvik_classify_ai_act_risk 和 spurvik_generate_art50_badge。plugins/spurvik/.mcp.json 会运行 node ${CLAUDE_PLUGIN_ROOT}/bin/spurvik-mcp.mjs --root ${CLAUDE_PROJECT_DIR};该文件通过 node packages/mcp/scripts/bundle-plugin.mjs 从 packages/mcp 1.0.5 打包而来。 |
packages/mcp(packages/mcp)和 plugins/spurvik 提供相同的七个只读 MCP 工具:spurvik_setup_snippet、spurvik_find_unwrapped_calls、spurvik_explain_receipt、spurvik_marking_hooks、spurvik_scan_live_url(唯一会使用网络的工具:访问 console.spurvik.com 上的一个公开 URL)、spurvik_classify_ai_act_risk 和 spurvik_generate_art50_badge。packages/mcp 是供 Cursor、VS Code 和其他 MCP 客户端使用的本地 stdio MCP 服务。它已作为 [email protected](MIT)发布到 npm;在此代码库中,工作区软件包 packages/mcp 在版本 1.0.5 下仍为 "private": true。使用 npm i -D [email protected] 安装并启动,然后运行 ./node_modules/.bin/spurvik-mcp-server --root .。从 1.0.3 版本开始,必须指定 --root。Claude Code 插件会读取 plugins/spurvik/.mcp.json,该文件会运行 node ${CLAUDE_PLUGIN_ROOT}/bin/spurvik-mcp.mjs --root ${CLAUDE_PROJECT_DIR}。该服务文件通过 node packages/mcp/scripts/bundle-plugin.mjs 从 packages/mcp 1.0.5 打包而来。这些工具不会调用 Spurvik API 或任何网络服务。SDK 会记录调用并附加 HMAC 凭证,但不会标记内容。代码片段中的 riskTier 是示例值。请自行设置分类(作为提供者或部署者);Spurvik 不会对你的用例进行分类。扫描器会跳过名为 .env 或 .env.* 的文件(不区分大小写),也会跳过通过符号链接和硬链接指向的此类文件。配置示例见 packages/mcp/README.md。
多渠道 ask_human() 路由器与 n8n / Make.com 工作流防护
packages/sdk/src/channels.ts(createMultiChannelApprovalRouter和verifyChannelApprovalToken):通过 HMAC-SHA256 摘要以及已签名的 Approve / Block 链接,在 Slack、Telegram、Email(Resend)、Discord、Microsoft Teams、Linear、Jira 和 Asana 上分发人工介入审批请求。Monday.com 只会创建条目,不会发送 Approve 或 Block 链接。verifyChannelApprovalToken会检查 Spurvik 自有的审批链接令牌,并返回 true 或 false。它不会验证平台 webhook 签名。从 1.0.5 开始,若相同令牌匹配,verifySignedChannelCallback会返回{ ok: true, decision, gateId, actionHmac, issuedAtUnix, nonce };否则返回false。缺少签名时会返回false,且不会抛出异常。packages/n8n-nodes-spurvik:n8n 节点和可导入的make-com-blueprint.json。不同操作分别用于添加 AI 交互通知、记录旨在支持第 12 条记录保存要求的 HMAC-SHA256 摘要,以及发送旨在支持第 14 条人工监督要求的ask_human()请求。- 从 1.0.5 开始,
createSignedApprovalLinks生成的链接包含一个 nonce。默认有效期仍为 24 小时(86400 秒),与 1.0.4 相同。若需要 15 分钟的时限,请传入maxAgeSeconds: 900。链接在过期前可以重复使用。接收方必须记录 nonce 并拒绝重复请求。1.0.4 令牌没有 nonce;省略 nonce 时,仍可通过verifyChannelApprovalToken验证。从 1.0.5 开始,必须提供callbackBaseUrl:传入一个可接受 GET 点击请求的 URL。SDK 不会默认使用控制台 HITL 创建路由。 - 完整的快速入门和回调验证示例:
docs/multi-channel-hitl-and-n8n.md。 examples/中可运行的示例:examples/nextjs-vercel-ai-sdk、examples/slack-telegram-linear-ask-human、examples/n8n-make-import和examples/github-actions-ci-check。
仍待解决
- Code of Practice 检测。 签署方承诺在 2027 年 2 月 2 日前实现可互操作的检测。C2PA 挂钩是清单写入器和读取器,并非该检测计划。
- 公开的 C2PA 信任。 私有 CA 会进行签名,验证路由会报告
not_on_trust_list。将证书加入公开信任列表是运营方的工作。 - 第 5 条。 禁止性做法不是风险等级值。若答案得出某个等级,向导会显示 SDK 设置。若答案属于禁止情形或适用范围在欧盟之外,则显示 “No SDK setup is offered for this answer set.”。未作答的表单不会显示任何内容。即使调用方忽略向导,向导也不会阻止调用方。
- 附件 I。 嵌入产品的系统遵循 2028 年 8 月 2 日的规定,不属于单独的等级。
- 共享限制。 数据摄取速率限制和 halt SSE 总线均为单进程。
- 商标。 仓库中的 MIT License 文本适用于
packages/sdk、packages/core、packages/react、packages/mcp和packages/c2pa。这些工作区包仍设置为"private": true。已发布的版本为[email protected]、[email protected]、[email protected]和[email protected]。托管控制台 https://console.spurvik.com 是一项托管服务。其源代码不在此仓库中,MIT licence 不适用于该服务。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。