Loading... # 社交文件系统 AT 协议技术分析 # 一、概述 ## 1. 文章信息 ### A. 标题 A Social Filesystem(社交文件系统) ### B. 作者 Dan Abramov ### C. 来源 overreacted.io ### D. 发布时间 2026 年 1 月 18 日 ## 2. 核心主题 本文探讨了如何将传统文件系统的理念应用到社交网络中,介绍了 AT 协议(Authenticated Transfer Protocol)如何实现数据与应用的分离,让用户数据真正归属于用户而非平台。 # 二、背景分析 ## 1. 传统文件系统的优势 ### A. 数据归属 文件不属于创建它的应用程序,而是属于用户。用户可以检查文件、发送给朋友、用其他应用打开。 ### B. 文件格式的作用 文件格式就像一种语言,应用可以"说"多种格式,同一种格式可以被多个应用理解。应用和格式是多对多的关系。 ### C. 应用无关性 我们的记忆、思想、设计应该比创建它们的软件更持久。应用无关的存储(文件系统)强制实施这种分离。 ## 2. 社交应用的现状问题 ### A. 数据被困 在 Instagram、Reddit、Tumblr、GitHub、TikTok 等社交应用中,用户数据被困在应用内部,无法自由迁移。 ### B. 应用主导 传统模式是应用主导,用户的数据存储在应用的服务器上,由应用控制。 ### C. 缺乏互操作性 不同社交平台之间数据无法互通,用户需要重复创建内容。 # 三、核心理念:社交文件系统 ## 1. 万物文件夹概念 假设有一个文件夹包含你的在线角色所有发布过的内容: 你的帖子、点赞、音乐播放记录、食谱等,可以称为"万物文件夹"。 在这个世界中: - 在 Tumblr 发帖会在你的文件夹中创建一个"Tumblr 帖子"文件 - 在 Instagram 关注会在你的文件夹中放入一个"Instagram 关注"文件 - 在 Hacker News 投票会在你的文件夹中添加一个"HN 投票"文件 ## 2. 文件作为真实来源 文件是真实来源,应用只是反映文件夹中的内容。对文件夹的任何写入都会同步到相关应用。删除"Instagram 关注"文件与应用中取消关注效果相同。 ## 3. 应用反应式设计 在这个范式下,应用对文件是反应式的。每个应用的数据库主要成为派生数据——应用特定的缓存物化视图,反映所有人的文件夹。 # 四、AT 协议架构 ## 1. 系统组成 ```mermaid graph TB User[用户] --> owns[拥有] owns --> Repo[Repository 仓库] Repo --> contains[包含] contains --> Collection[Collection 集合] Collection --> containsRecord[包含] containsRecord --> Record[Record 记录] Repo --> hostedBy[托管于] hostedBy --> PDS[Personal Data Server] PDS --> syncWith[同步] syncWith --> Relay[Relay 中继] App1[App 1] --> subscribes[订阅] subscribes --> Relay App2[App 2] --> subscribes App3[App 3] --> subscribes ```  ## 2. 核心概念 ### A. Record(记录) 记录是社交文件系统的基本单位,是一个 JSON 文件。例如一条推文记录: ```json { "text": "no", "createdAt": "2008-09-15T17:25:00.000Z" } ``` 关键原则: - 只包含用户创建的数据 - 不包含派生数据(如点赞数、转发数) - 可以独立验证和解析 ### B. Collection(集合) 集合是包含特定词表类型记录的文件夹。命名规则采用反向域名表示法: - com.twitter.post:Twitter 帖子 - com.instagram.follow:Instagram 关注 - fm.last.scrobble:Last.fm 播放记录 - io.letterboxd.review:Letterboxd 影评 ```mermaid graph LR subgraph Collections A[com.twitter.post] B[com.instagram.follow] C[fm.last.scrobble] D[org.schema.recipe] end App1[App 1] --> defines[定义] defines --> A App2[App 2] --> defines defines --> B App3[App 3] --> defines defines --> C ``` ### C. Repository(仓库) 仓库是用户的"万物文件夹",由 DID 标识,包含集合,集合包含记录: ```mermaid graph TD DID[DID:did:plc:xxx] --> Repo[Repository] Repo --> Collection1[com.twitter.post] Repo --> Collection2[fm.last.scrobble] Repo --> Collection3[com.ycombinator.news.vote] Collection1 --> Record1[记录1] Collection1 --> Record2[记录2] Collection2 --> Record3[记录3] ```  ### D. Lexicon(词表) 词表是记录格式的定义,类似于 TypeScript 类型定义,但更丰富: ```json { "lexicon": 1, "id": "com.twitter.post", "defs": { "main": { "type": "record", "key": "tid", "record": { "type": "object", "required": ["text", "createdAt"], "properties": { "text": { "type": "string", "maxGraphemes": 300 }, "createdAt": { "type": "string", "format": "datetime" } } } } } } ``` 词表特点: - 可以表达约束(如字符串长度、格式) - 易于解析,便于构建工具 - 可以生成多种语言的类型定义和验证代码 ### E. DID(去中心化标识符) DID 是账户的永久标识符,支持多种方法: ```mermaid graph TD DID[DID 标识符] --> Methods[方法类型] Methods --> did_web[did:web - 域名] Methods --> did_plc[did:plc - 注册表] Methods --> did_future[did:bla - 未来方法] did_web --> Example1[did:web:wint.co] did_plc --> Example2[did:plc:6wpkkitfdkgthatfvspcfmjo] ```  DID 解析过程: 1. 给定 DID,获取其文档(包含当前托管、句柄、公钥) 2. 文档指向数据的实际托管位置 3. 从托管位置获取记录 # 五、技术实现细节 ## 1. 记录键命名 使用时间戳加随机性混合的编码: ``` posts/ ├── 34qye3wows2c5 ├── 34qye3wows2k3 └── 34qye3wows3k3 ``` 优点: - 可以本地生成,几乎不会冲突 - 按字母排序即按时间排序 - ls -r 可以得到按时间倒序的时间线 ## 2. at:// URI at:// URI 是指向记录的永久链接,可以经受托管和句柄变更: ``` at://did:plc:6wpkkitfdkgthatfvspcfmjo/com.twitter.post/34qye3wows2c5 └─────────── who ──────────────┘ └─ collection ─┘ └── record ─┘ ``` 解析流程: 1. 解析 DID 获取托管位置 2. 从托管位置获取指定集合中的记录 ## 3. 记录间关系 通过 at:// URI 实现记录间的引用: ```mermaid graph TD Post[Post 记录] --> hasLikes[有点赞] hasLikes --> Like1[Like 记录] hasLikes --> Like2[Like 记录] hasLikes --> Like3[Like 记录] Like1 --> references[引用] references --> Post Post --> hasReplies[有回复] hasReplies --> Reply1[Reply 记录] Reply1 --> parentField[parent 字段] parentField --> references ```  示例: - 点赞记录:{ "subject": "at://did:plc:xxx/com.twitter.post/34qye3wows2c5" } - 回复记录:{ "text": "yes", "parent": "at://did:plc:xxx/com.twitter.post/34qye3wows2c5" } # 六、数据完整性验证 ## 1. 哈希树结构 仓库结构化为哈希树(Merkle Tree): ```mermaid graph TD Root[Root Hash] --> Commit[签名 Commit] Commit --> Tree[Tree Delta] Tree --> contains1[包含] contains1 --> Record1[记录 1] Tree --> contains2[包含] contains2 --> Record2[记录 2] Tree --> contains3[包含] contains3 --> Record3[记录 3] ```  每次写入都是包含新根哈希的签名提交,这使得: - 可以验证记录与原作者公钥的匹配 - 中继可以只重传证明,不存储内容 - 降低中继运行成本 ## 2. 数据流订阅 除了将仓库视为文件系统(列出和读取),还可以将其视为流,通过 WebSocket 订阅。 ```mermaid sequenceDiagram Repo as Repository Relay as Relay 中继 App as 应用缓存 Repo->>Relay: 提交新记录 Relay->>App: 推送事件 + 树证明 App->>App: 验证证明 App->>App: 更新本地缓存 ``` # 七、实际应用案例 ## 1. Sidetrail 应用 作者创建的 Sidetrail 应用演示了数据真实来源于仓库的概念: ```typescript export async function handleEvent(db: IngesterDb, evt: JetstreamEvent): Promise<void> { if (evt.kind !== "commit") return; const { commit } = evt; const { collection, rkey } = commit; if (commit.operation === "delete") { switch (collection) { case "app.sidetrail.walk": await deleteWalk(db, uri); break; } return; } const record = commit.record as Record<string, unknown>; switch (collection) { case "app.sidetrail.trail": await upsertTrail(db, uri, commit.cid, evt.did, rkey, record); break; } } ``` 用户在 pdsls 中删除 app.sidetrail.walk 记录,Sidetrail 应用中的对应 walk 会自动消失。 ## 2. teal.fm 演示 一个展示最近播放曲目的演示: ```mermaid graph LR Users[用户] --> Scrobble[Scrobble 记录] Scrobble --> creates[创建] creates --> fm_teal[fm.teal.alpha.feed.play] fm_teal --> indexed[被索引] indexed --> Relay[中继] Relay --> GraphQL[lex-gql GraphQL] GraphQL --> Demo[演示网站] ```  关键点: - teal.fm API 实际上不存在 - teal.fm 产品也只是着陆页 - 任何人都可以开始通过在仓库中放入记录来记录播放 - 演示只索引 fm.teal.alpha.feed.play 记录 # 八、词表生态系统 ## 1. 词表发现 通过以下工具发现现有词表: - pdsls.dev:词表目录服务 - Lexicon Garden:词表展示平台 - UFOs:词例浏览器 ## 2. 词表发布 词表可以作为记录发布: ```mermaid graph TD Lexicon[词表定义] --> publish[发布到] publish --> com_atproto[com.atproto.lexicon.schema] com_atproto --> contains[包含] contains --> io_overreacted[io.overreacted.comment] ```  需要通过 DNS 设置证明域名所有权。 ## 3. 词表验证原则 - 应用始终将记录视为不受信任的输入 - 在读取时验证,就像文件一样 - 演进词表时不能改变哪些记录被认为是有效的 - 可以添加新的可选字段,但不能改变字段的可选性 # 九、信任模型 ## 1. PLC 目录 PLC(Permissionless Concatenatable Log)目录的特点: ```mermaid graph TD User[用户] --> creates1[创建账户] creates1 --> Generate[生成密钥对] Generate --> Sign[签名操作] Sign --> Hash[哈希] Hash --> DID[DID 标识符] User --> updates[更新] updates --> NewOp[新操作] NewOp --> Prev[prev 指向前一个] Prev --> Chain[操作链] ```  验证过程: 1. 检查签名有效 2. prev 字段匹配前一个操作的哈希 3. 验证整个更新链到第一个操作 4. 第一个操作的哈希就是标识符 ## 2. 中继信任 中继不存储私钥数据、完全开源、操作日志可审计。理想情况下会独立成为法律实体。 # 十、优势与挑战 ## 1. 优势 ### A. 数据主权 用户真正拥有自己的数据,可以自由迁移托管 ### B. 应用创新 任何人都可以为现有数据创建新应用 ### C. 互操作性 不同应用可以共享和理解相同的数据格式 ### D. 可验证性 数据可以验证真实性,无需信任中继 ## 2. 挑战 ### A. 派生数据计算 应用需要计算派生数据(如点赞数)而无需额外开销 ### B. 中继信任 如何确保他人的中继不撒谎 ### C. 用户体验 密钥管理对大多数用户来说很复杂 # 十一、总结 AT 协议通过将文件系统理念引入社交网络,实现了: 1. 数据与应用的真正分离 2. 用户数据归属于用户 3. 应用可以自由创新,不被锁定 4. 数据可验证、可迁移、可互操作 这种范式转变可能重新定义社交网络的基础架构,让社交计算回归个人计算的本质。 *** ## 参考资料 1. [A Social Filesystem - overreacted.io](https://overreacted.io/a-social-filesystem/) 2. [AT Protocol 官方网站](https://atproto.com/) 3. [Bluesky 社交网络](https://bsky.app/) 4. [Lexicon Garden - 词表展示平台](https://lexicon.garden/) 5. [pdsls - AT Protocol 文件管理器](https://pdsls.dev) 最后修改:2026 年 01 月 19 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏