<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Julian Geiger Nunes</title>
    <description>The latest articles on DEV Community by Julian Geiger Nunes (@juliangn).</description>
    <link>https://dev.to/juliangn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3962901%2Fae7f830c-cc54-4681-a780-2fa7e3c1e4ab.jpg</url>
      <title>DEV Community: Julian Geiger Nunes</title>
      <link>https://dev.to/juliangn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juliangn"/>
    <language>en</language>
    <item>
      <title>FadeKey: zero-knowledge, self-destructing secret sharing engine</title>
      <dc:creator>Julian Geiger Nunes</dc:creator>
      <pubDate>Sat, 06 Jun 2026 21:57:06 +0000</pubDate>
      <link>https://dev.to/juliangn/fadekey-zero-knowledge-self-destructing-secret-sharing-engine-598k</link>
      <guid>https://dev.to/juliangn/fadekey-zero-knowledge-self-destructing-secret-sharing-engine-598k</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FadeKey&lt;/strong&gt; 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 (&lt;code&gt;#key=...&lt;/code&gt;). Since browsers do not send the hash fragment in HTTP requests, the server never sees the key or plaintext.&lt;br&gt;
The project is divided into two distinct components:&lt;br&gt;
&lt;strong&gt;Public Open-Source Core:&lt;/strong&gt; A standalone, stateless Fastify API and SDK package for self-hosting and automation via pipelines/CLI.&lt;br&gt;
&lt;strong&gt;Private SaaS Dashboard:&lt;/strong&gt; A commercial-grade Nuxt 4 web app that adds user accounts, Postgres database sync, persistent audit logs, and Stripe subscription control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Site (Private SaaS):&lt;/strong&gt; &lt;a href="https://fadekey.app" rel="noopener noreferrer"&gt;https://fadekey.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository (Open-Source Core):&lt;/strong&gt; &lt;a href="https://github.com/fadekey-app/fadekey.api" rel="noopener noreferrer"&gt;https://github.com/fadekey-app/fadekey.api&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faamjwq8bpphhmsfduoh9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faamjwq8bpphhmsfduoh9.png" alt=" " width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;We resurrected an unfinished prototype that had major security flaws, incomplete features, and a leaking state. Here is our before-and-after journey:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Active Revocation (SDK &amp;amp; API Core)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt; Secrets could only expire via TTL or view limits. The backend lacked a deletion endpoint, and the &lt;code&gt;@fadekey/sdk&lt;/code&gt; had an empty placeholder where &lt;code&gt;revoke()&lt;/code&gt; should have been.&lt;br&gt;
&lt;strong&gt;After:&lt;/strong&gt; We built a secure &lt;code&gt;DELETE /api/items/:id&lt;/code&gt; route in the Fastify API (with owner verification checks) and implemented the corresponding &lt;code&gt;revoke(id)&lt;/code&gt; method in the SDK package.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Zero-Knowledge Compliance for QR Codes (UX/Security)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt; The prototype suggested using external public APIs to generate QR codes. However, sending the full secret URL (containing the &lt;code&gt;#key&lt;/code&gt; hash) to a third-party server violates zero-knowledge compliance.&lt;br&gt;
&lt;strong&gt;After:&lt;/strong&gt; We moved 100% of the QR code generation to the browser using local client-side rendering with the &lt;code&gt;qrcode&lt;/code&gt; library, ensuring the decryption key never leaves the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Local-to-Cloud Preference Syncing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt; 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.&lt;br&gt;
&lt;strong&gt;After:&lt;/strong&gt; 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 &lt;code&gt;PATCH /api/auth/preferences&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Critical Nuxt SSR Session Leaks (Major Bugfix)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt; 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.&lt;br&gt;
&lt;strong&gt;After:&lt;/strong&gt; We refactored the auth composable to store sessions in request-isolated Nuxt &lt;code&gt;useState&lt;/code&gt; wrappers, guaranteeing sandboxed memory for every client.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Transition Polish &amp;amp; Redirection Guarding
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt; Logging out caused dashboard pages to immediately display blank values and zeroes before redirecting. Redirections also dropped the active language prefix (e.g. redirecting &lt;code&gt;/pt-BR/app/dashboard&lt;/code&gt; to &lt;code&gt;/&lt;/code&gt; instead of &lt;code&gt;/pt-BR&lt;/code&gt;).&lt;br&gt;
&lt;strong&gt;After:&lt;/strong&gt; We deferred state destruction in &lt;code&gt;signOut()&lt;/code&gt; until after the router navigation completes, backed by a &lt;code&gt;nextTick&lt;/code&gt; + delay in &lt;code&gt;router.afterEach&lt;/code&gt; to allow the DOM to mount. We wrapped all redirects in &lt;code&gt;localePath()&lt;/code&gt; to ensure language consistency.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot acted as a core partner during this sprint, particularly in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Refactoring Auth for SSR Safety:&lt;/strong&gt; Copilot recognized the risks of our initial module-level singleton state in Nuxt and drafted the migration to request-scoped &lt;code&gt;useState&lt;/code&gt; hooks, pointing out how to avoid server-side data pollution.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Writing Vitest Suites with Testcontainers:&lt;/strong&gt; 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.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Client-side Encryption Pipelines:&lt;/strong&gt; Copilot assisted in structuring the Web Crypto API calls in our SDK to correctly derive password hashes using PBKDF2 without introducing synchronous blocking.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
    </item>
  </channel>
</rss>
