内容
<p align="center">
<img src="docs/kysigned-logo.png" alt="kysigned" width="120" height="120">
</p>
<h1 align="center">kysigned</h1>
<p align="center">
<strong>电子签名,每封邮件 0.25 美元</strong>:简单,安全的签名,由您的电子邮件驱动。
</p>
kysigned 使用 **DKIM**,即您的电子邮件提供商已经在您发送的每封邮件上进行的加密签名,作为签名本身。签署者转发一封邮件;结果是一个自包含的 **证据包**(一个 PDF 文件),任何人都可以自行在其机器上验证,即使离线,即使该服务消失。
## 快速开始
### 1. 立即签署文件(无需设置)
在 [kysigned.com](https://kysigned.com) 上签署文件。购买积分,发送即可。无需安装,无需 SDK。
### 2. 部署您自己的
kysigned 是一个完整的,可自行托管的应用程序:克隆它,指向您自己的 [run402](https://run402.com) 项目(托管电子邮件 + 数据库 + 计算),您就可以运行您自己的实例。所有 run402 输入/输出都通过 [`@run402/sdk`](https://www.npmjs.com/package/@run402/sdk) 进行。
```bash
git clone https://github.com/kychee-com/kysigned.git
cd kysigned
KYSIGNED_ALLOWED_CREATORS='you@example.com,*@example.org' run402 up --name my-kysigned
```
该命令读取 `run402.json`,创建或链接 Run402 项目,创建 `forward-to-sign` 和 `notifications` 邮箱,设置生成的运行时机密,运行本地构建,部署数据库/站点/函数版本,并验证应用程序。有关详细的运行手册和烟雾测试检查清单,请参见 [`docs/run402-cloud.md`](docs/run402-cloud.md)。
遵循此路径的分叉者在其自己的 run402 项目上运行相同的公共代码,在其自己的域下,并端到端生成可验证的包。
**Agent Native:从任何 MCP 代理驱动日常签名。** 一旦您的实例上线,捆绑的 MCP 服务器(`kysigned-mcp`)就会通过您的端点(可通过 `KYSIGNED_ENDPOINT` 配置,默认为 kysigned.com)公开签名操作,例如 `create_envelope`、`check_envelope_status`、`list_envelopes`、`send_reminder`、`void_envelope`。在任何支持 MCP 的代理(Claude、Cursor 等)中配置它:
```json
{
"kysigned": { "command": "npx", "args": ["kysigned-mcp"] }
}
```
然后询问:*"将附件 PDF 发送到 alice@example.com 进行签名,via kysigned。"*
### 您的实例位于哪里?(第一天无需域名)
kysigned 部署在 [run402](https://run402.com) 上,与托管在那里的其他仓库的模式相同。您无需注册域名即可开始:
- **默认(无域名):** 您的 run402 项目在 run402 颁发的子域名(例如 `<your-project>.run402.com`)上可访问。您的仪表盘、签名页面和验证页面都位于此处,无需配置 DNS,无需续订证书。
- **使用您自己的域名(稍后):** 注册一个域名(例如 `lawyerxx.com`),按照项目设置将 DNS 指向 run402,然后 run402 接管 TLS + CDN + 路由。现有的签名邮件继续有效;新信封使用新域名。
- **包含静态信息页面:** `/faq`、`/pricing` 和 `/how-it-works` 由与应用程序相同的 Run402 源提供,因此默认克隆路径不需要第二个营销站点。
仓库中不包含对特定域名的硬编码引用。这里对 `kysigned.com` 的引用是说明性的,它们指的是 Kychee 运营的规范实例。
### 操作员配置
操作员完全通过环境/机密进行配置,**无需源代码编辑**:
| 变量 | 目的 |
| --- | --- |
| `KYSIGNED_ALLOWED_CREATORS` | 允许发送的创建者电子邮件或精确域通配符的逗号列表,例如 `you@example.com,*@example.org` |
| `KYSIGNED_BILLING` | `hosted` 以启用预付费信用额度;未设置 = 允许列表门控 |
| `KYSIGNED_UNSUBSCRIBE_MAILTO` | 可选,输出邮件上的 `List-Unsubscribe` 联系人 |
`run402 up` 生成并设置 Run402 基质值:
`RUN402_PROJECT_ID`、`RUN402_SERVICE_KEY`、`RUN402_ANON_KEY`、
`RUN402_PUBLIC_ORIGIN`、`RUN402_MAILBOX_FORWARD_TO_SIGN_ID`、
`RUN402_MAILBOX_FORWARD_TO_SIGN_ADDRESS`、`RUN402_MAILBOX_NOTIFICATIONS_ID`,
以及 `RUN402_MAILBOX_NOTIFICATIONS_ADDRESS`。迁移在
`run402.json` 中声明,并由版本控制应用。
### 品牌、首页和定价
该仓库附带 **通用、无操作员** 内容:占位符首页,无定价页面和“定价”导航项,通用页脚和无硬编码域名。您自己的身份通过单个 JSON 环境变量在构建时注入,因此您永远不会编辑源代码来重新品牌化:
| 变量 | 目的 |
| --- | --- |
| `VITE_OPERATOR_CONFIG` | 带有您的品牌和首页内容的 JSON 字符串。字段:`brandName`、`companyName`、`companyUrl`、`contactEmail`、`showPricing`(添加“定价”导航项),以及 `home`(英雄,加上可选的比较和受众营销部分)。有关完整形状和通用默认值的详细信息,请参见 `frontend/src/config/operator.ts`。 |
未设置 `VITE_OPERATOR_CONFIG` 时,SPA 渲染通用默认值(分叉广告宣传您,而不是上游)。要自定义,请将变量传递到前端构建:
```bash
VITE_OPERATOR_CONFIG='{"brandName":"Acme Sign","companyName":"Acme, Inc.","showPricing":true}' \
npm run build --prefix frontend
```
### 静态和法律页面
`frontend/public/` 中的被动页面(`faq.html`、`how-it-works.html`、
`how-it-works-technical.html`)是您可以自由编辑的纯 HTML 文件。法律页面
(`terms.html`、`privacy.html`、`cookies.html`、`aup.html`、`dpa.html`)作为 **空白占位符** 交付:用您自己的替换它们,然后上线,因为条款特定于每个操作员和司法管辖区。此仓库中没有定价页面;如果您启用 `showPricing` 并希望链接它,请添加一个。
### 发送者访问控制
kysigned 带有内置的 **允许列表**(`allowed_senders`),因此您可以决定哪些人可以从您的实例创建信封。 将 `KYSIGNED_ALLOWED_CREATORS` 设置为精确电子邮件和精确域通配符的逗号列表,例如 `you@example.com,*@example.org`。通配符仅匹配该域,而不匹配子域。对于本地开发和测试,默认情况下允许列表关闭;如果缺少所需的部署机密,`run402 up` 将快速失败。
### 试用签名文档
在发送真实文档之前要试用?仓库中附带两个刻意设计的试用表格,位于 [`docs/test-assets/`](docs/test-assets/) 中:**ACME Approval Form 42-B** (`acme-approval.pdf`) 和 **ACME Anvil Liability Waiver** (`acme-anvil-waiver.pdf`),两者都带有粗体 **TEST DOCUMENT, NOT LEGALLY BINDING** 水印。在新部署的实例中使用其中一个作为第一个文档,以端到端测试转发签名流程。随时重新生成:
```bash
node docs/test-assets/build-acme-approval.mjs
node docs/test-assets/build-acme-anvil-waiver.mjs
```
## 签名工作原理
1. 签署者收到一封来自 `forward-to-sign@<your-domain>` 的电子邮件,附件中包含文档。
2. 他们 **转发** 并输入 **"I sign this document"** 作为第一行。无需帐户,无需应用,无需密码。
3. 他们的电子邮件提供商的 **DKIM 签名** 是转发时的签名,只有提供商才能生成,因此其他人无法伪造以他们的名义发送的消息。
4. kysigned 验证 DKIM 签名,确认转发的附件 **字节相同** 于发送的内容,**时间戳** 转发的电子邮件,并记录签署者。
当所有人签署后,每个相关方都会收到一个 **证据包**。
## 证据包和验证
该包是一个单一的 PDF 文件,包含文档、签名页和 **每个签署者的原始 DKIM 签名电子邮件**,以及用于检查它们所需的公钥和时间戳。这是一个干净的、无签名的 PDF 文件(无证书,无印章,打开时无警告),带有打印的 SHA-256 指纹。
任何人都可以验证 `https://<your-domain>/verify` 上的包(拖放,完全在客户端),或使用捆绑的 CLI:
```bash
node bin/verify-bundle.mjs <bundle.pdf>
```
验证 **完全在验证者的本地机器上** 进行,离线,即使您的实例不再存在。**kysigned 不属于信任集:** 证明依赖于签署者的电子邮件提供商(DKIM)、公钥存档、时间戳权威机构和数学运算。有关完整的信任集和威胁模型,请参见 [docs/trust-model.md](docs/trust-model.md)。
想要立即尝试这两种工具,且没有任何内容已签名? [`docs/test-assets/`](docs/test-assets/) 提供了现成的示例: 将 `acme-anvil-waiver-signed-bundle.pdf`(一个真实的签名记录)放到 `/verify` 上,并将 `acme-anvil-waiver.pdf` 与该包或 `acme-anvil-waiver-sign-request.pdf` 搭配使用 `/hashcheck` 以确认原始文档。该文件夹还包含一组篡改的包,它们必须全部失败,每个包都破坏了一个指定的检查。 [docs/test-assets/README.md](docs/test-assets/README.md) 列出了每个文件的预期判决, [scripts/verification-tools/](scripts/verification-tools/) 在应用程序之外独立复制了每个检查。
## 架构
```
kysigned/
src/
api/ # 信封生命周期、分布、帐户和管理员处理程序
api/signing/ # 转发处理:DKIM 验证、意图和附件门、协调器
bundle/ # 证据包组装 + 指纹 + 验证引擎
timestamp/ # RFC 3161(TSA)+ OpenTimestamps 客户端,背后有一个 TimestampProvider 合同
pdf/ # 确定性规范 PDF、封面、签名页(pdf-lib)
email/ # 传输无关的 EmailProvider + HTML 模板
db/ # 模式 + 数据访问层(在 run402 的 HTTP SQL 上运行)
integrations/ # run402 适配器(@run402/sdk 电子邮件 + HTTP SQL 池)+ 路由表
functions/ # run402 路由的 HTTP 入口 + 电子邮件触发的持久工作
frontend/ # React + Vite + Tailwind:仪表盘、签名审查、/verify
mcp/ # kysigned-mcp(代理表面)
bin/ # verify-bundle.mjs(独立 CLI 验证器)
```
## 测试
```bash
# 后端单元测试套件
npm run test:all
# 前端
cd frontend && npx vitest run
# MCP
cd mcp && npm test
# 已部署端到端,设置 BASE_URL 到正在运行的实例
BASE_URL=https://your-instance npm run test:e2e
```
## 计费
**托管(kysigned.com):** **每封邮件 0.25 美元**,统一价格,最高可达 20 个签署者。创建者购买预付费信用包,信用卡支付,**5 美元购买 20 个信封**,信用额度永不过期。**Stripe** 是支付处理器;信用卡信息从未到达 kysigned。货币门控由配置决定(`KYSIGNED_BILLING=hosted`)。
**自行托管(此仓库):** 您为基础设施(计算、电子邮件、数据库)支付 run402 费用。使用内置的 `allowed_senders` 允许列表控制谁可以创建信封,或使用它作为授权钩线,编写您自己的计费系统。
## 构建于 run402
kysigned **完全** 运行在 [run402](https://run402.com) 上:用于 API 的路由 HTTP 函数,用于签名回复和退信的电子邮件触发的持久工作,用于数据库的 run402 的 HTTP SQL,以及用于电子邮件的 run402 邮箱。
所有 run402 输入/输出 **默认使用 [`@run402/sdk`](https://www.npmjs.com/package/@run402/sdk)**,该 SDK 拥有线路转换,因此应用程序保留了硬编码的 `snake_case` 边界适配器。两个原始 HTTP 例外被记录和包含:身份验证助手直接调用 run402 的 `/auth/v1/*` 端点(传递项目匿名密钥),数据库池包装 run402 的 HTTP SQL 接口。两者都在边界处映射 run402 的 `lower_snake_case` 线路形状。
## 许可证
[Apache-2.0](LICENSE),整个仓库,无需逐文件例外。每个依赖项都是允许的(MIT/Apache-2.0);树中没有 GPL 或其他 copyleft,允许分叉和商业使用不受限制。有关依赖项清单,请参见 [LICENSES.md](LICENSES.md),有关签名有效性免责声明和司法管辖区限制,请参见 [LEGAL.md](LEGAL.md)。