FadeKey: zero-knowledge, self-destructing secret sharing engine

FadeKey: Zero-knowledge, self-destructing secret sharing engine

FadeKey:零知识、自毁式密钥共享引擎

GitHub “Finish-Up-A-Thon” Challenge Submission. This is a submission for the GitHub Finish-Up-A-Thon Challenge. GitHub “Finish-Up-A-Thon” 挑战赛参赛作品。这是我为 GitHub Finish-Up-A-Thon 挑战赛提交的项目。

What I Built: FadeKey is a zero-knowledge, self-destructing secret sharing engine. Encrypted entirely in the browser using AES-GCM, the decryption key resides only in the URL hash fragment (#key=…). Since browsers do not send the hash fragment in HTTP requests, the server never sees the key or plaintext. 我构建了什么:FadeKey 是一个零知识、自毁式的密钥共享引擎。它完全在浏览器中使用 AES-GCM 进行加密,解密密钥仅存在于 URL 的哈希片段(#key=…)中。由于浏览器不会在 HTTP 请求中发送哈希片段,因此服务器永远无法获取密钥或明文。

The project is divided into two distinct components: 该项目分为两个不同的组件:

  • Public Open-Source Core: A standalone, stateless Fastify API and SDK package for self-hosting and automation via pipelines/CLI.

  • 公共开源核心:一个独立的、无状态的 Fastify API 和 SDK 包,用于自托管以及通过流水线/CLI 进行自动化操作。

  • Private SaaS Dashboard: A commercial-grade Nuxt 4 web app that adds user accounts, Postgres database sync, persistent audit logs, and Stripe subscription control.

  • 私有 SaaS 控制面板:一个商业级的 Nuxt 4 Web 应用,增加了用户账户、Postgres 数据库同步、持久化审计日志以及 Stripe 订阅控制功能。

Demo Live Site (Private SaaS): https://fadekey.app GitHub Repository (Open-Source Core): https://github.com/fadekey-app/fadekey.api 演示站点(私有 SaaS):https://fadekey.app GitHub 仓库(开源核心):https://github.com/fadekey-app/fadekey.api

The Comeback Story: We resurrected an unfinished prototype that had major security flaws, incomplete features, and a leaking state. Here is our before-and-after journey: 回归故事:我们复活了一个未完成的原型项目,它曾存在重大的安全漏洞、功能缺失以及状态泄露问题。以下是我们改进前后的历程:

1. Active Revocation (SDK & API Core)

1. 主动撤销(SDK 与 API 核心)

Before: Secrets could only expire via TTL or view limits. The backend lacked a deletion endpoint, and the @fadekey/sdk had an empty placeholder where revoke() should have been. 改进前:密钥只能通过 TTL(生存时间)或查看次数限制来过期。后端缺乏删除接口,且 @fadekey/sdk 在本应放置 revoke() 方法的地方只有一个空占位符。

After: We built a secure DELETE /api/items/:id route in the Fastify API (with owner verification checks) and implemented the corresponding revoke(id) method in the SDK package. 改进后:我们在 Fastify API 中构建了一个安全的 DELETE /api/items/:id 路由(包含所有者验证检查),并在 SDK 包中实现了相应的 revoke(id) 方法。

2. Zero-Knowledge Compliance for QR Codes (UX/Security)

2. 二维码的零知识合规性(用户体验/安全)

Before: The prototype suggested using external public APIs to generate QR codes. However, sending the full secret URL (containing the #key hash) to a third-party server violates zero-knowledge compliance. 改进前:原型建议使用外部公共 API 来生成二维码。然而,将完整的密钥 URL(包含 #key 哈希)发送到第三方服务器违反了零知识合规性。

After: We moved 100% of the QR code generation to the browser using local client-side rendering with the qrcode library, ensuring the decryption key never leaves the client. 改进后:我们将二维码生成功能 100% 迁移到了浏览器端,使用 qrcode 库进行本地客户端渲染,确保解密密钥永远不会离开客户端。

3. Local-to-Cloud Preference Syncing

3. 本地到云端的偏好设置同步

Before: Users lost their theme (dark/light) and locale (en/es/pt-BR) settings upon page reload, and there was no way to persist these preferences for registered users. 改进前:用户在页面刷新后会丢失主题(深色/浅色)和语言(英语/西班牙语/葡萄牙语)设置,且注册用户无法持久化保存这些偏好。

After: We built a dual-persistence system. Anonymous users store preferences in cookies/localStorage, while authenticated users sync their choices automatically to a PostgreSQL database via a new PATCH /api/auth/preferences endpoint. 改进后:我们构建了一个双重持久化系统。匿名用户将偏好存储在 cookie/localStorage 中,而认证用户则通过新的 PATCH /api/auth/preferences 接口自动将选择同步到 PostgreSQL 数据库。

4. Critical Nuxt SSR Session Leaks (Major Bugfix)

4. 关键的 Nuxt SSR 会话泄露(重大 Bug 修复)

Before: The authentication state was stored in a global reactive singleton. During Server-Side Rendering (SSR), this leaked the session/token of one user to subsequent requests from completely different visitors, causing security risks and hydration errors. 改进前:认证状态存储在一个全局响应式单例中。在服务端渲染(SSR)期间,这会导致一个用户的会话/令牌泄露给后续完全不同的访问者,从而引发安全风险和水合(hydration)错误。

After: We refactored the auth composable to store sessions in request-isolated Nuxt useState wrappers, guaranteeing sandboxed memory for every client. 改进后:我们重构了认证组合式函数(composable),将会话存储在请求隔离的 Nuxt useState 包装器中,确保每个客户端的内存都是沙盒化的。

5. Transition Polish & Redirection Guarding

5. 过渡优化与重定向保护

Before: Logging out caused dashboard pages to immediately display blank values and zeroes before redirecting. Redirections also dropped the active language prefix (e.g. redirecting /pt-BR/app/dashboard to / instead of /pt-BR). 改进前:注销时,控制面板页面在重定向之前会立即显示空白值和零。重定向还会丢失当前的语言前缀(例如,将 /pt-BR/app/dashboard 重定向到 / 而不是 /pt-BR)。

After: We deferred state destruction in signOut() until after the router navigation completes, backed by a nextTick + 150ms delay in router.afterEach to allow the DOM to mount. We wrapped all redirects in localePath() to ensure language consistency. 改进后:我们将 signOut() 中的状态销毁推迟到路由导航完成之后,并辅以 router.afterEach 中的 nextTick + 150ms 延迟,以确保 DOM 完成挂载。我们将所有重定向包裹在 localePath() 中,以确保语言的一致性。

My Experience with GitHub Copilot

我使用 GitHub Copilot 的体验

GitHub Copilot acted as a core partner during this sprint, particularly in: 在本次冲刺开发中,GitHub Copilot 成为了核心合作伙伴,特别是在以下方面:

  • Refactoring Auth for SSR Safety: Copilot recognized the risks of our initial module-level singleton state in Nuxt and drafted the migration to request-scoped useState hooks, pointing out how to avoid server-side data pollution.

  • 重构认证以实现 SSR 安全:Copilot 识别出了我们最初在 Nuxt 中使用模块级单例状态的风险,并起草了向请求作用域 useState 钩子的迁移方案,指出了如何避免服务端数据污染。

  • Writing Vitest Suites with Testcontainers: It accelerated the creation of our backend integration tests, generating mock Postgres databases and Redis instances using Docker Testcontainers to test rate-limiting and quota rollback scenarios.

  • 使用 Testcontainers 编写 Vitest 测试套件:它加速了我们后端集成测试的创建,利用 Docker Testcontainers 生成模拟的 Postgres 数据库和 Redis 实例,用于测试速率限制和配额回滚场景。

  • Client-side Encryption Pipelines: Copilot assisted in structuring the Web Crypto API calls in our SDK to correctly derive password hashes using PBKDF2 without introducing synchronous blocking.

  • 客户端加密流水线:Copilot 协助构建了 SDK 中的 Web Crypto API 调用,使用 PBKDF2 正确派生密码哈希,且不会引入同步阻塞。