# Toot Worker 一个运行在 Cloudflare Workers 上的单用户联邦宇宙发布软件,使用: - Workers: HTTP API、ActivityPub 路由、Mastodon API 兼容层 - D1: 用户、OAuth 应用、嘟文、媒体索引、关注、收藏、转发、通知、提及、话题标签、远端 actor 缓存 - R2: 媒体文件 - KV: OAuth access token 会话 当前目标:让常见 Mastodon App 完成实例发现、创建 OAuth App、登录、上传媒体、发布嘟文、读取公开/家庭时间线、收藏/转发/回复、查看通知、搜索、关注/取关远端账号,同时支持单用户实例与 Fediverse 双向联邦。 ## 本地运行 ```bash npm install npm run db:local npm run dev ``` 默认管理员账号来自 `wrangler.jsonc`: - 用户名:`admin` - 密码:`change-me-before-deploy` 部署前必须改掉 `ADMIN_PASSWORD`,更推荐用 Cloudflare secret 管理密码: ```bash wrangler secret put ADMIN_PASSWORD ``` `PUBLIC_BASE_URL` 必须在首次正式部署前改成你的稳定实例域名,例如: ```json "PUBLIC_BASE_URL": "https://social.example.com" ``` 这个值会进入: - Actor ID - Object ID - WebFinger 返回值 - 媒体和头像 URL 一旦开始对外联邦后,不要再改域名,否则远端会把你视为另一个实例身份。 ## Cloudflare 资源 ```bash wrangler d1 create toot_db wrangler r2 bucket create toot-media wrangler kv namespace create KV ``` 把返回的 ID 填回 `wrangler.jsonc`,然后应用迁移并部署: ```bash npm run db:remote npm run deploy ``` ## 已实现接口 ### Mastodon API 兼容 实例 / 应用 / 鉴权: - `GET /api/v1/instance`、`GET /api/v2/instance` - `POST /api/v1/apps`、`GET /api/v1/apps/verify_credentials` - `GET /oauth/authorize`、`POST /oauth/authorize` - `POST /oauth/token`、`POST /oauth/revoke` 账号: - `GET /api/v1/accounts/verify_credentials` - `PATCH /api/v1/accounts/update_credentials`(自动联邦 Update Person) - `GET /api/v1/accounts/relationships` - `GET /api/v1/accounts/:id` - `GET /api/v1/accounts/:id/statuses` - `POST /api/v1/accounts/:id/follow`、`POST /api/v1/accounts/:id/unfollow`(向远端发送 Follow / Undo) - `GET /api/v1/follow_requests`、`POST /api/v1/follow_requests/:id/authorize`、`/reject`(stub,默认全自动接受) 嘟文: - `POST /api/v1/statuses`(支持 `media_ids`、`spoiler_text`、`sensitive`、`in_reply_to_id`、`visibility`、`language`,自动解析 `@user`/`@user@host` 提及和 `#hashtag`,投递 Create 给 followers 与 mention) - `GET /api/v1/statuses/:id`、`DELETE /api/v1/statuses/:id`(联邦 Delete 出站) - `GET /api/v1/statuses/:id/context` - `POST /api/v1/statuses/:id/favourite`、`/unfavourite`(联邦 Like / Undo Like) - `POST /api/v1/statuses/:id/reblog`、`/unreblog`(联邦 Announce / Undo Announce) - `POST /api/v1/statuses/:id/bookmark`、`/unbookmark`、`/pin`、`/unpin`(本地 stub) 时间线 / 通知 / 媒体 / 搜索 / 其它: - `GET /api/v1/timelines/public`、`GET /api/v1/timelines/home`(分页支持 `max_id` / `since_id` / `min_id`,响应携带 `Link` 头) - `GET /api/v1/notifications`、`POST /api/v1/notifications/clear`、`POST /api/v1/notifications/:id/dismiss` - `POST /api/v1/media`、`POST /api/v2/media`、`PUT /api/v1/media/:id` - `GET /api/v2/search`、`GET /api/v1/search`(本地账号 / 嘟文 / 话题标签 + 跨站 WebFinger 解析 `acct:` 查询) - `GET /api/v1/custom_emojis`、`GET /api/v1/filters`、`GET /api/v1/trends/tags`、`GET /api/v1/markers`(stub) - `POST /api/v1/push/subscription`(返回 422,目前不支持推送) ### ActivityPub / 发现 - `GET /.well-known/webfinger?resource=acct:user@example.com` - `GET /.well-known/nodeinfo`、`GET /.well-known/host-meta` - `GET /nodeinfo/2.0` - `GET /users/:username`(含 `endpoints.sharedInbox`、`icon`、`image`、`publicKey`) - `GET /users/:username/followers`、`/following` - `GET /users/:username/outbox`(支持 `?page=true` 翻页) - `POST /users/:username/inbox`、`POST /inbox`(共享 inbox) - `GET /objects/:id`(嘟文已删除时返回 `Tombstone`,HTTP 410) 入站 inbox 处理类型:`Follow` / `Undo(Follow)` / `Accept(Follow)` / `Reject(Follow)` / `Like` / `Undo(Like)` / `Announce` / `Undo(Announce)` / `Delete(Note)` / `Delete(Person)` / `Update(Person)` / `Create(Note)`(只用于触发提及通知)。`Create` 用于触发提及通知和回复通知。 ## 安全 - 密码哈希使用 **PBKDF2-SHA256 / 100000 iterations**,带每用户随机 16 字节 salt,旧版 `salt.hash` 哈希也能继续验证(便于无缝升级)。 - HTTP Signature(rsa-sha256)出站:签名 `(request-target)`、`host`、`date`、`digest`,自动计算 SHA-256 digest。 - HTTP Signature 入站验证: - 强制要求 `Date` 头,允许 ±12 小时时钟偏移 - `POST` 必须带 `Digest`,且与 body 哈希一致 - 通过签名头里的 `keyId` 取得远端 actor 公钥(并在 `actor_cache` 表中缓存),拒绝 `body.actor` 与 actor cache 不一致的请求 - 验证 `host` 头匹配请求 URL - 远端 actor 公钥与 inbox 写入 `actor_cache`,默认 24 小时 TTL,远端 `Delete(Person)` 会清理缓存与所有相关关注 / 收藏 / 转发 / 通知。 - 重放保护:已处理过的 `activity.id` 会写入 `remote_activities`,重复投递被静默丢弃(返回 202)。 ## 数据库结构 迁移文件: - `migrations/0001_initial.sql` — 基础表(users / oauth_apps / oauth_codes / statuses / media / follows / remote_activities) - `migrations/0002_features.sql` — 通知 / 收藏 / 转发 / 提及 / 话题标签 / actor 缓存 / 出站关注 / 删除墓碑 / 嘟文扩展字段(summary / sensitive / language) ## 重要限制 这是一个单用户可运行实现,不是完整 Mastodon 服务端: - 只支持单管理员账号自动初始化,不开放注册 - 通知 / 收藏 / 转发都已实现,但内容审核、屏蔽、过滤、列表、自定义表情、推送通知仍是 stub - 没有处理远端嘟文缓存(收到 `Create(Note)` 不会存,仅触发提及通知)。意味着客户端的 home timeline 仍只能看到本地嘟文 - 私信(direct visibility)的检索没有按收信人过滤,目前所有客户端都能在公开时间线之外读到自己的嘟文,不应当作私信使用 - 没有实现轮询(poll)、列表(list)、推送(push)、未来嘟文(scheduled)等 ## 参考 - Cloudflare Workers 绑定:https://developers.cloudflare.com/workers/runtime-apis/bindings/ - Cloudflare D1:https://developers.cloudflare.com/d1/ - Cloudflare R2:https://developers.cloudflare.com/r2/ - Cloudflare KV:https://developers.cloudflare.com/kv/ - Mastodon API:https://docs.joinmastodon.org/methods/ - ActivityPub:https://www.w3.org/TR/activitypub/ - HTTP Signatures:https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12