FadeKey: zero-knowledge, self-destructing secret sharing engine
Source: Dev.to

[](https://dev.to/juliangn)
GitHub “Finish-Up-A-Thon” Challenge Submission
This is a submission for the GitHub Finish-Up-A-Thon Challenge
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.
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.
- Private SaaS Dashboard: A commercial-grade Nuxt 4 web app that adds user accounts, Postgres database sync, persistent audit logs, and Stripe subscription control.
Demo
Live Site (Private SaaS): https://fadekey.app
GitHub Repository (Open-Source Core): 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:
- Active Revocation (SDK & API Core)
- Before: Secrets could only expire via TTL or view limits. The backend lacked a deletion endpoint, and the
@fadekey/sdkhad an empty placeholder whererevoke()should have been.
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.
2. Zero-Knowledge Compliance for QR Codes (UX/Security)
- Before: The prototype suggested using external public APIs to generate QR codes. However, sending the full secret URL (containing the
#keyhash) to a third-party server violates zero-knowledge compliance.
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.
3. Local-to-Cloud Preference Syncing
- 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.
4. Critical Nuxt SSR Session Leaks (Major Bugfix)
- 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.
After: We refactored the auth composable to store sessions in request-isolated Nuxt useState wrappers, guaranteeing sandboxed memory for every client.
5. Transition Polish & Redirection Guarding
- 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/dashboardto/instead of/pt-BR).
- After: We deferred state destruction in
signOut()until after the router navigation completes, backed by anextTick+ 150ms delay inrouter.afterEachto allow the DOM to mount. We wrapped all redirects inlocalePath()to ensure language consistency.
My Experience with GitHub Copilot
GitHub Copilot acted as a core partner during this sprint, particularly in:
-
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
useStatehooks, pointing out how to avoid server-side data pollution. -
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.
-
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.
