<?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: Pranav Kishan</title>
    <description>The latest articles on DEV Community by Pranav Kishan (@pranav_kishan_).</description>
    <link>https://dev.to/pranav_kishan_</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3669047%2Fe14eda30-1493-460f-bccf-2742af9d8310.jpg</url>
      <title>DEV Community: Pranav Kishan</title>
      <link>https://dev.to/pranav_kishan_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pranav_kishan_"/>
    <language>en</language>
    <item>
      <title>The Judge That Never Guesses</title>
      <dc:creator>Pranav Kishan</dc:creator>
      <pubDate>Sun, 20 Sep 2026 18:05:12 +0000</pubDate>
      <link>https://dev.to/pranav_kishan_/the-judge-that-never-guesses-43l9</link>
      <guid>https://dev.to/pranav_kishan_/the-judge-that-never-guesses-43l9</guid>
      <description>&lt;h1&gt;
  
  
  The Judge That Never Guesses
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;How an AI pipeline that fixes its own bugs still refuses to trust its own opinion.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every autonomous system eventually faces the same temptation: let the thing that did the work also decide whether the work was any good. It's efficient. It's tidy. It's also how you end up with a pipeline that reports success on a run that quietly made everything worse. Klyro was built to resist that temptation on purpose, and the reasoning behind it is worth walking through in full.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Let the Model Grade Its Own Homework
&lt;/h2&gt;

&lt;p&gt;There's an obvious shortcut Klyro doesn't take: asking the same LLM that proposed a fix whether the fix actually worked. It would take one extra prompt to wire up, and it would be easy to trust right up until the first time it's wrong in a way nobody catches. Language models are persuasive by design. Ask one to defend its own patch and it will find a reason the numbers look fine, even when they don't.&lt;/p&gt;

&lt;p&gt;So the verdict on every run comes from deterministic code, never a model call. No prompt, no interpretation, no room for a confident-sounding rationalization. Just a fixed set of numeric thresholds applied to numbers a load test actually produced. The Investigator gets to be creative, proposing whatever fix it thinks will help. The Evaluator does not get that luxury, and that asymmetry is the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trap of Self-Grading
&lt;/h2&gt;

&lt;p&gt;It's worth being specific about why this matters. An LLM asked to evaluate its own output isn't lying, exactly. It's doing what it was trained to do: produce a plausible, coherent answer to the question it was asked. "Did this help?" is a question with a plausible-sounding "yes" available almost regardless of the data, especially once the model has already committed, in an earlier turn, to believing the fix was a good idea.&lt;/p&gt;

&lt;p&gt;That failure mode doesn't show up in a demo. It shows up three weeks later, when someone finally cross-checks a "validated" run against the raw metrics and finds the p95 latency barely moved. By then the bad verdict has already shaped a decision. Klyro closes that gap by never letting the question reach a model in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changed Is Not the Same as Validated
&lt;/h2&gt;

&lt;p&gt;The Evaluator draws a specific, unforgiving line between two things that sound similar and aren't. Performance can change after a patch without that change meaning anything worth celebrating. A fix might shave milliseconds off one endpoint while quietly pushing error rates up somewhere else, and "changed" would technically be true.&lt;/p&gt;

&lt;p&gt;"Validated" is a stricter claim, and Klyro only makes it when three conditions hold at once:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;p95 latency&lt;/td&gt;
&lt;td&gt;Improves by at least 10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error rate&lt;/td&gt;
&lt;td&gt;Moves by no more than 0.5 percentage points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU utilization&lt;/td&gt;
&lt;td&gt;Stays at or under 95%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Miss any one of those and the run reports a change, not a validated optimization. That distinction, one word doing a lot of quiet work, is where a system that's honest about what an LLM's fix actually accomplished lives. It's the difference between "something happened" and "something worth trusting happened."&lt;/p&gt;

&lt;h2&gt;
  
  
  Same Workload, Same Data, Every Time
&lt;/h2&gt;

&lt;p&gt;None of those thresholds mean anything if the before and after runs aren't genuinely comparable. A p95 improvement measured against a lighter workload or a warmer cache isn't evidence of anything except that the test changed, and a system that lets its comparison drift is a system quietly grading on a curve without admitting it.&lt;/p&gt;

&lt;p&gt;Klyro treats that risk the way a controlled experiment would. Task CPU, memory, and replica count stay identical across both runs. The exact same k6 workload hits both. The database gets the same discipline: db-init runs a full DROP and CREATE SCHEMA followed by a fresh seed before every single run, never an INSERT-only reset that could leave leftover rows from a previous attempt quietly nudging the numbers one way or another. If the "after" run looks better, it has to be because the patch made it better. There's no easier lane for it to have found instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Patch Has to Prove It Is What It Claims to Be
&lt;/h2&gt;

&lt;p&gt;The trust story doesn't stop at measurement. It starts earlier, at the moment a patch is proposed at all. Before any patch from the Investigator gets anywhere near a rebuild, it has to carry the &lt;code&gt;original_sha256&lt;/code&gt; of the file it targets, checked against that file exactly as it exists right now. A mismatch means the patch doesn't apply, full stop, no partial credit and no best-effort merge.&lt;/p&gt;

&lt;p&gt;That check is paired with something even simpler: a three-file allowlist the Investigator is boxed into, covering only the files a performance fix should ever need to touch. Together, those two guardrails mean the thing the Evaluator eventually judges is provably the exact change that was proposed, applied to the exact file it claimed to target. Nothing smuggled in. Nothing silently dropped. By the time a number reaches the Evaluator, its provenance is no longer a question anyone has to take on faith.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Guardrails Compound
&lt;/h2&gt;

&lt;p&gt;Looked at individually, the sha256 check, the file allowlist, and the deterministic Evaluator each solve a narrow problem. Looked at together, they form a chain of custody that runs from the moment a fix is imagined to the moment a verdict is printed. A patch can't drift from what it claims to be. A verdict can't be shaped by the same reasoning that produced the patch. Each link only has to hold its own weight, which is exactly what makes the whole chain trustworthy instead of merely convincing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Different Kinds of Trust
&lt;/h2&gt;

&lt;p&gt;Trusting an LLM to notice a slow database query and propose a fix is one kind of trust. It's a bet on creativity and pattern recognition, and it's fine to lose that bet occasionally, because a bad patch just fails to validate. Trusting a system to tell you, honestly, whether that fix actually helped is a completely different kind of trust, and conflating the two is how systems end up reporting success that doesn't survive a second look.&lt;/p&gt;

&lt;p&gt;Klyro keeps those jobs in separate hands on purpose. An LLM proposes. A guard verifies the proposal is what it claims to be. Plain deterministic code renders the verdict. None of the three steps has to trust the others' judgment, only their outputs, and that's precisely why the whole pipeline can be trusted at all.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Designing a Zero-Knowledge Persistent Personal Information Manager with Client-Side Encryption</title>
      <dc:creator>Pranav Kishan</dc:creator>
      <pubDate>Sat, 20 Dec 2025 16:25:10 +0000</pubDate>
      <link>https://dev.to/pranav_kishan_/designing-a-zero-trust-personal-information-manager-with-client-side-encryption-4pb5</link>
      <guid>https://dev.to/pranav_kishan_/designing-a-zero-trust-personal-information-manager-with-client-side-encryption-4pb5</guid>
      <description>&lt;p&gt;I am a B.Tech Computer Science undergraduate at &lt;strong&gt;Amrita Vishwa Vidyapeetham&lt;/strong&gt; who enjoys building privacy-focused systems and learning by deploying real software end-to-end.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Motivation
&lt;/h2&gt;

&lt;p&gt;The inception of &lt;strong&gt;InfoStuffs&lt;/strong&gt; was not driven by a desire to build just another productivity application. It started with a very specific user requirement from my sister. She needed a digital space to organize personal documents and sensitive notes but refused to use standard cloud services such as Google Keep or Notion.&lt;/p&gt;

&lt;p&gt;Her constraint was simple but technically demanding: &lt;strong&gt;she wanted the convenience of the cloud without trusting the cloud provider with her plaintext data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This challenge became the foundation of InfoStuffs. My goal shifted from building a simple web application to architecting a &lt;strong&gt;Zero-Knowledge Information Management System&lt;/strong&gt; that prioritizes privacy by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Statement
&lt;/h2&gt;

&lt;p&gt;Modern productivity tools generally fall into two categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Convenient SaaS:&lt;/strong&gt; (e.g., Notion, Keep) store user data in plaintext or use server-managed keys, leaving data vulnerable to internal leaks or database breaches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-Hosted:&lt;/strong&gt; (e.g., Obsidian, Nextcloud) offer strong privacy but are difficult to access and maintain across multiple devices.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;InfoStuffs bridges this gap. The system had to be secure enough that a &lt;strong&gt;complete server-side compromise would yield nothing but garbage data&lt;/strong&gt;, yet accessible via a standard web browser on any device.&lt;/p&gt;

&lt;h2&gt;
  
  
  High-Level Architecture
&lt;/h2&gt;

&lt;p&gt;To satisfy these constraints, InfoStuffs uses a decoupled, cloud-native architecture with clearly separated responsibilities.&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8eu2329chvc21mlh7o61.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8eu2329chvc21mlh7o61.png" alt="Architecture diagram for infostuffs" width="800" height="871"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React (Vite) with Material UI. Responsibilities include UI rendering and &lt;strong&gt;client-side cryptographic operations&lt;/strong&gt; (encryption/decryption).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Node.js and Express, utilizing a &lt;strong&gt;Serverless Architecture&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Development:&lt;/strong&gt; Runs as a &lt;strong&gt;fully dockerized monolithic container&lt;/strong&gt;, ensuring a consistent development environment that mirrors production dependencies.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Production Deployment:&lt;/strong&gt; Deployed to &lt;strong&gt;Vercel&lt;/strong&gt; as &lt;strong&gt;stateless Serverless Functions&lt;/strong&gt;, allowing the API to scale to zero when idle (cost-efficient) while maintaining a single Express codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database:&lt;/strong&gt; MongoDB Atlas for storing encrypted metadata and ciphertext.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication:&lt;/strong&gt; Clerk. Delegating identity management reduced the attack surface for auth flows (MFA, session management).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Supabase Storage, used strictly for isolating binary objects (images and PDFs) via obfuscated paths and client-side encrypted blobs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security by Design: The Zero-Knowledge Vault
&lt;/h2&gt;

&lt;p&gt;Security was not an optional feature; it was the primary architectural constraint.&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcpmbhd9mxxeeiyn5n7r.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcpmbhd9mxxeeiyn5n7r.png" alt="Sequence diagram flow" width="800" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Problem with Static Keys
&lt;/h3&gt;

&lt;p&gt;In my initial design, I used a static encryption key stored in the server's environment variables (&lt;code&gt;VITE_SECRET_KEY&lt;/code&gt;). I quickly realized this was a critical flaw. If an attacker or a compromised hosting environment were to expose environment variables, they could decrypt everyone's data. The key was &lt;strong&gt;visible&lt;/strong&gt;, which violated the core concept of Zero-Knowledge.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Solution: User-Derived Cryptography
&lt;/h3&gt;

&lt;p&gt;To fix this, I removed the static key entirely. I implemented &lt;strong&gt;PBKDF2 (Password-Based Key Derivation Function 2)&lt;/strong&gt; on the client side.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When a user logs in, they enter a &lt;strong&gt;Vault Password&lt;/strong&gt;. This password is never transmitted or stored and exists only transiently in the client’s memory.&lt;/li&gt;
&lt;li&gt;The browser runs PBKDF2 to derive a temporary 256-bit AES-GCM key in memory.&lt;/li&gt;
&lt;li&gt;This key is used to encrypt notes, titles, and file paths &lt;em&gt;before&lt;/em&gt; the network request is even formed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The server only ever sees (and stores) ciphertext. If the database administrator (me) were to look at the data, I would see nothing but unreadable strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ephemeral Access to Media
&lt;/h3&gt;

&lt;p&gt;For file storage, I avoided public buckets entirely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted Paths:&lt;/strong&gt; The database stores an &lt;em&gt;encrypted&lt;/em&gt; string pointing to the file path (e.g., "user/123/image.jpg" is encrypted).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Obfuscated Storage:&lt;/strong&gt; Uploaded files generate randomized UUID storage paths, so the storage provider never sees the original filenames.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-Demand Access:&lt;/strong&gt; When a user unlocks their vault, the client decrypts the path and requests a &lt;strong&gt;Signed URL&lt;/strong&gt; from Supabase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-Limited:&lt;/strong&gt; Signed URLs are valid for one hour. This prevents "link sharing" leaks and ensures that even if a URL is intercepted, it becomes useless quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Zero-Knowledge Offline Vault (PWA)
&lt;/h3&gt;

&lt;p&gt;To make the app truly resilient, I engineered a complete offline mode without sacrificing the encryption model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offline Caching:&lt;/strong&gt; During an online session, raw encrypted ciphertexts of the user's notes are saved into IndexedDB; plaintext is never stored on disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant Offline Detection:&lt;/strong&gt; A module-level event interceptor and a fast connectivity probe immediately detect offline states.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth Bypass &amp;amp; Key Derivation:&lt;/strong&gt; If offline, Clerk initialization is bypassed entirely. The app regenerates the AES-GCM key dynamically using the Vault Password and the cached, plaintext Clerk User ID as the PBKDF2 salt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Infrastructure Evolution: Solving the Cost Problem
&lt;/h2&gt;

&lt;p&gt;One of the most valuable learning experiences came from adapting the infrastructure to real-world cost constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1: The "Enterprise" Trap (GCP)
&lt;/h3&gt;

&lt;p&gt;My initial deployment used Google Cloud Platform with &lt;strong&gt;Cloud Run&lt;/strong&gt; and &lt;strong&gt;Cloud Build&lt;/strong&gt;. While this was an industry-standard "Enterprise" setup, it introduced significant problems for a personal project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Costs:&lt;/strong&gt; Paying for load balancers, container registry storage, and compute time quickly added up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; Managing IAM roles and build triggers for a simple app was overkill.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 2: The "Serverless Monolith" (Vercel)
&lt;/h3&gt;

&lt;p&gt;To solve the deployment cost problem, I re-architected the stack to run for &lt;strong&gt;$0/month&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Development (Dockerized):&lt;/strong&gt; I kept the convenience of a containerized environment. A single &lt;code&gt;docker-compose up&lt;/code&gt; spins up the Frontend, Backend, and Database services. This ensures that the development environment is isolated and reproducible on any machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production Deployment (Serverless):&lt;/strong&gt; Instead of paying for a permanently running container (which costs money even when idle), I refactored the Express application to run on &lt;strong&gt;Vercel Serverless Functions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Result:&lt;/strong&gt; I effectively have a "Serverless Monolith." I develop it like a standard monolithic app (easy to debug, easy to run locally in Docker) but deploy it as distributed functions. This gives me the best of both worlds: &lt;strong&gt;Zero infrastructure management&lt;/strong&gt; and &lt;strong&gt;Zero cost&lt;/strong&gt; for personal use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I intentionally avoided microservices, as the domain does not yet justify multiple bounded contexts, and premature service decomposition would increase complexity and attack surface without tangible benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Challenges &amp;amp; Performance Optimizations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Environment Variable Visibility&lt;/strong&gt;&lt;br&gt;
Relying on &lt;code&gt;.env&lt;/code&gt; files for security was a mistake. The migration to user-derived keys solved this, but it required handling edge cases like "Lost Passwords." Since I no longer had the key, I had to implement a &lt;strong&gt;"Nuclear Reset"&lt;/strong&gt; feature. This allows users to wipe their unrecoverable data and start fresh, prioritizing security over recovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Client-Side Decryption Bottlenecks&lt;/strong&gt;&lt;br&gt;
Rendering a vault full of encrypted images and text placed heavy load on the UI thread. I implemented two major optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intersection Observer Deferral:&lt;/strong&gt; Encrypted image attachments are only requested, downloaded, and decrypted when they scroll into the viewport.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Performance Base64 Parser:&lt;/strong&gt; I replaced slow native &lt;code&gt;Uint8Array.from()&lt;/code&gt; callbacks with custom loops, significantly reducing CPU overhead during decryption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. The Docker vs. Serverless Routing Mismatch&lt;/strong&gt;&lt;br&gt;
One of the most complex challenges was reconciling the difference between a running Docker container and Vercel's file-system routing. In my local Docker container, Express handled all routing internally. However, when deployed to Vercel, requests to sub-paths (like &lt;code&gt;/api/info/nuke&lt;/code&gt;) were hitting Vercel's 404 handler before reaching my Express app. I resolved this by creating a Vercel-compatible entry point (&lt;code&gt;api/info.js&lt;/code&gt;) and a rewrite rule that pipes all sub-route traffic directly into the Express instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Production OAuth Strictness&lt;/strong&gt;&lt;br&gt;
A critical UI bug emerged in production: users completing Google Sign-In were dumped onto a blank white screen at &lt;code&gt;/sso-callback&lt;/code&gt;. My SPA lacked a dedicated route to handle strict server-side redirects enforced in production. I architected a dedicated &lt;strong&gt;"OAuth Landing Pad"&lt;/strong&gt; component that intercepts the OAuth token, displays a branded loading state, and seamlessly completes the handshake before forwarding the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Roadmap
&lt;/h2&gt;

&lt;p&gt;While InfoStuffs is fully functional, I plan to explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Redis Caching:&lt;/strong&gt; To reduce database reads for frequently accessed (encrypted) metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native Mobile App:&lt;/strong&gt; Wrapping the existing logic to allow biometric vault unlocking (FaceID) instead of typing the password.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;InfoStuffs is more than a note-taking application. It is a practical exploration of &lt;strong&gt;Zero-Knowledge Engineering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By addressing the real-world problems of &lt;strong&gt;data visibility&lt;/strong&gt; and &lt;strong&gt;cloud costs&lt;/strong&gt;, I built a system where privacy is enforced by mathematics, not by policy. It satisfies a real user need while serving as a valuable learning experience in full-stack security and DevOps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/Destroyer795/InfoStuffs" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Live Deployment:&lt;/strong&gt; &lt;a href="https://info-stuffs.vercel.app" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The live deployment requires authentication and a vault password. The core security properties are enforced client-side and are best understood via the architecture discussion above.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>cloud</category>
      <category>security</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
