<?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: freerave</title>
    <description>The latest articles on DEV Community by freerave (@freerave).</description>
    <link>https://dev.to/freerave</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%2F3563889%2F6ecf3060-63f8-46f1-9869-b61412ef894c.png</url>
      <title>DEV Community: freerave</title>
      <link>https://dev.to/freerave</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/freerave"/>
    <language>en</language>
    <item>
      <title>DotShare AI 3.5.2: From Git Tags to Technical Articles You Can Review</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Thu, 08 Oct 2026 10:51:14 +0000</pubDate>
      <link>https://dev.to/freerave/dotshare-ai-352-from-git-tags-to-technical-articles-you-can-review-3lik</link>
      <guid>https://dev.to/freerave/dotshare-ai-352-from-git-tags-to-technical-articles-you-can-review-3lik</guid>
      <description>&lt;h2&gt;
  
  
  A deep dive into DotShare 3.5.2: release-aware AI articles, verified code excerpts, Dev.to live preview, and safer credential handling.
&lt;/h2&gt;

&lt;p&gt;An AI release article can sound convincing while describing code that never shipped.&lt;/p&gt;

&lt;p&gt;The failure is often subtle: a changelog comes from one version, source code comes from today's checkout, and an example gets rewritten into something that looks cleaner but no longer matches the implementation. By the time the article reaches the publishing screen, the facts have already drifted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DotShare AI 3.5.2 makes release selection, implementation evidence, and article review part of the writing workflow.&lt;/strong&gt; It adds a dedicated Dev.to article experience, strengthens the generation pipeline, and revises how credentials move between the extension host, its webviews, and the CLI.&lt;/p&gt;

&lt;p&gt;The work behind this update spans &lt;strong&gt;65 changed or new files&lt;/strong&gt;, including implementation, tests, documentation, dependency manifests, and build configuration. The useful result is what those changes let a developer do: choose a version, generate a technical draft from that version, inspect its formatting and code, and publish with a clearer understanding of what was checked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes in the daily workflow?
&lt;/h2&gt;

&lt;p&gt;DotShare already brings social and blog publishing into the editor. Version 3.5.2 expands the technical writing side of that workflow:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Behavior in this update&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Release selection&lt;/td&gt;
&lt;td&gt;Choose a committed release, current committed work at HEAD, or tracked uncommitted changes explicitly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation context&lt;/td&gt;
&lt;td&gt;Read release material from one resolved commit and include source excerpts with file and line information.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Article generation&lt;/td&gt;
&lt;td&gt;Generate a Markdown draft with metadata, validate it, and use a bounded repair pass when needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code examples&lt;/td&gt;
&lt;td&gt;Verify excerpts against supplied source or documentation; flag and omit remaining unverifiable examples when the rest of the draft passes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev.to review&lt;/td&gt;
&lt;td&gt;Preview the title, description, tags, and rendered body together.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Saved credentials&lt;/td&gt;
&lt;td&gt;Show &lt;strong&gt;🔒 Key Saved &amp;amp; Active&lt;/strong&gt;, with an empty replacement field available on demand.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI configuration&lt;/td&gt;
&lt;td&gt;Store supported platform credentials in the OS credential store and keep preferences in the configuration file.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The developer still owns the final editorial decision. The checks make specific problems detectable; they do not establish the truth of every sentence an AI writes.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A release article needs a consistent version of the project
&lt;/h2&gt;

&lt;p&gt;The first architectural change is the release boundary.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ReleaseRepository&lt;/code&gt; resolves the selected Git reference to a commit. That snapshot is then used for metadata, changelog content, release documents, source files, diffs, commits, and dependency comparisons. Reading these inputs from the same snapshot prevents a tagged release article from accidentally describing later local edits.&lt;/p&gt;

&lt;p&gt;The distinction becomes visible in the UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Committed release&lt;/strong&gt; describes the selected tagged version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current committed work (HEAD)&lt;/strong&gt; can describe committed changes beyond the latest tag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uncommitted changes&lt;/strong&gt; describes tracked local edits as work in progress.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if a repository contains a &lt;code&gt;v2.1.2&lt;/code&gt; tag and additional edits in the checkout, selecting &lt;code&gt;v2.1.2&lt;/code&gt; keeps those edits out of the release article. Choosing HEAD or uncommitted changes communicates a different scope.&lt;/p&gt;

&lt;p&gt;The collector also explains incomplete history. A first tagged release without a previous release tag can include the complete committed tree. In an untagged repository, the committed comparison can be limited to the latest commit. Warnings help the author understand the material behind the draft instead of guessing from the version label.&lt;/p&gt;

&lt;p&gt;Context is refreshed before generation, so an earlier modal preview is not silently treated as the final evidence set.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Workspace search follows the topic and the release boundary
&lt;/h2&gt;

&lt;p&gt;A useful technical article needs more than the last few commit messages.&lt;/p&gt;

&lt;p&gt;The context service can search Git history for terms from the selected topic. It combines commit-message matching with Git pickaxe searches for relevant code changes. Keyword extraction handles English and Arabic input, filtering conversational words so the search can focus on technical terms.&lt;/p&gt;

&lt;p&gt;The same selected boundary also governs dependency comparisons. DotShare recognizes manifests for several ecosystems:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ecosystem&lt;/th&gt;
&lt;th&gt;Manifest&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pyproject.toml&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go.mod&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That lets an article distinguish a dependency upgrade in the chosen release from an unrelated edit in the current checkout.&lt;/p&gt;

&lt;p&gt;Documentation adds another layer. Version-specific release files and relevant architecture or security documents can explain why a change exists. Multiline changelog notes are preserved so their meaning does not collapse into a handful of isolated bullets.&lt;/p&gt;

&lt;p&gt;The collector limits document and source budgets and reports truncation. A truncated README is a visible limitation, not evidence that the entire document was reviewed. Architecture notes provide background; roadmap items do not establish that a feature has shipped. A verification document can also contain checks that remain unfinished, and the article should retain that distinction.&lt;/p&gt;

&lt;p&gt;Active editor context is optional. A selected fragment can help identify the topic, but a local selection is labeled as a working-tree hint when writing about a committed release. It does not replace source read from the selected commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Code examples come from implementation excerpts
&lt;/h2&gt;

&lt;p&gt;Technical articles are especially vulnerable to invented examples. A plausible function name or a convincing security check is easy to generate and hard to spot during a quick read.&lt;/p&gt;

&lt;p&gt;DotShare now extracts source excerpts around added executable lines. The extractor looks for enclosing declarations and supplies the file path, line range, and whether the excerpt is partial. Ranking uses the release terms, identifiers, and changed code, while supporting helper or lifecycle methods can give a change the context it needs.&lt;/p&gt;

&lt;p&gt;This is bounded source extraction using language-aware heuristics. It is not a full compiler analysis of every supported language.&lt;/p&gt;

&lt;p&gt;The collector also reduces prompt noise by excluding material such as lockfiles, binary files, minified bundles, and test code from implementation examples. Python handling distinguishes executable changes from docstrings and test-oriented material.&lt;/p&gt;

&lt;p&gt;After generation, a separate verifier checks fenced examples. Implementation examples must match a contiguous excerpt from the supplied evidence. Display normalization allows line-ending differences and a uniform dedent while preserving internal indentation, string literals, and the actual statements.&lt;/p&gt;

&lt;p&gt;Reconstructing a function, inserting explanatory comments into its body, or joining unrelated pieces into a new example does not satisfy that rule.&lt;/p&gt;

&lt;p&gt;Documentation examples and shell commands have their own evidence rules. Commands must be supported by supplied documentation or fit a narrow recognized checkout workflow. Changing a fence label to &lt;code&gt;text&lt;/code&gt; does not provide a route around provenance checking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code is optional.&lt;/strong&gt; An article that explains a supported change clearly can be more useful than one padded with an invented implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Validation and repair have a defined stopping point
&lt;/h2&gt;

&lt;p&gt;The generation flow has three main stages: create a draft, check detectable problems, and repair when necessary.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ReleaseContentValidator&lt;/code&gt; checks problems including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty output and unfinished code fences.&lt;/li&gt;
&lt;li&gt;Unsupported fenced code examples.&lt;/li&gt;
&lt;li&gt;URLs outside the exact selected call-to-action links.&lt;/li&gt;
&lt;li&gt;Source paths that do not appear in supplied evidence.&lt;/li&gt;
&lt;li&gt;Certain numeric claims about tests or diff statistics without supporting material.&lt;/li&gt;
&lt;li&gt;Missing or invalid Dev.to metadata.&lt;/li&gt;
&lt;li&gt;A generated draft that incorrectly sets &lt;code&gt;published: true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Release prose that mixes in uncommitted work or exposes internal writing instructions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The service makes &lt;strong&gt;at most two generation attempts&lt;/strong&gt;. A validation problem can trigger one repair using the same evidence. The previous generated draft is identified as untrusted text rather than new evidence.&lt;/p&gt;

&lt;p&gt;There is also a bounded recovery path for a response that reaches its output limit. A retry with a larger budget uses the remaining attempt; it does not start an unlimited series of retries and repairs.&lt;/p&gt;

&lt;p&gt;Full Dev.to articles begin with a 6,000-token generation budget. The output-limit recovery can increase that budget up to 12,000 tokens. Technical deep dives and shorter posts use smaller budgets appropriate to their format. These are response budgets, not promises of an exact article length.&lt;/p&gt;

&lt;h3&gt;
  
  
  When an example still cannot be verified
&lt;/h3&gt;

&lt;p&gt;Earlier behavior could end the entire generation flow with a code-validation error even when most of the article was usable.&lt;/p&gt;

&lt;p&gt;The revised behavior is more precise. If the second attempt still contains closed, unverifiable code blocks, DotShare can omit those blocks and validate the remaining article again. When that article passes, the author receives a visible warning such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Omitted 1 code example(s) that could not be verified against the supplied evidence. Review the surrounding explanation before publishing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A short standalone introduction to an omitted example can be removed with it. Other prose remains available for review.&lt;/p&gt;

&lt;p&gt;The warning matters: removing a code block does not prove the neighboring explanation is correct. An unfinished fence, an unsupported URL, or another unresolved blocking error still prevents a successful result.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Provider completion is part of article quality
&lt;/h2&gt;

&lt;p&gt;A successful HTTP request does not necessarily contain a complete article.&lt;/p&gt;

&lt;p&gt;This update strengthens response handling across OpenAI, Claude, Gemini, DeepSeek, and xAI. Empty text is rejected, and provider-specific completion signals are checked before returning a draft.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Completion handling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;Detect incomplete Responses API output and distinguish output-limit truncation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude&lt;/td&gt;
&lt;td&gt;Combine text blocks and detect token-limit stops or refusal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;td&gt;Check candidate finish reasons, including output-token exhaustion.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;Check completion finish reasons and reject empty content.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xAI&lt;/td&gt;
&lt;td&gt;Check completion finish reasons and reject empty content.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Generation requests have explicit timeouts, and SDK retry settings are bounded where configured. The author gets an error for an incomplete response instead of a truncated article presented as finished.&lt;/p&gt;

&lt;p&gt;Live model discovery remains the foundation introduced in the previous release. The improvements here build on it with stronger response handling and safer reuse of saved keys. Provider/model request identifiers also help prevent an older asynchronous response from replacing a newer selection in the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Dev.to articles arrive as editable Markdown
&lt;/h2&gt;

&lt;p&gt;The Dev.to workflow now has a dedicated &lt;strong&gt;DotShare AI Article&lt;/strong&gt; action and a &lt;strong&gt;Full Article (Dev.to)&lt;/strong&gt; writing tone. The result is Markdown with YAML frontmatter, ready to inspect and edit.&lt;/p&gt;

&lt;p&gt;DotShare parses the metadata into separate publisher fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Title.&lt;/li&gt;
&lt;li&gt;Description.&lt;/li&gt;
&lt;li&gt;Tags, normalized and limited to four.&lt;/li&gt;
&lt;li&gt;Optional cover image, canonical URL, and series when supplied.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frontmatter is separated from the article body so the editor does not show metadata as prose. Generated content also receives publishing cleanup, including redundant opening titles and trailing hashtag lines where appropriate.&lt;/p&gt;

&lt;p&gt;The article title belongs in the title field. Body sections can start at &lt;code&gt;##&lt;/code&gt;, which keeps the hierarchy consistent with Dev.to's article page. This follows the conventions in the &lt;a href="https://dev.to/p/editor_guide/"&gt;DEV Editor Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Canonical URLs receive special treatment: a repository URL is not automatically used as the article's canonical URL. The repository identifies the project; a canonical URL identifies the original publication of the same article. Authors can add that field when it actually applies.&lt;/p&gt;

&lt;p&gt;The publisher retains both draft and publishing choices. Generating text is separate from deciding to publish it.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Live Preview includes the whole article header
&lt;/h2&gt;

&lt;p&gt;Reviewing only the Markdown body misses part of the reader's first impression.&lt;/p&gt;

&lt;p&gt;The updated Live Preview displays &lt;strong&gt;title, description, tags, then the article body&lt;/strong&gt;, using the current editor values. Changes to the metadata fields update the preview without another AI request. Direction-aware text also helps with Arabic and mixed-language content.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;marked&lt;/code&gt; renders the body and &lt;code&gt;DOMPurify&lt;/code&gt; sanitizes the resulting HTML. The title, description, and tag labels are inserted as text rather than interpreted as HTML. The preview supports familiar Markdown structures such as headings, lists, tables, blockquotes, and fenced code blocks, with code styling suitable for review.&lt;/p&gt;

&lt;p&gt;The UI includes word count, character count, and estimated reading time. They help authors judge the size of a draft without treating length as a measure of correctness.&lt;/p&gt;

&lt;p&gt;Related webview changes escape content in thread composers, media thumbnails, draft cards, and scheduled-post attributes. Custom publish-button labels also survive UI refreshes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Links respect the editor's decision
&lt;/h3&gt;

&lt;p&gt;Web links appear blue and can be clicked during review. The webview sends an opening request to the extension host, which accepts ordinary HTTP or HTTPS URLs and calls the editor's external-link API.&lt;/p&gt;

&lt;p&gt;This is the implementation in &lt;code&gt;src/services/PreviewLinkService.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;openArticlePreviewLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getPreviewWebUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Respect VS Code's result; a refusal must not trigger an alternate opener.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openExternal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If opening is declined or throws an error, the action stops. There is no alternate opener. Local resources and command URLs are not accepted as external article links. In-article anchors are handled within the preview.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Saved keys stay on the extension host
&lt;/h2&gt;

&lt;p&gt;Credential storage needed a review across the full workflow: platform configuration, AI model selection, saved API sets, migration, logging, and cleanup.&lt;/p&gt;

&lt;p&gt;The extension uses &lt;code&gt;context.secrets&lt;/code&gt; for sensitive values. That includes the Dev.to API key and the supported AI-provider keys. The browser-based webviews receive saved-status information instead of stored key values.&lt;/p&gt;

&lt;p&gt;The status helper in &lt;code&gt;src/security/credentials.ts&lt;/code&gt; returns booleans:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;credentialStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SecretStorage&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;ALL_SECRET_KEYS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UI shows &lt;strong&gt;🔒 Key Saved &amp;amp; Active&lt;/strong&gt;. It does not populate the old key into the field, even as a masked value. &lt;strong&gt;Change saved key&lt;/strong&gt; reveals an empty replacement input, and leaving it blank retains the saved value.&lt;/p&gt;

&lt;p&gt;Newly typed replacements necessarily pass through the input while the user is editing them. The important separation is that stored keys are not sent back from the extension host to fill the webview. Successful save acknowledgements clear replacement fields; closing the AI dialog discards pending replacements.&lt;/p&gt;

&lt;p&gt;Saved AI keys can be reused for model discovery and generation without retyping them. A successful model-list request alone is not treated as proof that a new key was saved, and save failures do not receive a success acknowledgement.&lt;/p&gt;

&lt;p&gt;Saved API configurations follow the same design. The host activates the selected credentials, while the UI gets metadata such as the configuration name and whether credentials are available. Snapshots are created from credentials already held on the host.&lt;/p&gt;

&lt;h3&gt;
  
  
  A saved key is scoped to its editor
&lt;/h3&gt;

&lt;p&gt;VS Code and a separate editor application such as Antigravity have separate application storage. A key saved by DotShare in VS Code is not automatically available in DotShare running inside another editor.&lt;/p&gt;

&lt;p&gt;The same key can be entered and saved in that editor separately. An empty saved-key status there does not, by itself, show that VS Code lost its stored key.&lt;/p&gt;

&lt;p&gt;The extension relies on the host's SecretStorage implementation and its available storage backend. VS Code documents its API in the &lt;a href="https://code.visualstudio.com/api/references/vscode-api#SecretStorage" rel="noopener noreferrer"&gt;SecretStorage reference&lt;/a&gt; and Linux keyring configuration in its &lt;a href="https://code.visualstudio.com/docs/configure/settings-sync#_troubleshooting-keychain-issues" rel="noopener noreferrer"&gt;credential-storage troubleshooting guidance&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Migration and cleanup cover the credential lifecycle
&lt;/h2&gt;

&lt;p&gt;Moving future writes into secure storage is only part of a migration. Older plaintext copies can remain behind.&lt;/p&gt;

&lt;p&gt;The update migrates saved API configurations for every supported platform, including Dev.to. When a newer secure copy already exists, it is preserved and the stale legacy copy is removed. When no secure copy exists, the secure write precedes deletion of the old state.&lt;/p&gt;

&lt;p&gt;Migration also handles the previous Discord webhook storage name and legacy API keys inside saved model-selection state. Model preferences can remain as preferences without retaining the key in ordinary state.&lt;/p&gt;

&lt;p&gt;Local credential clearing covers platform keys, AI keys, GitHub and DotShare account secrets, saved configuration lists, relevant model preferences, and remembered cloud-sync consent. The UI receives cleanup notifications so the displayed state can follow the host.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local cleanup is not cloud revocation.&lt;/strong&gt; Credentials previously uploaded for scheduling must be revoked separately through the cloud service. That distinction is now stated in the user-facing security documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. The CLI stores credentials in the OS credential store
&lt;/h2&gt;

&lt;p&gt;The extension's storage changes also exposed a separate CLI concern: a preferences file should not double as a credential vault.&lt;/p&gt;

&lt;p&gt;The CLI now uses &lt;code&gt;@napi-rs/keyring&lt;/code&gt; through a dedicated credential-store adapter. Its supported Telegram and LinkedIn credentials are stored under the DotShare CLI service in the native OS credential store.&lt;/p&gt;

&lt;p&gt;The JSON configuration file contains preferences such as the server URL and default platforms. It is written through a temporary file and renamed, with a restrictive file mode requested on platforms that honor it. Credentials are read from the credential store when a command needs them.&lt;/p&gt;

&lt;p&gt;For older configurations, the migration writes credentials to the native store before replacing the configuration with metadata. An existing secure value takes precedence over an older file copy. If keyring access fails, migration stops without erasing the legacy file or falling back to a new plaintext credential write.&lt;/p&gt;

&lt;p&gt;The setter in &lt;code&gt;src/cli/credential-store.ts&lt;/code&gt; makes the failure behavior explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;rememberSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DotShare CLI&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Could not save credentials in the OS keyring. No plaintext fallback was used.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CLI logging is separated from VS Code-dependent logging, so command-line diagnostics can use redaction without requiring the editor runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Logs and cloud sync have narrower, clearer behavior
&lt;/h2&gt;

&lt;p&gt;This update removes sensitive logging of complete OAuth callback URLs and credential values from the reviewed paths. A shared redaction layer remembers secrets obtained from or written to SecretStorage and masks known values and common token patterns in diagnostic messages. Snippet sanitization also reduces the chance of common credential formats entering external AI requests.&lt;/p&gt;

&lt;p&gt;Git commands use &lt;code&gt;execFile&lt;/code&gt; with structured argument arrays. That avoids shell interpretation of topic text and path arguments and improves handling of platform-specific quoting. It is a concrete protection for Git subprocess calls, not a general claim that all inputs are safe.&lt;/p&gt;

&lt;p&gt;Cloud scheduling has an explicit boundary as well. Credential synchronization checks saved user consent and requires HTTPS before reading local credentials for upload. Consent text explains that the server receives credentials to run scheduled posts.&lt;/p&gt;

&lt;p&gt;The security documentation no longer presents unverified backend encryption claims as guarantees. Local SecretStorage protects the local workflow; it does not establish how a deployed server stores its copy.&lt;/p&gt;

&lt;p&gt;Redaction and migration also have practical limits. Pattern matching cannot identify every possible secret, historical logs are not automatically rewritten, and removing a local copy does not rotate a token that was previously exposed.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. The saved-key controls now follow the editor theme
&lt;/h2&gt;

&lt;p&gt;The saved-state design should look deliberate, too.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Change saved key&lt;/strong&gt; control now has a dedicated CSS class in both the sidebar and the AI modal. It uses VS Code theme colors, rounded borders, a hover state, and a visible keyboard-focus outline. Hidden controls stay hidden through the CSS rule as well as their UI state.&lt;/p&gt;

&lt;p&gt;That fixes the unstyled native button previously shown beside the saved-key badge and makes credential replacement fit the rest of the extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Build and test changes support the release
&lt;/h2&gt;

&lt;p&gt;The update targets VS Code &lt;code&gt;^1.90.0&lt;/code&gt;, with matching API type definitions. Build, webview type-checking, lint configuration, dependency manifests, and packaging exclusions were adjusted alongside the implementation. Development artifacts and source-only material are excluded from the packaged extension where configured.&lt;/p&gt;

&lt;p&gt;The automated suite was rerun for this article: &lt;strong&gt;157 tests passed across 17 suites&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The coverage includes release boundaries and evidence extraction, generation validation and repair, provider completion signals, preview-link handling, credential status and migration, AI-key behavior, redaction, cloud-consent checks, and CLI configuration migration.&lt;/p&gt;

&lt;p&gt;Those tests exercise deterministic behavior and mocked integrations. Native keyring persistence across an editor restart, live provider responses, Dev.to publishing, and deployed backend behavior remain separate integration checks. The passing suite is evidence for the tested implementation paths, not a production security certification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install or download DotShare
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotshare" rel="noopener noreferrer"&gt;Install from the Visual Studio Marketplace&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://open-vsx.org/extension/freerave/dotshare" rel="noopener noreferrer"&gt;Install from Open VSX&lt;/a&gt; in editors that use that registry.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/FreeRave/vsextensions/dotshare/latest/vspackage" rel="noopener noreferrer"&gt;Download the latest available VSIX from the Marketplace&lt;/a&gt; for manual installation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install the downloaded file, open the Extensions view, select &lt;strong&gt;Install from VSIX…&lt;/strong&gt; from its menu, and choose the package. Check that the installed version is &lt;strong&gt;3.5.2&lt;/strong&gt; to use the behavior described in this article; the latest version available can differ between registries while an update is being published.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try the article workflow on a real release
&lt;/h2&gt;

&lt;p&gt;Start with a project that has useful release notes and a committed version to describe:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save an AI-provider key and choose an available model in DotShare.&lt;/li&gt;
&lt;li&gt;Open the Dev.to Article Publisher and select &lt;strong&gt;DotShare AI Article&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose the release scope and version deliberately.&lt;/li&gt;
&lt;li&gt;Enable the relevant changelog and Git sources, and add an optional topic or editor hint.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Full Article (Dev.to)&lt;/strong&gt;, language, selected links, and whether to include verified code excerpts.&lt;/li&gt;
&lt;li&gt;Generate the draft and inspect any context or validation warnings.&lt;/li&gt;
&lt;li&gt;Review the title, description, tags, links, and body in Live Preview.&lt;/li&gt;
&lt;li&gt;Save a Dev.to draft, make the final editorial edits, and publish when ready.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DotShare 3.5.2 puts the version, the evidence, and the draft in the same workflow. It helps authors spend their review time on the actual explanation: what changed, why it matters, and what the implementation supports.&lt;/p&gt;

&lt;p&gt;The code is available in the &lt;a href="https://github.com/kareem2099/DotShare" rel="noopener noreferrer"&gt;DotShare repository&lt;/a&gt;. Which part of writing release articles costs you the most time: finding the changes, explaining the implementation, or preparing the final post?&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>ai</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>DotGhostBoard 2.1 'Leviathan' — Cryptographic Vault Backups, Secret Expiry &amp; Password History (Part 2)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Tue, 06 Oct 2026 13:20:28 +0000</pubDate>
      <link>https://dev.to/freerave/dotghostboard-21-leviathan-cryptographic-vault-backups-secret-expiry-password-history-part-3pk8</link>
      <guid>https://dev.to/freerave/dotghostboard-21-leviathan-cryptographic-vault-backups-secret-expiry-password-history-part-3pk8</guid>
      <description>&lt;h2&gt;
  
  
  A deep-dive into DotGhostBoard 2.1's security layer: AES-256-GCM .vault backup packages with AAD header authentication, CSPRNG password generation with keyspace entropy, secret expiration tracking, and encrypted version history with safe revert.
&lt;/h2&gt;

&lt;p&gt;Most local password managers have a backup problem: export to unencrypted CSV and you have a plaintext credential dump sitting on your disk. Use proprietary cloud sync and you've handed your secrets to a third party. Neither is acceptable.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;&lt;a href="https://dev.to/freerave/dotghostboard-21-leviathan-smart-clipboard-tagging-contextual-actions-on-linux-part-1-5gb8"&gt;Part 1&lt;/a&gt;&lt;/strong&gt;, we covered the productivity layer of DotGhostBoard 2.1 — smart auto-tagging and contextual clipboard actions running locally in under 1ms for typical payloads (&amp;lt; 5KB).&lt;/p&gt;

&lt;p&gt;This part is about security architecture: what happens when you need to safely move, store, expire, and rotate credentials.&lt;/p&gt;

&lt;p&gt;Here's what we're covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standalone &lt;code&gt;.vault&lt;/code&gt; Encrypted Backup Packages (with AAD header authentication)&lt;/li&gt;
&lt;li&gt;CSPRNG Password &amp;amp; Token Generator with Live Keyspace Entropy&lt;/li&gt;
&lt;li&gt;Secret Expiry Tracking &amp;amp; Dynamic Warning Badges&lt;/li&gt;
&lt;li&gt;Encrypted Password Version History with Safe Revert&lt;/li&gt;
&lt;li&gt;Vault-to-Dashboard Plaintext Sweep &amp;amp; Its Practical Boundaries&lt;/li&gt;
&lt;li&gt;Unified UX Polish &amp;amp; Ergonomics&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Encrypted Vault Backups: The &lt;code&gt;.vault&lt;/code&gt; Package Format
&lt;/h2&gt;

&lt;p&gt;The goal was simple: export your entire Vault as a single portable file that contains &lt;strong&gt;zero unencrypted secret bytes&lt;/strong&gt; — safe to copy to a USB drive, upload to a personal server, or store offsite.&lt;/p&gt;

&lt;p&gt;The result is the &lt;code&gt;.vault&lt;/code&gt; format (&lt;code&gt;core/security/vault/backup.py&lt;/code&gt;), a compact binary package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------+---------------+---------------+---------------+---------------+
| Magic Header  | Version       | Salt          | Nonce         | Payload + Tag |
| "DGBV"        | 0x01          | 16 bytes      | 12 bytes      | Ciphertext +  |
| (4 bytes)     | (1 byte)      | os.urandom    | AES-GCM       | 16B GCM Tag   |
+---------------+---------------+---------------+---------------+---------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Cryptographic Stack
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cipher&lt;/td&gt;
&lt;td&gt;AES-256-GCM (authenticated encryption with AAD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key derivation&lt;/td&gt;
&lt;td&gt;PBKDF2-HMAC-SHA256, 100,000 rounds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Salt&lt;/td&gt;
&lt;td&gt;16-byte random, per-export (&lt;code&gt;os.urandom(16)&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nonce&lt;/td&gt;
&lt;td&gt;12-byte random, per-export (&lt;code&gt;os.urandom(12)&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Associated Data (AAD)&lt;/td&gt;
&lt;td&gt;5-byte header (&lt;code&gt;MAGIC + VERSION&lt;/code&gt;) authenticated into the GCM tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;128-bit GCM tag — tampering with ciphertext, nonce, or header fails cleanly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's the core export logic, lightly abbreviated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/security/vault/backup.py (simplified)
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives.kdf.pbkdf2&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PBKDF2HMAC&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashes&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives.ciphers.aead&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AESGCM&lt;/span&gt;

&lt;span class="n"&gt;MAGIC&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DGBV&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;KDF_ITER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100_000&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;export_vault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;salt&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;header_aad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MAGIC&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;VERSION&lt;/span&gt;

    &lt;span class="c1"&gt;# Derive 256-bit key from passphrase
&lt;/span&gt;    &lt;span class="n"&gt;kdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PBKDF2HMAC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hashes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;KDF_ITER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;derive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;# Serialize payload entirely in-memory — never touches disk
&lt;/span&gt;    &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# AES-256-GCM: encrypt payload and authenticate format header via AAD
&lt;/span&gt;    &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AESGCM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header_aad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Return complete package (16-byte GCM tag is appended to ciphertext by AESGCM)
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;header_aad&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And importing reverses the process — with AEAD integrity verification happening &lt;em&gt;before&lt;/em&gt; any payload parsing or database operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;import_vault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAGIC&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not a valid .vault file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unsupported .vault backup version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;header_aad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="n"&gt;kdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PBKDF2HMAC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hashes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;KDF_ITER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;derive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;# Decrypt and authenticate: raises InvalidTag if ciphertext, passphrase,
&lt;/span&gt;    &lt;span class="c1"&gt;# or header bytes (MAGIC/VERSION) were tampered with
&lt;/span&gt;    &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AESGCM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header_aad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Associated Authenticated Data (AAD)?
&lt;/h3&gt;

&lt;p&gt;Passing &lt;code&gt;MAGIC + VERSION&lt;/code&gt; as AAD cryptographically binds the cleartext header to the payload's 128-bit authentication tag. Without AAD, an attacker could flip the version byte undetected by the cipher until application-level parsing. With AAD, modifying even a single bit in the header or ciphertext triggers an immediate &lt;code&gt;InvalidTag&lt;/code&gt; rejection by the cipher.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Gets Exported
&lt;/h3&gt;

&lt;p&gt;Everything: active secrets, categories, creation/update timestamps, expiration dates, and the last 3 encrypted version history entries. Full Vault state in one file.&lt;/p&gt;

&lt;p&gt;Built-in duplicate skipping (&lt;code&gt;overwrite_existing=False&lt;/code&gt;) on import means re-importing an old backup won't create duplicates in your live Vault.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;On PBKDF2 iteration count:&lt;/strong&gt; 100,000 rounds is a responsive baseline across diverse Linux hardware, including low-power ARM boards. Argon2id support and user-configurable iteration scaling are on the v2.2 roadmap.&lt;/p&gt;
&lt;/blockquote&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%2Fl55vaetpohpdzyfb3my6.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%2Fl55vaetpohpdzyfb3my6.png" alt="DotGhostBoard 2.1 Encrypted Vault Backup Dialog" width="799" height="401"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: Standalone .vault backup export dialog showing PBKDF2 passphrase derivation, AES-256-GCM encryption parameters, and live Vault drawer state.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  2. CSPRNG Password &amp;amp; Token Generator
&lt;/h2&gt;

&lt;p&gt;Generating credentials inside a clipboard manager means you stay in one tool. No tab-switching to a web generator, no pasting between windows.&lt;/p&gt;

&lt;p&gt;The generator is embedded directly inside the Add/Edit Secret dialog (&lt;code&gt;ui/vault/secret_dialog.py&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ⚡ Generate Password / Token ]
├── CSPRNG Source: Python secrets module (/dev/urandom)
├── Character Pools: [✓] a-z  [✓] A-Z  [✓] 0-9  [✓] Symbols
├── Length Slider: 8 ──────────●─────── 64  (default: 20)
├── Token Presets: Hex | UUIDv4 | Base64 | Bearer | URL-Safe
└── Entropy Meter: [████████████████████] 131.1 bits — Fort Knox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Entropy Calculation
&lt;/h3&gt;

&lt;p&gt;Instead of an arbitrary "password strength checklist," we display &lt;strong&gt;theoretical keyspace entropy&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H = L × log₂(N)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;L&lt;/code&gt; = character length&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;N&lt;/code&gt; = active pool size (e.g., a-z + A-Z + 0-9 + symbols = 94 characters)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ui/vault/secret_dialog.py (simplified)
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;keyspace_entropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Theoretical bits of entropy for a uniformly random credential.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pool_size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;entropy_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Weak&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Moderate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Strong&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Fort Knox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The meter updates live as you drag the slider or toggle character pools. A 20-character password using the full 94-character pool yields &lt;strong&gt;131.1 bits&lt;/strong&gt; of keyspace entropy (20 × log₂(94)) — comfortably above the 80–128-bit range generally considered strong for random credentials.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Keyspace entropy across the stack:&lt;/strong&gt; Both the auto-tagger in Part 1 and the generator here use the same keyspace entropy formula (H = L × log₂(N)). The difference is in application: the auto-tagger &lt;em&gt;estimates&lt;/em&gt; the character pool of existing clipboard text to detect high-entropy tokens, while the generator &lt;em&gt;computes&lt;/em&gt; the exact strength of newly generated passwords from user-selected pools.&lt;/p&gt;
&lt;/blockquote&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%2Fgfxt41u34xsh6bvwvtsj.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%2Fgfxt41u34xsh6bvwvtsj.png" alt="DotGhostBoard 2.1 Cryptographic Password Generator &amp;amp; Live Entropy Meter" width="503" height="695"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2: Built-in CSPRNG Password &amp;amp; Token Generator showing character pool toggles, 20-character length slider, and live keyspace entropy evaluation (Strong ~131 bits).&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Secret Expiry Tracking &amp;amp; Dynamic Badges
&lt;/h2&gt;

&lt;p&gt;Temporary credentials — staging tokens, contractor access keys, short-lived API secrets — have an expiration date. Most password managers ignore this.&lt;/p&gt;

&lt;p&gt;DotGhostBoard 2.1 tracks expiry directly in the Vault model (&lt;code&gt;core/security/vault/models.py&lt;/code&gt;) and surfaces it visually on each secret card (&lt;code&gt;ui/vault/secret_card.py&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting an Expiry Date
&lt;/h3&gt;

&lt;p&gt;In the Add/Edit dialog, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick a &lt;strong&gt;preset duration&lt;/strong&gt;: 30 days, 90 days, 180 days, 1 year.&lt;/li&gt;
&lt;li&gt;Or pick an &lt;strong&gt;exact date&lt;/strong&gt; via a &lt;code&gt;QDateEdit&lt;/code&gt; calendar picker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The date is stored as an ISO 8601 timestamp string in SQLite. The expiry logic lives in a shared mixin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/security/vault/models.py
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_ExpiryMixin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;expires_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_expired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expires_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expires_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Corrupted timestamp: treated as non-expiring rather than raising in the UI
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;days_remaining&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expires_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expires_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VaultItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_ExpiryMixin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VaultSummary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_ExpiryMixin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;VaultItem&lt;/code&gt; (full DB record) and &lt;code&gt;VaultSummary&lt;/code&gt; (UI listing) inherit the same expiry logic through the mixin — written once, tested once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Status Badges
&lt;/h3&gt;

&lt;p&gt;The secret card renders the appropriate badge at render time:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Badge&lt;/th&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Appearance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;⛔ EXPIRED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;is_expired == True&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Red badge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;⚠️ 0d–7d left&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;days_remaining &amp;lt;= 7&lt;/code&gt; (e.g., &lt;code&gt;⚠️ 3d left&lt;/code&gt;, or &lt;code&gt;⚠️ 0d left&lt;/code&gt; when less than 24 hours remain)&lt;/td&gt;
&lt;td&gt;Amber badge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;⏳ 2027-03-01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Active, &amp;gt; 7 days remaining&lt;/td&gt;
&lt;td&gt;Blue pill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;(none)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;No expiry set&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2Fzjkxkbbwfx97vo7gvikd.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%2Fzjkxkbbwfx97vo7gvikd.png" alt="DotGhostBoard 2.1 Secret Expiry Status Badges" width="395" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3: Secret cards displaying dynamic status badges including expired credentials and upcoming renewal countdowns.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Encrypted Password Version History &amp;amp; Safe Revert
&lt;/h2&gt;

&lt;p&gt;Rotating a production credential is risky. If the new key fails, you need the old one — immediately. DotGhostBoard 2.1 solves this with &lt;strong&gt;Encrypted Version History&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;Every time you update an existing secret, the current ciphertext is archived before the new one is written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/security/vault/service.py (simplified)
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save_history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_require_unlocked&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;save_history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# 1. Fetch current encrypted record before replacing
&lt;/span&gt;        &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# 2. Archive previous ciphertext to history (capped at 3 newest)
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_history_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_entries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Encrypt and store the new secret version
&lt;/span&gt;    &lt;span class="n"&gt;new_ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;new_ciphertext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Max 3 versions&lt;/strong&gt; — capped in SQLite, avoiding unbounded storage growth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted at rest&lt;/strong&gt; — history entries use the same DEK as the live secret. Plaintext never hits disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decrypted in memory only&lt;/strong&gt; — when you open the History Viewer, decryption happens in RAM and is discarded on close.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The History Viewer (📜) &amp;amp; Safe Revert
&lt;/h3&gt;

&lt;p&gt;Clicking the &lt;code&gt;📜&lt;/code&gt; icon on any secret card opens the modal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version index and creation timestamp for each entry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;👁️ Reveal&lt;/code&gt; / &lt;code&gt;🙈 Hide&lt;/code&gt; toggle with monospace masking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy&lt;/strong&gt; button — protected by DotGhostBoard's 30-second automatic clipboard scrub.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;↺ Revert to this&lt;/strong&gt; — restores the selected version as the active secret.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Behind the scenes, revert calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save_history&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This neatly preserves the active secret you just replaced into history, allowing you to toggle back and forth safely without data loss. When a secret is deleted, SQLite cascades and purges all historical entries in the same transaction.&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%2Fph2t177u2a1giemvqig2.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%2Fph2t177u2a1giemvqig2.png" alt="DotGhostBoard 2.1 Encrypted Password Version History &amp;amp; Safe Revert" width="559" height="661"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4: Password version history modal showing archived credential states, reveal toggle, and one-click atomic revert.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  5. Vault-to-Dashboard Plaintext Sweep
&lt;/h2&gt;

&lt;p&gt;Here's a subtle security gap:&lt;/p&gt;

&lt;p&gt;You add a secret to the Vault. But before you did, you copied it to your clipboard — meaning an unencrypted copy was recorded in your general clipboard history.&lt;/p&gt;

&lt;p&gt;Later, you delete the secret from the Vault. If the clipboard history remains untouched, your secret is gone from the encrypted vault but still sitting in plaintext in the general history database.&lt;/p&gt;

&lt;p&gt;DotGhostBoard 2.1 closes this gap with a &lt;strong&gt;Coordinated Plaintext Sweep&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ui/vault/vault_controller.py (simplified)
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Temporarily decrypt secret in-memory to discover history traces
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reveal_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Delete from encrypted Vault database
&lt;/span&gt;    &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. If deleted, sweep matching plaintext entries from clipboard history
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;history_matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_history_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history_matches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_history_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history_item_removed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# removes card from UI
&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;secrets_changed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;history_item_removed&lt;/code&gt; signal coordinates the UI: the Vault controller emits it, and the HistoryController receives it to cleanly remove the card from the UI. No tight coupling, no shared database transactions — just Qt signals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Boundary: Exact Match vs. Substrings
&lt;/h3&gt;

&lt;p&gt;The sweep performs an exact match (&lt;code&gt;find_by_content(plaintext)&lt;/code&gt;). If you copied the credential with trailing whitespace, a trailing newline, or embedded inside a larger terminal command line (e.g. &lt;code&gt;curl -H "Authorization: Bearer &amp;lt;key&amp;gt;"&lt;/code&gt;), the exact sweep will not catch the enclosing entry.&lt;/p&gt;

&lt;p&gt;We deliberately chose this conservative exact match: running broad substring searches across the entire clipboard history could easily result in destructive false-positive deletions of unrelated notes or commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Unified Design System &amp;amp; UX Polish
&lt;/h2&gt;

&lt;p&gt;Security tools only work if developers actually use them. Friction kills adoption. In 2.1, we focused on tightening common interactions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Component Unification (&lt;code&gt;PasswordInputWidget&lt;/code&gt;):&lt;/strong&gt; We extracted password input handling and the visibility toggle into a single reusable widget. Both the session &lt;code&gt;LockScreen&lt;/code&gt; and the &lt;code&gt;VaultUnlockDialog&lt;/code&gt; now share identical keyboard behavior, input styling, and state management rather than maintaining divergent Qt implementations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drawer Ergonomics:&lt;/strong&gt; The slide-out Vault drawer (&lt;code&gt;ui/vault/vault_panel.py&lt;/code&gt;) was restructured into a clear two-row toolbar (title/status row + action controls row) with an expanded 380px width for better readability. First-time users see an empty-state onboarding card outlining shortcuts and clipboard auto-scrub policies rather than a blank panel.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fysuuvwbuew71rimd2yod.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%2Fysuuvwbuew71rimd2yod.png" alt="DotGhostBoard 2.1 Vault Drawer &amp;amp; Action Toolbar" width="380" height="1008"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 5: Expanded 380px Vault drawer featuring a two-row action toolbar and structured onboarding empty-state.&lt;/em&gt;&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%2Fgibhaox0g71dmc63kj8t.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%2Fgibhaox0g71dmc63kj8t.png" alt="DotGhostBoard 2.1 Unified PasswordInputWidget" width="519" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 6: Unified PasswordInputWidget on the Session Lock screen with integrated eye toggle and focus handling.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing &amp;amp; Code Quality
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;523 automated tests. 100% passing.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;======================== 523 passed in ~100s ========================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test matrix covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cryptographic roundtrips with AAD tampering verification&lt;/li&gt;
&lt;li&gt;SQLite transaction isolation for version history and cascade deletes&lt;/li&gt;
&lt;li&gt;UI event loops via headless Xvfb (tested against both Openbox and Qtile 0.36.0)&lt;/li&gt;
&lt;li&gt;Expiry logic edge cases (timezone-aware vs. naive datetimes, malformed strings)&lt;/li&gt;
&lt;li&gt;Plaintext sweep signal propagation across the Vault ↔ Dashboard boundary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zero Flake8 errors. &lt;code&gt;ui/dashboard.py&lt;/code&gt; enforces a hard &lt;code&gt;&amp;lt;= 500 LOC&lt;/code&gt; limit — all specialized logic delegates to controllers and mixins.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next &amp;amp; Known Limitations
&lt;/h2&gt;

&lt;p&gt;A few honest limitations, on the record:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wayland compatibility:&lt;/strong&gt; DotGhostBoard relies on X11/EWMH for clipboard capture and hotkeys. We're investigating &lt;code&gt;wlr-data-control&lt;/code&gt; protocol support for Wayland. No ETA yet, but it's our most-requested architecture evolution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KDF hardening:&lt;/strong&gt; 100,000 PBKDF2 rounds is our current baseline. User-configurable iteration counts (targeting OWASP's 600,000 recommendation) and Argon2id evaluation are on the v2.2 roadmap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backup format version negotiation:&lt;/strong&gt; v2.1 introduces the single-byte version header; upcoming releases will support forward-compatible schema migrations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Substring Plaintext Sweeps:&lt;/strong&gt; Exploring optional flagged heuristics for wiping shell history snippets containing expired tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI Vault queries:&lt;/strong&gt; Scriptable, authenticated &lt;code&gt;dotghost vault list&lt;/code&gt; and &lt;code&gt;dotghost vault get &amp;lt;title&amp;gt;&lt;/code&gt; commands are planned for v2.2.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Try DotGhostBoard 2.1
&lt;/h2&gt;

&lt;p&gt;100% free and open-source — &lt;strong&gt;Apache-2.0 License.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;kareem2099/DotGhostBoard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenDesktop / KDE Store:&lt;/strong&gt; &lt;a href="https://www.opendesktop.org/p/2353623/" rel="noopener noreferrer"&gt;DotGhostBoard on OpenDesktop&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kareem2099/DotGhostBoard.git
&lt;span class="nb"&gt;cd &lt;/span&gt;DotGhostBoard

python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

python3 main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keyboard Shortcuts
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Alt+V&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Summon / hide Dashboard (migrates to active workspace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Alt+Space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Floating Spotlight Quick Search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Shift+V&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open / close The Vault encrypted drawer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+F&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Focus search bar inside Dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Questions about the vault format, the key derivation choices, or the history revert logic? Drop them below — happy to go deeper on any of it. 👻🔒&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>python</category>
      <category>security</category>
    </item>
    <item>
      <title>DotGhostBoard 2.1 'Leviathan' — Smart Clipboard Tagging &amp; Contextual Actions on Linux (Part 1)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Fri, 02 Oct 2026 20:59:46 +0000</pubDate>
      <link>https://dev.to/freerave/dotghostboard-21-leviathan-smart-clipboard-tagging-contextual-actions-on-linux-part-1-5gb8</link>
      <guid>https://dev.to/freerave/dotghostboard-21-leviathan-smart-clipboard-tagging-contextual-actions-on-linux-part-1-5gb8</guid>
      <description>&lt;h2&gt;
  
  
  How we built a rules-based clipboard intelligence engine for Linux — local, deterministic, sub-millisecond for typical payloads (&amp;lt; 5KB), zero AI, zero telemetry. Auto-tagging, contextual smart actions, and a tight pipeline architecture explained.
&lt;/h2&gt;

&lt;p&gt;You copy a minified JSON blob from a terminal log. To actually read it, you paste it into an editor, run a formatter, then copy the result back. You copy an API key from a config file and your clipboard manager stores it as plain text, alongside screenshots and grocery lists, until you manually hunt it down and secure it.&lt;/p&gt;

&lt;p&gt;Most clipboard tools treat every copied item the same: inert text in a database. For anyone who spends time in terminals, editors, and browser devtools, that uniformity creates constant small frictions that accumulate fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DotGhostBoard 2.1 "Leviathan"&lt;/strong&gt; takes a different approach. The clipboard understands what it's holding and surfaces the right action immediately — format this JSON, open that URL, secure this credential.&lt;/p&gt;

&lt;p&gt;This is a two-part series on how we built it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1 (you're here):&lt;/strong&gt; Rules-based Smart Auto-Tagging, Contextual Smart Actions, and the pipeline behind them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/freerave/dotghostboard-21-leviathan-cryptographic-vault-backups-secret-expiry-password-history-part-3pk8"&gt;Part 2&lt;/a&gt;:&lt;/strong&gt; Cryptographic &lt;code&gt;.vault&lt;/code&gt; Backups, CSPRNG Password Generator, Secret Expiry, and Encrypted Version History.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Design Constraint: Local, Deterministic, Fast
&lt;/h2&gt;

&lt;p&gt;The obvious shortcut for text classification is an LLM or a cloud API. For a clipboard manager, that's a non-starter on three counts.&lt;/p&gt;

&lt;p&gt;Your clipboard routinely holds API keys, internal paths, private tokens, and proprietary code snippets. Sending that to any remote service — even a local on-device model — introduces a trust boundary that shouldn't exist in a tool people actually rely on for security. Beyond that, loading inference libraries adds hundreds of MB of idle RAM, and any latency between &lt;code&gt;Ctrl+C&lt;/code&gt; and the item appearing in history is enough to make the tool feel broken.&lt;/p&gt;

&lt;p&gt;Our constraint was concrete: &lt;strong&gt;every classification must run locally, produce deterministic results, and complete in under 1ms for typical clipboard payloads (&amp;lt; 5KB), scaling to ~1.4ms worst-case at the 8KB classification cap.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The approach: pre-compiled regular expressions, structural heuristics, and a pool-based keyspace entropy estimate — no opaque models.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Auto-Tagger: How Classification Actually Works
&lt;/h2&gt;

&lt;p&gt;The engine lives in &lt;code&gt;core/security/auto_tagger.py&lt;/code&gt;. It runs synchronously on every new clipboard item before storage and UI rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Captured Text ──► Pre-compiled Patterns &amp;amp; Heuristics ──► Tags ──► Storage &amp;amp; UI
                  ├── URL regex                       ──► #link
                  ├── JSON fast-path + json.loads     ──► #json
                  ├── Code keywords + bracket density ──► #code
                  ├── Known prefixes + entropy gate   ──► #secret
                  ├── IPv4 regex + IPv6 regex         ──► #ip
                  ├── RFC-like email regex            ──► #email
                  ├── Unix / Windows path regex       ──► #path
                  └── Hex length check {32,64}        ──► #hash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All patterns compile once at module load time. The function is pure — no I/O, no Qt, no database access — which makes it fast to call and trivial to test.&lt;/p&gt;

&lt;p&gt;Here's the real implementation, abbreviated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/security/auto_tagger.py
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;

&lt;span class="c1"&gt;# ── Compiled patterns (module-level — compiled once, reused forever) ──────────
&lt;/span&gt;
&lt;span class="n"&gt;_RE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https?://[^\s\"&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;gt;]{3,}|ftp://[^\s\"&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;gt;]{3,}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IGNORECASE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;_RE_EMAIL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;_RE_IPV4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;                             &lt;span class="c1"&gt;# validates 0-255 per octet
&lt;/span&gt;    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;_RE_IPV6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(?:[0-9a-fA-F]{1,4}:){2,7}[0-9a-fA-F]{1,4}\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Pragmatic range matching MD5 (32), SHA-1 (40), SHA-256 (64); strict lengths planned for v2.2
&lt;/span&gt;&lt;span class="n"&gt;_RE_HEX_HASH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b[0-9a-fA-F]{32,64}\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Known credential prefixes — the first line of secret detection
&lt;/span&gt;&lt;span class="n"&gt;_RE_SECRET_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ghp_[A-Za-z0-9]{36,}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;                          &lt;span class="c1"&gt;# GitHub PAT
&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AKIA[0-9A-Z]{16}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;                               &lt;span class="c1"&gt;# AWS Access Key
&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sk-[A-Za-z0-9]{32,}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;                           &lt;span class="c1"&gt;# OpenAI / Stripe
&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xox[baprs]-[A-Za-z0-9\-]{10,}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;                 &lt;span class="c1"&gt;# Slack tokens
&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eyJ[A-Za-z0-9\-_]{10,}\.[A-Za-z0-9\-_]{10,}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;# JWT
&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# (Note: _RE_PATH, _CODE_KEYWORDS, and _CODE_BRACKETS are omitted here for brevity)
&lt;/span&gt;
&lt;span class="c1"&gt;# ── Pool-based keyspace entropy estimate ──────────────────────────────────────
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_entropy_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Estimate theoretical keyspace entropy: H = len * log₂(pool_size).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_lowercase&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_uppercase&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;digits&lt;/span&gt;           &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="c1"&gt;# Any non-alphanumeric character (symbols, punctuation, or non-ASCII) adds 32
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_letters&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;digits&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# ── Main classification function ──────────────────────────────────────────────
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;detect_tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_RE_URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#link&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_RE_EMAIL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_RE_IPV4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;_RE_IPV6&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#ip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_RE_PATH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#link&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_RE_HEX_HASH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;                       &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#hash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Secret detection: known prefix first, entropy gate as fallback
&lt;/span&gt;    &lt;span class="n"&gt;is_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_RE_SECRET_PATTERNS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_secret&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;_entropy_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;is_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#secret&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# JSON: only attempt parse if it looks like an object or array
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lstrip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="c1"&gt;# Code: multi-line with language keywords or dense bracket patterns
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_CODE_KEYWORDS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;_CODE_BRACKETS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromkeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# deduplicate, preserve order
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Secret Detection: Two Layers
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;#secret&lt;/code&gt; classifier uses a two-step approach:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1 — Known prefixes.&lt;/strong&gt; Patterns like &lt;code&gt;ghp_&lt;/code&gt;, &lt;code&gt;AKIA&lt;/code&gt;, &lt;code&gt;eyJ&lt;/code&gt; (JWT header) are unambiguous. Match any of them and the tag is assigned immediately, no entropy calculation needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2 — Entropy gate.&lt;/strong&gt; For everything else: single-line, no spaces, at least 16 characters, and a pool-based keyspace entropy ≥ 90 bits. The 90-bit threshold was tuned empirically to catch random high-entropy tokens, API keys, and strong bearer credentials while skipping short identifiers, dictionary words, and common camelCase variable names.&lt;/p&gt;

&lt;p&gt;Both conditions guard against a common pitfall: pure Shannon entropy on raw text produces too many false positives on long sentences or dense code snippets. The entropy function here is &lt;code&gt;H = len × log₂(pool_size)&lt;/code&gt; — a measure of the &lt;em&gt;theoretical keyspace&lt;/em&gt;, not character frequency distribution.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note on non-ASCII characters:&lt;/strong&gt; Because &lt;code&gt;any(c not in string.ascii_letters + string.digits ...)&lt;/code&gt; catches non-ASCII characters (e.g. Arabic script, accented letters, emoji), unicode text will trigger the &lt;code&gt;+32&lt;/code&gt; symbols branch. This heuristic is tuned primarily for ASCII credentials; multilingual script entropy is handled gracefully without throwing exceptions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Known Limitations
&lt;/h3&gt;

&lt;p&gt;Honest engineering requires talking about edge cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Long Paths tagged as &lt;code&gt;#secret&lt;/code&gt;:&lt;/strong&gt; A Unix path like &lt;code&gt;/home/kareem/StudioProjects/DotGhostBoard/main.py&lt;/code&gt; currently receives both &lt;code&gt;#path&lt;/code&gt; and &lt;code&gt;#secret&lt;/code&gt; — it satisfies the entropy gate because it has no spaces and mixes uppercase, lowercase, digits, and &lt;code&gt;/&lt;/code&gt;. We've logged this as a known limitation; v2.2 will add &lt;code&gt;#path&lt;/code&gt; as an explicit exclusion condition for the entropy fallback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hashes flagged as &lt;code&gt;#secret&lt;/code&gt;:&lt;/strong&gt; A 32-character hex string (like an MD5 digest) uses digits + lowercase (&lt;code&gt;pool = 36&lt;/code&gt;), yielding &lt;code&gt;32 × log₂(36) ≈ 165 bits&lt;/code&gt;, which clears the ≥ 90-bit gate. Consequently, MD5 and SHA digests receive both &lt;code&gt;#hash&lt;/code&gt; and &lt;code&gt;#secret&lt;/code&gt;; a dedicated check to prioritize &lt;code&gt;#hash&lt;/code&gt; alone is slated for v2.2.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  2. What the Tag Enables: Contextual Smart Actions
&lt;/h2&gt;

&lt;p&gt;Tags are displayed as colored pill chips on each card. More importantly, they drive &lt;strong&gt;Contextual Smart Actions&lt;/strong&gt; — buttons that appear dynamically in the card toolbar based on what was detected.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#link&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🔗 Open Link&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;QDesktopServices.openUrl()&lt;/code&gt; — no copy-paste to browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;{ }&lt;/code&gt; Format JSON&lt;/td&gt;
&lt;td&gt;Parses, re-serializes with 2-space indent, writes back to clipboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✉ Compose&lt;/td&gt;
&lt;td&gt;Constructs a &lt;code&gt;mailto:&lt;/code&gt; URI, hands off to default mail client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#ip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;📡 Copy IP&lt;/td&gt;
&lt;td&gt;Extracts just the IP from surrounding log noise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#secret&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🛡 → Vault&lt;/td&gt;
&lt;td&gt;Opens Vault drawer, prefills secret dialog, purges plaintext from history&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's the JSON formatter — the action developers use most:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ui/widgets/item_card.py (simplified)
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_on_format_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_raw_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;formatted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_flash_badge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✓ Formatted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_flash_badge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✗ Invalid JSON&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One button. Minified JSON in, readable JSON back in your clipboard. No editor, no extra window.&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%2Facfb25eq5b5pldkhxpkp.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%2Facfb25eq5b5pldkhxpkp.png" alt="DotGhostBoard 2.1 Smart Auto-Tagging &amp;amp; Contextual Actions Live UI" width="800" height="216"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: Auto-detected tags (&lt;code&gt;#link&lt;/code&gt;, &lt;code&gt;#ip&lt;/code&gt;, &lt;code&gt;#code&lt;/code&gt;) and dynamic contextual smart actions (&lt;code&gt;🔗 Open Link&lt;/code&gt;, &lt;code&gt;📡 Copy IP&lt;/code&gt;) on clipboard cards.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Pipeline Architecture
&lt;/h2&gt;

&lt;p&gt;The classifier only stays fast because it runs inside a well-isolated pipeline:&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%2Fb7mwvntrvq6rrmbusbb2.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%2Fb7mwvntrvq6rrmbusbb2.png" alt="DotGhostBoard 2.1 Ingestion &amp;amp; Classification Pipeline" width="800" height="382"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2: The 4-phase sequential classification and dispatch pipeline.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[System Clipboard] ──► ClipboardWatcher (background polling / events)
                             │
                             ▼
                    ClipboardPipeline (pure policy layer)
                      ├── App filter      (skip blacklisted sources)
                      ├── Self-paste guard (skip our own copy events)
                      ├── AutoTagger      (sync, pure, no I/O)
                      └── Duplicate &amp;amp; pin policy
                             │
                             ▼
                    HistoryService ──► SQLite (PRAGMA secure_delete)
                             │
                             ▼
                    HistoryController ──► CardsView (lazy render)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AutoTagger&lt;/code&gt; has zero dependencies on Qt, SQLite, or any network code. That isolation means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The UI thread is never blocked by classification.&lt;/li&gt;
&lt;li&gt;Unit tests need no display server or mocked widgets.&lt;/li&gt;
&lt;li&gt;You can swap, extend, or replace tagging rules without touching controllers or storage.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Measured Latency
&lt;/h2&gt;

&lt;p&gt;We wanted hard performance guarantees rather than assumptions. Here are &lt;code&gt;timeit&lt;/code&gt; measurements on typical clipboard payloads running on an &lt;strong&gt;Intel Core i5-8350U @ 1.70GHz (Python 3.14.7, Linux x86_64)&lt;/strong&gt;, 1,000 iterations each:&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%2Fxa88jjpqkrr6fvqc6da0.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%2Fxa88jjpqkrr6fvqc6da0.png" alt="DotGhostBoard 2.1 Classification Latency Benchmarks" width="800" height="382"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3: Microsecond-level classification benchmark measurements across typical clipboard payloads.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payload                      min µs    median µs    max µs
──────────────────────────────────────────────────────────
URL                             8.2          8.8      10.7
GitHub PAT                      6.5          6.8      10.1
IPv4 address                    7.1          7.5      12.7
MD5 hash                        7.1          7.2       7.6
JSON (small, ~80 chars)        14.1         14.4      16.1
Code snippet                   20.3         20.4      21.4
Plain English text             14.8         15.2      15.3
JSON (1KB payload)             80.3         81.8      82.6
Worst-case dense (7.8KB)     1380.0       1410.6    1460.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "&amp;lt; 1ms" guarantee holds for typical clipboard payloads (&amp;lt; 5KB), with small items (URLs, hashes, JSON) processing in 8–82 µs. At the 8KB cap, worst-case dense tokens (7.8KB of unspaced text forcing character-by-character entropy evaluation) measure ~1.4ms. Payloads exceeding 8KB automatically bypass the entropy gate to ensure the UI loop never hitches on huge paste events.&lt;/p&gt;




&lt;h2&gt;
  
  
  Coming Up in Part 2
&lt;/h2&gt;

&lt;p&gt;The productivity layer is half the story. The other half is what happens to sensitive data after it's detected.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;&lt;a href="https://dev.to/freerave/dotghostboard-21-leviathan-cryptographic-vault-backups-secret-expiry-password-history-part-3pk8"&gt;Part 2&lt;/a&gt;&lt;/strong&gt;, we cover the security architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔐 &lt;strong&gt;Standalone &lt;code&gt;.vault&lt;/code&gt; encrypted backups&lt;/strong&gt; — AES-256-GCM packages with AAD header authentication, zero plaintext on disk, PBKDF2 key derivation.&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;CSPRNG Password &amp;amp; Token Generator&lt;/strong&gt; — Live keyspace entropy meter calibrated to 131.1 bits.&lt;/li&gt;
&lt;li&gt;⏳ &lt;strong&gt;Secret Expiry Tracking&lt;/strong&gt; — Calendar-based expiry with &lt;code&gt;⛔ EXPIRED&lt;/code&gt; and &lt;code&gt;⚠️ 3d left&lt;/code&gt; badges.&lt;/li&gt;
&lt;li&gt;📜 &lt;strong&gt;Encrypted Version History&lt;/strong&gt; — Last 3 versions retained, one-click atomic revert.&lt;/li&gt;
&lt;li&gt;🧹 &lt;strong&gt;Coordinated Plaintext Sweep&lt;/strong&gt; — Purging matching unencrypted history records upon Vault deletion.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Try DotGhostBoard 2.1
&lt;/h2&gt;

&lt;p&gt;100% free and open-source — &lt;strong&gt;Apache-2.0 License.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;kareem2099/DotGhostBoard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenDesktop / KDE Store:&lt;/strong&gt; &lt;a href="https://www.opendesktop.org/p/2353623/" rel="noopener noreferrer"&gt;DotGhostBoard on OpenDesktop&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kareem2099/DotGhostBoard.git
&lt;span class="nb"&gt;cd &lt;/span&gt;DotGhostBoard

python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

python3 main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keyboard Shortcuts
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Alt+V&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Summon / hide Dashboard (migrates to active workspace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Alt+Space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Floating Spotlight Quick Search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+Shift+V&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open / close The Vault encrypted drawer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Questions about the classification heuristics, the entropy threshold choice, or the action pipeline? Drop them in the comments. 👻&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Building an Automated, API-Driven Stats &amp; Version Synchronizer for VS Code Extensions with 24-Hour Smart Caching (dotUniverse v1.2.0)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Mon, 28 Sep 2026 14:01:29 +0000</pubDate>
      <link>https://dev.to/freerave/building-an-automated-api-driven-stats-version-synchronizer-for-vs-code-extensions-with-24-hour-4inm</link>
      <guid>https://dev.to/freerave/building-an-automated-api-driven-stats-version-synchronizer-for-vs-code-extensions-with-24-hour-4inm</guid>
      <description>&lt;h2&gt;
  
  
  How I built a dual-path synchronization architecture for 7 VS Code extensions using VS Marketplace &amp;amp; Open VSX APIs, 24-hour client caching, and daily zero-dependency GitHub Actions.
&lt;/h2&gt;

&lt;p&gt;As an open-source creator building a growing ecosystem of developer tools, one repetitive chore kept draining my time: &lt;strong&gt;keeping metrics and version numbers in sync&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My portfolio, &lt;a href="https://universe.dotsuite.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;dotUniverse&lt;/strong&gt;&lt;/a&gt;, showcases 20+ open-source tools—including 7 VS Code extensions published across both the &lt;strong&gt;Visual Studio Marketplace&lt;/strong&gt; and the &lt;strong&gt;Eclipse Open VSX Registry&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every time I bumped a release or checked how many developers installed &lt;a href="https://github.com/kareem2099/codetune" rel="noopener noreferrer"&gt;CodeTune&lt;/a&gt;, &lt;a href="https://github.com/kareem2099/dotcommand" rel="noopener noreferrer"&gt;dotcommand&lt;/a&gt;, or &lt;a href="https://github.com/kareem2099/DotShare" rel="noopener noreferrer"&gt;DotShare&lt;/a&gt;, I had to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into multiple web dashboards.&lt;/li&gt;
&lt;li&gt;Manually calculate cross-platform sums.&lt;/li&gt;
&lt;li&gt;Edit HTML cards, version badges, and repository README tables by hand.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Manual upkeep is tedious, error-prone, and quickly falls behind. I wanted an &lt;strong&gt;automated, dual-path synchronization architecture&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At Runtime:&lt;/strong&gt; Visitors see fresh, API-backed numbers and versions fetched directly from store APIs, cached intelligently on the client for 24 hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At Build/Repository Time:&lt;/strong&gt; Static fallbacks in &lt;code&gt;index.html&lt;/code&gt; and markdown tables in &lt;code&gt;README.md&lt;/code&gt; are automatically kept fresh via a scheduled, zero-dependency GitHub Action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a deep dive into how I built this system using pure modern JavaScript, 24-hour client-side caching, and GitHub Actions CI/CD.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏛️ The Architecture: Dual-Path Synchronization
&lt;/h2&gt;

&lt;p&gt;Instead of treating this as a simple "fetch data in JavaScript" problem, I designed a &lt;strong&gt;dual-path synchronization pipeline&lt;/strong&gt; sharing a single source of truth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  ┌──────────────────────────────┐
                  │ Visual Studio Marketplace    │
                  │   &amp;amp; Open VSX Registry APIs   │
                  └──────────────┬───────────────┘
                                 │
             ┌───────────────────┴───────────────────┐
             │                                       │
      [Runtime Path]                           [Build/CI Path]
             │                                       │
             ▼                                       ▼
  extension-stats.js                     sync-extension-stats.mjs
             │                                       │
      ┌──────┴──────┐                         ┌──────┴──────┐
      ▼             ▼                         ▼             ▼
  24h Cache     Fresh DOM                 index.html    README.md
 (localStorage) (No Flicker)              (Fallback)    (Markdown)
                                                     │
                                                     ▼
                                              Git Commit &amp;amp; Push
                                              (Only on Changes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This decoupled design guarantees that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First-time and repeat visitors&lt;/strong&gt; get an instant render from static markup or &lt;code&gt;localStorage&lt;/code&gt; without waiting for API responses to render the initial content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search engine crawlers&lt;/strong&gt; and developers browsing the GitHub repository see accurate static numbers even without executing client-side JavaScript.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🏗️ The Challenge: Two Stores, Fragmented Metrics
&lt;/h2&gt;

&lt;p&gt;Tracking extensions across the VS Code ecosystem is fragmented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code Marketplace&lt;/strong&gt;: Owned by Microsoft. Its web interface displays a single "Installs" counter, but its underlying gallery API exposes separate metrics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open VSX Registry&lt;/strong&gt;: The vendor-neutral marketplace used by VSCodium, Gitpod, and Eclipse Theia. It provides a clean REST API with different metric structures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crucially, &lt;strong&gt;both APIs support CORS with &lt;code&gt;access-control-allow-origin: *&lt;/code&gt;&lt;/strong&gt;, allowing modern browsers to query them directly without requiring a proxy server.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Layer 1: Querying Store APIs Directly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Batch-Querying Visual Studio Marketplace
&lt;/h3&gt;

&lt;p&gt;Instead of making 7 separate HTTP requests, Microsoft's Marketplace API allows querying multiple extensions in a single &lt;code&gt;POST&lt;/code&gt; request to &lt;code&gt;_apis/public/gallery/extensionquery&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchVsMarketplace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
      &lt;span class="na"&gt;criteria&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;filterType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vsId&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;914&lt;/span&gt; &lt;span class="c1"&gt;// Requests statistics, versions, and metadata&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json;api-version=3.0-preview.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statistics&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statisticName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Empirical verification: Microsoft Marketplace UI displays (install + downloadCount)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;installs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;downloadCount&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// The API returns the latest release first in versions[0]&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensionName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;installs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Empirical Verification on Marketplace Installs:&lt;/strong&gt; Microsoft's API returns two separate download metrics: &lt;code&gt;install&lt;/code&gt; (active installed instances) and &lt;code&gt;downloadCount&lt;/code&gt; (package downloads/updates). Through empirical cross-referencing between the API response and the live web pages for all 7 extensions, the "Installs" figure shown on the Marketplace product page aligned with &lt;code&gt;(stats.install + stats.downloadCount)&lt;/code&gt;. This was observed across the seven extensions tested during development; it should be treated as an empirical observation rather than a guaranteed API contract.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Querying Open VSX Registry
&lt;/h3&gt;

&lt;p&gt;Open VSX provides an open REST endpoint at &lt;code&gt;https://open-vsx.org/api/{namespace}/{extension}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchOpenVsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ovsxExts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ovsxId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ovsxExts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://open-vsx.org/api/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ovsxId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;downloads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;downloadCount&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Open VSX fetch failed for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚡ Layer 2: The Client-Side Module (&lt;code&gt;extension-stats.js&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://github.com/kareem2099/dotuniverse/tree/main/js/modules" rel="noopener noreferrer"&gt;dotUniverse's modular architecture&lt;/a&gt;, we created &lt;code&gt;js/modules/extension-stats.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why a 24-Hour Cache is Essential
&lt;/h3&gt;

&lt;p&gt;Firing external API requests on every page refresh is bad engineering—it wastes bandwidth, risks third-party rate limits, and causes text flicker.&lt;/p&gt;

&lt;p&gt;Because developer tools are typically released over days or weeks, a &lt;strong&gt;24-hour cache TTL&lt;/strong&gt; (&lt;code&gt;24 * 60 * 60 * 1000&lt;/code&gt;) is a practical default: it reduces unnecessary API requests while keeping the displayed statistics reasonably fresh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ExtensionStats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;CACHE_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotuniverse_ext_stats_v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;CACHE_TTL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 24 hours (1 day)&lt;/span&gt;

  &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Instantly apply cached data to DOM (avoids visible flicker)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCached&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyToDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Fetch in background only when the 24-hour window expires&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CACHE_TTL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clean DOM Mutation via Semantic Attributes
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;index.html&lt;/code&gt;, each extension card includes a semantic &lt;code&gt;data-ext-name&lt;/code&gt; identifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ext-card"&lt;/span&gt; &lt;span class="na"&gt;data-ext-name=&lt;/span&gt;&lt;span class="s"&gt;"codetune"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ext-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ext-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"prefix"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Code&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"suffix"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tune&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ext-version"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;v1.3.0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ext-stores"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-badge vs"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-info"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;VS Marketplace&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-dl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;737 installs&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-badge ovsx"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-info"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Open VSX&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"store-dl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;1,500 downloads&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When fresh metrics arrive:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;.ext-version&lt;/code&gt; updates to the store's current version (e.g. &lt;code&gt;v1.3.0&lt;/code&gt;, &lt;code&gt;v2.2.1&lt;/code&gt;, &lt;code&gt;v3.5.1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Store badges update with formatted counts (e.g., &lt;code&gt;1,040 installs&lt;/code&gt;, &lt;code&gt;6,000 downloads&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The grand total (&lt;code&gt;19,500+&lt;/code&gt;) is calculated and smoothly updated in both the header stats and the hero banner.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🤖 Layer 3: Automated Daily CI/CD Synchronization
&lt;/h2&gt;

&lt;p&gt;To keep the repository &lt;code&gt;README.md&lt;/code&gt; and static HTML in sync for users without JavaScript or search bots, we created a zero-dependency Node script: &lt;code&gt;scripts/sync-extension-stats.mjs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Running this script fetches live data, parses &lt;code&gt;index.html&lt;/code&gt; and &lt;code&gt;README.md&lt;/code&gt;, updates markdown tables, Shields.io badges, and prints a formatted terminal overview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;node scripts/sync-extension-stats.mjs

🔄 Fetching live extension stats from VS Marketplace and Open VSX...

📊 Live Extension Stats:
┌─────────┬──────────────┬──────────┬────────────────┬──────────┬─────────────────┐
│ &lt;span class="o"&gt;(&lt;/span&gt;index&lt;span class="o"&gt;)&lt;/span&gt; │ Extension    │ Version  │ VS Marketplace │ Open VSX │ Total Downloads │
├─────────┼──────────────┼──────────┼────────────────┼──────────┼─────────────────┤
│ 0       │ &lt;span class="s1"&gt;'CodeTune'&lt;/span&gt;   │ &lt;span class="s1"&gt;'v1.3.0'&lt;/span&gt; │ &lt;span class="s1"&gt;'734'&lt;/span&gt;          │ &lt;span class="s1"&gt;'1,486'&lt;/span&gt;  │ &lt;span class="s1"&gt;'2,220'&lt;/span&gt;         │
│ 1       │ &lt;span class="s1"&gt;'dotcommand'&lt;/span&gt; │ &lt;span class="s1"&gt;'v2.0.1'&lt;/span&gt; │ &lt;span class="s1"&gt;'778'&lt;/span&gt;          │ &lt;span class="s1"&gt;'970'&lt;/span&gt;    │ &lt;span class="s1"&gt;'1,748'&lt;/span&gt;         │
│ 2       │ &lt;span class="s1"&gt;'DotEnvy'&lt;/span&gt;    │ &lt;span class="s1"&gt;'v2.2.1'&lt;/span&gt; │ &lt;span class="s1"&gt;'758'&lt;/span&gt;          │ &lt;span class="s1"&gt;'2,173'&lt;/span&gt;  │ &lt;span class="s1"&gt;'2,931'&lt;/span&gt;         │
│ 3       │ &lt;span class="s1"&gt;'DotShare'&lt;/span&gt;   │ &lt;span class="s1"&gt;'v3.5.1'&lt;/span&gt; │ &lt;span class="s1"&gt;'1,040'&lt;/span&gt;        │ &lt;span class="s1"&gt;'5,987'&lt;/span&gt;  │ &lt;span class="s1"&gt;'7,027'&lt;/span&gt;         │
│ 4       │ &lt;span class="s1"&gt;'DotFetch'&lt;/span&gt;   │ &lt;span class="s1"&gt;'v2.1.1'&lt;/span&gt; │ &lt;span class="s1"&gt;'470'&lt;/span&gt;          │ &lt;span class="s1"&gt;'2,766'&lt;/span&gt;  │ &lt;span class="s1"&gt;'3,236'&lt;/span&gt;         │
│ 5       │ &lt;span class="s1"&gt;'DotReadme'&lt;/span&gt;  │ &lt;span class="s1"&gt;'v1.2.0'&lt;/span&gt; │ &lt;span class="s1"&gt;'364'&lt;/span&gt;          │ &lt;span class="s1"&gt;'1,719'&lt;/span&gt;  │ &lt;span class="s1"&gt;'2,083'&lt;/span&gt;         │
│ 6       │ &lt;span class="s1"&gt;'DotSense'&lt;/span&gt;   │ &lt;span class="s1"&gt;'v1.3.0'&lt;/span&gt; │ &lt;span class="s1"&gt;'257'&lt;/span&gt;          │ &lt;span class="s1"&gt;'0'&lt;/span&gt;      │ &lt;span class="s1"&gt;'257'&lt;/span&gt;           │
└─────────┴──────────────┴──────────┴────────────────┴──────────┴─────────────────┘

🏆 Grand Total Downloads: 19,502 &lt;span class="o"&gt;(&lt;/span&gt;Marketplace: 4,401, Open VSX: 15,101&lt;span class="o"&gt;)&lt;/span&gt;

✅ index.html updated successfully.
✅ README.md updated successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run this hands-free, we added &lt;code&gt;.github/workflows/update-extension-stats.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auto Update Extension Stats&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Runs everyday at midnight UTC&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Allows manual trigger from GitHub UI&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sync-stats&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sync extension downloads and versions&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node scripts/sync-extension-stats.mjs&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Commit and push changes if updated&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config --global user.name "github-actions[bot]"&lt;/span&gt;
          &lt;span class="s"&gt;git config --global user.email "github-actions[bot]@users.noreply.github.com"&lt;/span&gt;
          &lt;span class="s"&gt;git add index.html README.md&lt;/span&gt;
          &lt;span class="s"&gt;if git diff --staged --quiet; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "No changes detected."&lt;/span&gt;
          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;git commit -m "chore: auto-update extension downloads and versions [skip ci]"&lt;/span&gt;
            &lt;span class="s"&gt;git push&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Clean Commit History:&lt;/strong&gt; The &lt;code&gt;git diff --staged --quiet&lt;/code&gt; check ensures that GitHub Actions only commits when marketplace metrics or versions actually change. This keeps the Git history clean from empty daily noise.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🚀 The Bigger Picture: Building in Public
&lt;/h2&gt;

&lt;p&gt;Automating tool statistics ties directly into how I build in public. Alongside extensions, dotUniverse features an open &lt;strong&gt;Growth Challenge Tracker&lt;/strong&gt; across 9 creator and developer platforms.&lt;/p&gt;

&lt;p&gt;Here is the current state for &lt;strong&gt;October 2026&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Current (Now)&lt;/th&gt;
&lt;th&gt;Target (Goal)&lt;/th&gt;
&lt;th&gt;Remaining&lt;/th&gt;
&lt;th&gt;Progress&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🚀 &lt;strong&gt;dev.to&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3,986&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4,200&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+214&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;95%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💼 &lt;strong&gt;LinkedIn&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;709&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;800&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+91&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;89%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🎵 &lt;strong&gt;TikTok&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;37&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+23&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;62%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;▶️ &lt;strong&gt;YouTube&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+30&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✍️ &lt;strong&gt;Medium&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📘 &lt;strong&gt;Facebook&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;75%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📸 &lt;strong&gt;Instagram&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;𝕏 &lt;strong&gt;X / Twitter&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;18&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;90%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🦋 &lt;strong&gt;Bluesky&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;21&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On dev.to specifically, we recently passed &lt;strong&gt;15,400+ total views&lt;/strong&gt;, &lt;strong&gt;93 published posts&lt;/strong&gt;, &lt;strong&gt;97 reactions&lt;/strong&gt;, and &lt;strong&gt;67 comments&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Because dev.to is currently at 3,986 / 4,200, we explicitly commented out the celebratory &lt;code&gt;15-DAY RECORD&lt;/code&gt; badge in the HTML until the 4,200 mark is officially crossed. Milestones are meaningful only when they are genuine!&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Key Engineering Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Leverage Dual-Path Synchronization&lt;/strong&gt;: Combining client-side background sync with scheduled CI/CD ensures that both web visitors and static repository viewers get consistently updated extension statistics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore Public API Capabilities&lt;/strong&gt;: Both the Visual Studio Marketplace and Open VSX support CORS directly. Before introducing a custom serverless proxy, inspect the network headers first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respect the Client Cache&lt;/strong&gt;: A 24-hour &lt;code&gt;localStorage&lt;/code&gt; TTL reduces visible flickering, avoids API-dependent initial rendering on repeat visits, respects third-party rate limits, and matches the realistic release frequency of developer tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional CI/CD Commits&lt;/strong&gt;: Always check &lt;code&gt;git diff --staged --quiet&lt;/code&gt; before committing automated bot changes to keep your repository history concise and meaningful.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🔗 Project Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;Live Website&lt;/strong&gt;: &lt;a href="https://universe.dotsuite.dev/" rel="noopener noreferrer"&gt;universe.dotsuite.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/kareem2099/dotuniverse" rel="noopener noreferrer"&gt;kareem2099/dotuniverse&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;VS Code Extensions&lt;/strong&gt;: Search for &lt;code&gt;FreeRave&lt;/code&gt; on VS Code Marketplace or Open VSX!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;How do you automate metrics across your open-source repositories? Do you rely on static shields or live client-side queries? Let's discuss in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>vscode</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The VSIX Packaging Trap: How I Eliminated Embedded Client Secrets from a VS Code Extension</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Fri, 25 Sep 2026 15:04:51 +0000</pubDate>
      <link>https://dev.to/freerave/the-vsix-packaging-trap-how-i-eliminated-embedded-client-secrets-from-a-vs-code-extension-2650</link>
      <guid>https://dev.to/freerave/the-vsix-packaging-trap-how-i-eliminated-embedded-client-secrets-from-a-vs-code-extension-2650</guid>
      <description>&lt;h2&gt;
  
  
  A .vsix is just a ZIP archive of plain JavaScript. Here is the post-mortem of how our build-time secrets failed, how we designed dynamic device registration with OS SecretStorage, and how we solved the 'scanner scanning the scanner' paradox.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Distributing a client-server VS Code extension means accepting a hard truth: &lt;strong&gt;a &lt;code&gt;.vsix&lt;/code&gt; file is just a ZIP archive containing JavaScript that can be extracted and inspected.&lt;/strong&gt; This article breaks down how our initial attempt to inject build-time backend secrets was scrapped, how we engineered an anonymous dynamic device handshake with OS-level &lt;code&gt;SecretStorage&lt;/code&gt;, and how we resolved the bizarre paradox of static security scanners flagging our own secret detection patterns.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Illusion of the Extension Package
&lt;/h2&gt;

&lt;p&gt;When developers distribute software through the VS Code Marketplace or the Open VSX Registry, it is easy to unconsciously think of the &lt;code&gt;.vsix&lt;/code&gt; file as a compiled, opaque binary.&lt;/p&gt;

&lt;p&gt;It is not.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;.vsix&lt;/code&gt; package is an Open Packaging Conventions (OPC) archive — an ordinary ZIP file containing your extension’s manifest (&lt;code&gt;package.json&lt;/code&gt;), assets, and compiled JavaScript output (&lt;code&gt;out/&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Anyone can verify this with standard shell utilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Rename and extract any published extension&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;DotEnvy-2.1.0.vsix DotEnvy.zip
unzip &lt;span class="nt"&gt;-q&lt;/span&gt; DotEnvy.zip &lt;span class="nt"&gt;-d&lt;/span&gt; extracted/
&lt;span class="nb"&gt;cd &lt;/span&gt;extracted/extension/out

&lt;span class="c"&gt;# Search for sensitive variables&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"SHARED_SECRET"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you injected an API key, an HMAC signing secret, or a database token into your client code at compile time, &lt;strong&gt;you just published that secret to the entire world.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Context: Why Did We Need a Secret in the First Place?
&lt;/h2&gt;

&lt;p&gt;In &lt;a&gt;Part 1 of this series&lt;/a&gt;, I explained how we built &lt;strong&gt;Aegis&lt;/strong&gt; — a 4-layer AI secret detection pipeline for &lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotenvy" rel="noopener noreferrer"&gt;DotEnvy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first three layers (Regex, Community Blacklist, and Entropy Gating) execute locally inside the editor process. But Layer 4 requires invoking our Python microservice (&lt;code&gt;aegis.dotsuite.dev&lt;/code&gt;) on Railway to run contextual neural classification.&lt;/p&gt;

&lt;p&gt;To protect the backend against unauthorized abuse, spam, and denial-of-service, we required incoming HTTP requests to be signed using &lt;strong&gt;HMAC-SHA256&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;$$\text{Signature} = \text{HMAC-SHA256}(\text{SharedSecret}, \text{Timestamp} + "." + \text{Payload})$$&lt;/p&gt;

&lt;p&gt;This design introduced our fundamental dilemma:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How does an open-source, publicly distributed client authenticate with a protected backend service without shipping a hardcoded secret in its package?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Attempt 1: The Build-Time Secret Trap (v2.1.0)
&lt;/h2&gt;

&lt;p&gt;Our initial approach relied on build-time environment variable substitution. In our deployment pipeline, a Node script injected a secret before invoking &lt;code&gt;vsce package&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// scripts/build-with-env.js (Flawed Approach)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRODUCTION_EXTENSION_SECRET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;out/utils/llmAnalyzer.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;REPLACE_AT_BUILD_TIME&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;out/utils/llmAnalyzer.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this kept the secret out of our public git repository, it was an architectural disaster:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The VSIX Leak&lt;/strong&gt;: As demonstrated above, extracting the &lt;code&gt;.vsix&lt;/code&gt; exposed the secret immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Scanner Flags&lt;/strong&gt;: Automated CI/CD bots (GitHub Secret Scanning, Trufflehog, CodeQL) automatically inspect release assets. A high-entropy hex string inside compiled JavaScript triggers immediate alerts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Point of Compromise&lt;/strong&gt;: If one user decompiles the extension and leaks the shared secret, the backend can no longer trust &lt;em&gt;any&lt;/em&gt; extension client without rotating the key and breaking every installed instance worldwide.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We scrapped this design entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attempt 2: Zero Embedded Client Secrets &amp;amp; Dynamic Device Handshake (v2.1.2)
&lt;/h2&gt;

&lt;p&gt;We established a strict architectural rule: &lt;strong&gt;Zero Embedded / Static Client Secrets&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not a single secret, token, or private key may exist in the source code, build scripts, or packaged &lt;code&gt;.vsix&lt;/code&gt; bundle.&lt;/p&gt;

&lt;p&gt;Instead, we designed an anonymous, zero-touch dynamic device registration handshake:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────────────────────────────────┐           ┌────────────────────────────────────────┐
│ DotEnvy Client (First Activation)      │           │ Aegis Backend (aegis.dotsuite.dev)     │
└───────────────────┬────────────────────┘           └───────────────────┬────────────────────┘
                    │                                                    │
                    │ 1. POST /extension/register                        │
                    │    { machine_id: hash(vscode.env.machineId) }      │
                    ├───────────────────────────────────────────────────►│ Strict IP Rate Limiter
                    │                                                    │ (Max 10 per hour per IP)
                    │                                                    │
                    │                                                    │ 2. Backend generates unique
                    │                                                    │    cryptographic client_secret
                    │ 3. Returns per-device secret                       │    and stores active record
                    │◄───────────────────────────────────────────────────┤
                    │                                                    │
                    ▼                                                    ▼
          Stored Exclusively in                                Subsequent requests signed via
         OS-level SecretStorage                                HMAC-SHA256(timestamp + body)
       (macOS Keychain / Windows                               with per-machine rate limiting
      Credential Manager / libsecret)                                 (30 req/min)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Anonymous Environment Identity
&lt;/h3&gt;

&lt;p&gt;When DotEnvy launches for the first time, it generates a non-reversible identifier from VS Code's environment API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;getMachineId&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;machineId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anonymous-machine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;vscode.env.machineId&lt;/code&gt; provides a pseudonymous environment identifier that lets the backend maintain per-client state and rate limits without requiring a user account.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ephemeral Dynamic Registration
&lt;/h3&gt;

&lt;p&gt;The extension calls &lt;code&gt;/extension/register&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Defense in Depth&lt;/strong&gt;: The registration endpoint is protected by strict IP-based rate limiting (maximum 10 registrations per hour per IP) to prevent Sybil registration floods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unique Credential Issuance&lt;/strong&gt;: The backend generates an independent 256-bit cryptographically random secret (&lt;code&gt;client_secret&lt;/code&gt;), persists the mapping in PostgreSQL, and returns it over TLS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. OS-Level SecretStorage
&lt;/h3&gt;

&lt;p&gt;The extension never writes the returned secret to disk, &lt;code&gt;.env&lt;/code&gt; files, or standard workspace settings. It stores the credential directly inside VS Code's &lt;code&gt;SecretStorage&lt;/code&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;setSharedSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenvy.llm.sharedSecret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sharedSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, VS Code delegates &lt;code&gt;SecretStorage&lt;/code&gt; to native operating system keyrings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;: Apple Keychain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;: Windows Credential Manager&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux&lt;/strong&gt;: Secret Service API (gnome-keyring / KWallet)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Authenticated Request Signing
&lt;/h3&gt;

&lt;p&gt;For all subsequent requests, DotEnvy signs its payloads using HMAC-SHA256:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;signRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sharedSecret&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the backend, Aegis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validates the timestamp against a &lt;strong&gt;5-minute sliding window&lt;/strong&gt; to prevent replay attacks.&lt;/li&gt;
&lt;li&gt;Looks up the &lt;code&gt;client_secret&lt;/code&gt; corresponding to the &lt;code&gt;X-Machine-ID&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;Uses Python's constant-time comparison &lt;code&gt;hmac.compare_digest&lt;/code&gt; to prevent timing attacks.&lt;/li&gt;
&lt;li&gt;Applies a machine-level rate limit (30 requests/minute).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a specific client secret is ever compromised on a developer's local machine, revoking that single record does not disrupt any other user.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Automated Gatekeeper: CI/CD Pre-Publish Validation
&lt;/h2&gt;

&lt;p&gt;To ensure no developer or automated script ever accidentally reintroduces an embedded secret, we added an automated pre-publish scanner to &lt;a&gt;&lt;code&gt;scripts/build-with-env.js&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// scripts/build-with-env.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;out&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;scanDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;flagged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;statSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;flagged&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;scanDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Check for illegal embedded secret patterns&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/const&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+embeddedSecret&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*=&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;"'&lt;/span&gt;&lt;span class="se"&gt;][&lt;/span&gt;&lt;span class="sr"&gt;A-Za-z0-9_-&lt;/span&gt;&lt;span class="se"&gt;]{20,}[&lt;/span&gt;&lt;span class="sr"&gt;"'&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`❌ Security Alert: Hardcoded embeddedSecret found in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;flagged&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;flagged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;scanDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`\n❌ Pre-publish check failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; leaked secret(s) found in out/!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;✅ Security check passed: 0 embedded secrets found in compiled out/ bundle.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This verification script runs automatically as part of &lt;code&gt;npm run package&lt;/code&gt;. If a secret is detected, the build halts with an exit code of &lt;code&gt;1&lt;/code&gt;, aborting the release pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Scanner Scanning the Scanner" Paradox (v2.1.3)
&lt;/h2&gt;

&lt;p&gt;Once we eliminated embedded secrets, we collided with an ironic roadblock: &lt;strong&gt;automated static security scanners started blocking our extension releases.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DotEnvy is a security extension designed to detect leaked credentials. Its pattern registry naturally contains regular expressions for popular API tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ v2.1.0: Literal regex prefixes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;KNOWN_SECRET_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AWS Access Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/AKIA&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9A-Z&lt;/span&gt;&lt;span class="se"&gt;]{16}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Stripe Live Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/sk_live_&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9a-zA-Z&lt;/span&gt;&lt;span class="se"&gt;]{24,}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GitHub Token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/ghp_&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z0-9&lt;/span&gt;&lt;span class="se"&gt;]{36}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Google API Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/AIza&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9A-Za-z&lt;/span&gt;&lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="sr"&gt;_&lt;/span&gt;&lt;span class="se"&gt;]{35}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When GitHub’s push protection and marketplace upload scanners inspected our compiled output, their naive string-matching heuristics triggered on our own code:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Warning: Leaked AWS Access Key pattern detected in out/utils/llmAnalyzer.js"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The scanners couldn't differentiate between code &lt;em&gt;containing&lt;/em&gt; a secret and code &lt;em&gt;designed to detect&lt;/em&gt; a secret.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoiding Static Scanner False Positives via Runtime Pattern Construction
&lt;/h3&gt;

&lt;p&gt;To resolve these false positives without weakening our detection capabilities, we refactored the pattern registry to assemble sensitive token prefixes dynamically at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ v2.1.3: Assembled at runtime — clean scanner bill of health&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;KNOWN_SECRET_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AWS Access Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;KIA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[0-9A-Z]{16}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Stripe Live Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_live_&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[0-9a-zA-Z]{24,}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GitHub Token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    
        &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hp_&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[a-zA-Z0-9]{36}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Google API Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AI&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;za&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[0-9A-Za-z&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;-_]{35}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Engineering Note&lt;/strong&gt;: This runtime string assembly is &lt;strong&gt;not an evasion technique against security controls&lt;/strong&gt;; it is a pragmatic packaging workaround to prevent regex-based linters from confusing detection definitions with genuine credential leaks. Inside Node's V8 engine, the compiled &lt;code&gt;RegExp&lt;/code&gt; objects are identical and execute at native engine speed.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Build Hygiene &amp;amp; VSIX Purity
&lt;/h2&gt;

&lt;p&gt;Our final hardening step addressed package purity:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Pre-Build Purging&lt;/strong&gt;: We updated our &lt;code&gt;package.json&lt;/code&gt; scripts to mandate &lt;code&gt;rm -rf out&lt;/code&gt; before every invocation of &lt;code&gt;tsc&lt;/code&gt;. Stale, uncompiled test artifacts from previous development sessions can never accidentally be swept into a production &lt;code&gt;.vsix&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggressive &lt;code&gt;.vscodeignore&lt;/code&gt; Hardening&lt;/strong&gt;: We audited and excluded all non-production files:

&lt;ul&gt;
&lt;li&gt;Development linter configs (&lt;code&gt;eslint.config.mjs&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Internal test runners and mock fixtures&lt;/li&gt;
&lt;li&gt;Temporary extraction folders (&lt;code&gt;extracted-vsix/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Documentation drafts and article markdowns&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The resulting &lt;code&gt;.vsix&lt;/code&gt; bundle contains solely the minified runtime code and localized UI assets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Checklist for VS Code Extension Developers
&lt;/h2&gt;

&lt;p&gt;If you are building a VS Code extension that interacts with a private backend, keep these rules in mind:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Bad Practice ❌&lt;/th&gt;
&lt;th&gt;Good Practice ✅&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Client Secrets&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Injecting API keys in build scripts&lt;/td&gt;
&lt;td&gt;Zero embedded secrets; dynamic device handshake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Saving tokens in &lt;code&gt;workspaceState&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Storing credentials in native OS &lt;code&gt;SecretStorage&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Request Signing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sending plain machine IDs&lt;/td&gt;
&lt;td&gt;HMAC-SHA256 with timestamp sliding window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scanner Hygiene&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hardcoded token regex literals&lt;/td&gt;
&lt;td&gt;Dynamic runtime pattern construction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Package Hygiene&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Relying on default package contents&lt;/td&gt;
&lt;td&gt;Automated &lt;code&gt;rm -rf out&lt;/code&gt; + strict &lt;code&gt;.vscodeignore&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Links &amp;amp; Verification
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;VS Code Marketplace&lt;/strong&gt;: &lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotenvy" rel="noopener noreferrer"&gt;marketplace.visualstudio.com/items?itemName=FreeRave.dotenvy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Open VSX Registry&lt;/strong&gt;: &lt;a href="https://open-vsx.org/extension/freerave/dotenvy" rel="noopener noreferrer"&gt;open-vsx.org/extension/freerave/dotenvy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/kareem2099/dotenvy" rel="noopener noreferrer"&gt;github.com/kareem2099/dotenvy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Read Part 1&lt;/strong&gt;: &lt;a href="https://dev.to/freerave/dotenvy-aegis-building-a-4-layer-ai-secret-detection-pipeline-for-vs-code-115o"&gt;DotEnvy Aegis: Building a 4-Layer AI Secret Detection Pipeline for VS Code&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;Full Changelog&lt;/strong&gt;: &lt;a href="https://github.com/kareem2099/dotenvy/blob/main/CHANGELOG.md" rel="noopener noreferrer"&gt;CHANGELOG.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Written by FreeRave. If you've encountered packaging headaches or static scanner false alarms in your extensions, feel free to reach out and share your experience.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>security</category>
      <category>typescript</category>
      <category>architecture</category>
    </item>
    <item>
      <title>DotEnvy Aegis: Building a 4-Layer AI Secret Detection Pipeline for VS Code</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Thu, 24 Sep 2026 20:38:11 +0000</pubDate>
      <link>https://dev.to/freerave/dotenvy-aegis-building-a-4-layer-ai-secret-detection-pipeline-for-vs-code-115o</link>
      <guid>https://dev.to/freerave/dotenvy-aegis-building-a-4-layer-ai-secret-detection-pipeline-for-vs-code-115o</guid>
      <description>&lt;h2&gt;
  
  
  How I architected a multi-layer secret scanner combining regex, truncated composite community hashing, Shannon entropy gating, and a 35-feature neural classifier — cutting LLM overhead by ~80%.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: DotEnvy Aegis introduces a 4-layer secret detection pipeline (Regex → Truncated Composite Community Blacklist → Shannon Entropy Gate → Neural Context Classifier), migrates encryption keys to the OS keychain, auto-authorizes backups with project master keys, and syncs hashes to an anti-poisoning community blacklist on Railway — all without transmitting raw secret payloads.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What is DotEnvy?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotenvy" rel="noopener noreferrer"&gt;DotEnvy&lt;/a&gt; is an open-source VS Code extension designed to bring enterprise-grade security to local &lt;code&gt;.env&lt;/code&gt; file management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted Variable Management&lt;/strong&gt; (AES-256-GCM, PBKDF2 with 310,000 iterations)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-User Envelope Encryption&lt;/strong&gt; (each teammate decrypts using individual credentials)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Synchronization&lt;/strong&gt; (native Doppler, Vercel, and AWS integrations)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-Powered Secret Detection&lt;/strong&gt; (the focus of this article)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git Pre-Commit Hooks&lt;/strong&gt; (blocking credential leaks before commits land in git history)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment Analytics, Timeline, &amp;amp; Diff&lt;/strong&gt; panels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extension communicates with &lt;strong&gt;Aegis&lt;/strong&gt; (&lt;code&gt;python-llm&lt;/code&gt;), a custom Python microservice deployed on Railway that runs contextual neural classification on candidate secrets.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: One Layer is Never Enough
&lt;/h2&gt;

&lt;p&gt;In our earliest experimental prototype, secret detection was a blunt instrument: every candidate token triggered an HTTP request to the backend model.&lt;/p&gt;

&lt;p&gt;This naive architecture fell apart under real-world development workloads:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Latency Overhead&lt;/strong&gt;: Every network round-trip added 200–450ms of latency, quickly degrading editor responsiveness during live typing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability Dependency&lt;/strong&gt;: If the network dropped or the backend restarted, secret detection failed silently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The False Positive/Negative Dilemma&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;A high-entropy random string (like an image hash or UUID) looks like a secret to entropy analyzers, but is harmless.&lt;/li&gt;
&lt;li&gt;A low-entropy or structured token looks harmless to statistical math, but may grant full database admin rights.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Context matters. Regex patterns matter. Math matters. Community intelligence matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aegis solves this by decoupling detection into an L1 → L4 pipeline: four independent, complementary layers where each layer filters out noise before invoking the more expensive layer downstream.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The L1–L4 Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Candidate: (secretValue, contextLine, variableName)
                     │
                     ▼
┌──────────────────────────────────────────┐
│  L1: Regex Pattern Engine                │ ← Sub-millisecond, in-process
│  Matches well-known vendor prefixes      │   High-confidence match → HIGH
└────────────────────┬─────────────────────┘
                     │ no match
                     ▼
┌──────────────────────────────────────────┐
│  L2: Community Blacklist Cache           │ ← O(1) in-memory Set&amp;lt;string&amp;gt;
│  Truncated composite hash lookup         │   Known leaked hash → HIGH
└────────────────────┬─────────────────────┘
                     │ not in blacklist
                     ▼
┌──────────────────────────────────────────┐
│  L3: Shannon Entropy Gate                │ ← Pure mathematical calculation
│  Normalized entropy &amp;lt; 3.5 → LOW (skip)   │   Filters ~80% of candidate tokens
└────────────────────┬─────────────────────┘
                     │ entropy ≥ 3.5
                     ▼
┌──────────────────────────────────────────┐
│  L4: Contextual Neural Classifier        │ ← Remote FastAPI service
│  35-feature vector + attention layers    │   Deep semantic risk analysis
└──────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our current workload benchmarks across typical codebases, &lt;strong&gt;approximately 20% of extracted candidates reach L4&lt;/strong&gt;. The remaining ~80% are resolved in-memory with sub-millisecond execution times, saving substantial network bandwidth and cloud compute.&lt;/p&gt;




&lt;h3&gt;
  
  
  Layer 1: In-Process Regex Engine (Instant Confidence)
&lt;/h3&gt;

&lt;p&gt;Known secret formats (like AWS access keys, Stripe live tokens, and GitHub personal access tokens) follow strict, deterministic grammars. Running an AI model to identify a string that starts with &lt;code&gt;AKIA&lt;/code&gt; followed by 16 alphanumeric characters is wasteful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;KNOWN_SECRET_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AWS Access Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;KIA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[0-9A-Z]{16}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Stripe Live Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_live_&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[0-9a-zA-Z]{24,}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GitHub Token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hp_&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[a-zA-Z0-9]{36}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Google API Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AI&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;za&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[0-9A-Za-z&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;-_]{35}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;An L1 match immediately assigns &lt;code&gt;high&lt;/code&gt; risk, bypasses all subsequent layers, and triggers an asynchronous hash report to the community blacklist.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Layer 2: Community Blacklist via Truncated Composite Hashing
&lt;/h3&gt;

&lt;p&gt;When a secret is identified and verified across the community, other developers should benefit instantly without having to re-analyze it through the LLM. However, sharing leaked secrets raises an immediate privacy question: &lt;strong&gt;How do you cross-reference secrets without transmitting sensitive values over the network?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;L2 utilizes &lt;strong&gt;truncated composite hashing&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;hashEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;variableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Only capture the variable name and the first 8 characters of the value&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;variableName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Privacy Nuance &amp;amp; Threat Model
&lt;/h4&gt;

&lt;p&gt;We deliberately avoid claiming that this hashing scheme is an "absolute privacy shield":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it accomplishes&lt;/strong&gt;: The full secret is never transmitted across the wire or stored in community databases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The engineering trade-off&lt;/strong&gt;: For very short secrets or known formats, truncated prefixes could theoretically be susceptible to targeted dictionary guessing. We treat this composite hash as an effective deduplication fingerprint for collaborative defense, not a one-way cryptographic commitment for sensitive data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On extension activation, DotEnvy pulls the promoted blacklist hashes into an in-memory &lt;code&gt;Set&amp;lt;string&amp;gt;&lt;/code&gt;. Any candidate lookup is an $O(1)$ memory check with zero network overhead.&lt;/p&gt;

&lt;h4&gt;
  
  
  Server-Side Anti-Poisoning Architecture
&lt;/h4&gt;

&lt;p&gt;To prevent malicious clients from poisoning the blacklist or whitelisting actual credentials, submissions must pass a server-side reputation pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client Submits Hash
        │
        ▼
Staging Queue (Requires 3 distinct environments + reputation weighting)
        │
        ▼
Server-Side Verification (Backend re-evaluates risk on the pattern)
        │
        ▼
Promoted to Community Blacklist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Threat Model Note&lt;/strong&gt;: The 3-environment quorum and historical accuracy weighting are designed to &lt;strong&gt;raise the operational cost of poisoning attacks&lt;/strong&gt;, rather than claiming Byzantine Sybil-proof consensus. High-accuracy reporters gain vote weight, while repeated false reporters are banned.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Layer 3: Shannon Entropy Gate
&lt;/h3&gt;

&lt;p&gt;Shannon entropy quantifies the unpredictability and information density of a string:&lt;/p&gt;

&lt;p&gt;$$H(X) = -\sum_{i=1}^{n} P(x_i) \log_2 P(x_i)$$&lt;/p&gt;

&lt;p&gt;In our feature extraction pipeline, Shannon entropy is calculated and normalized into a standard feature scalar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractFeatures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secretValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variableName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entropy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Denormalize f[7]&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entropy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;3.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;low&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Skip expensive L4 inference entirely&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plain text words and standard identifiers (&lt;code&gt;const databaseHost = "localhost"&lt;/code&gt;) exhibit low entropy ($\approx 2.1 - 2.8$). Cryptographic secrets and API tokens (&lt;code&gt;sk_live_9xQ8...&lt;/code&gt;) typically exhibit entropy values above $4.2$. &lt;/p&gt;

&lt;p&gt;Filtering out low-entropy candidates at L3 eliminates the vast majority of false alarms before a single byte touches the network.&lt;/p&gt;




&lt;h3&gt;
  
  
  Layer 4: Contextual Neural Classifier (Aegis)
&lt;/h3&gt;

&lt;p&gt;Tokens that survive L1–L3 enter L4. This layer evaluates a &lt;strong&gt;35-dimensional feature vector&lt;/strong&gt; capturing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Text Morphology (6)&lt;/strong&gt;: Uppercase ratio, digit ratio, symbol density, length normalization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entropy Gradients (3)&lt;/strong&gt;: Shannon entropy, bigram entropy, trigram entropy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern Signals (3)&lt;/strong&gt;: Base64 padding, hex character sets, character transition frequency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Semantics (5)&lt;/strong&gt;: Surrounding keywords (&lt;code&gt;Bearer&lt;/code&gt;, &lt;code&gt;Authorization&lt;/code&gt;, &lt;code&gt;db_pass&lt;/code&gt;, &lt;code&gt;private_key&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identifier Conventions (4)&lt;/strong&gt;: &lt;code&gt;ALL_CAPS&lt;/code&gt; naming, presence of &lt;code&gt;SECRET&lt;/code&gt;/&lt;code&gt;TOKEN&lt;/code&gt;/&lt;code&gt;KEY&lt;/code&gt; substrings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structural Separators (4)&lt;/strong&gt;: Dot delimiters (JWTs), underscores, dashes, colons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derived Interactions (10)&lt;/strong&gt;: Non-linear threshold flags combining entropy with context sensitivity.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# python-llm/src/model.py
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomLLM&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Neural risk classifier with self-attention and backpropagation.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ModelConfig&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DenseLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attention&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MultiHeadSelfAttention&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_heads&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;classifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FeedForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_classes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;optimizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Adam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At its current stage, the classifier is trained on an &lt;strong&gt;experimental curated dataset of 112+ labeled secret and non-secret samples&lt;/strong&gt;. It runs backpropagation via Adam optimization, with model weights persisted in a PostgreSQL database surviving service redeploys.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important Philosophy: Risk Signals, Not a Security Oracle
&lt;/h2&gt;

&lt;p&gt;A vital design principle behind Aegis:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No layer is treated as an absolute security oracle.&lt;/strong&gt; &lt;br&gt;
The pipeline generates heuristic risk classifications, not mathematical proofs of secrecy. L1 provides deterministic pattern matching for known vendor formats, while entropy and neural inference provide weighted signals to aid human developers in reviewing their environments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the remote model is unreachable or rate limits are reached, the extension seamlessly falls back to local heuristic scoring without crashing or blocking the developer.&lt;/p&gt;




&lt;h2&gt;
  
  
  OS-Level Key Security: SecretStorage Migration
&lt;/h2&gt;

&lt;p&gt;A secret detector is useless if the extension itself stores encryption keys insecurely. &lt;/p&gt;

&lt;p&gt;In earlier versions, master keys lived in VS Code’s &lt;code&gt;workspaceState&lt;/code&gt; (essentially unencrypted JSON storage). In &lt;strong&gt;Aegis&lt;/strong&gt;, all master encryption keys and PBKDF2 salts were migrated to VS Code’s OS-level &lt;strong&gt;&lt;code&gt;SecretStorage&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;: Apple Keychain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;: Windows Credential Manager&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux&lt;/strong&gt;: Secret Service API / gnome-keyring
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;ensureMasterKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExtensionContext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secretsKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET_STORAGE_KEY_PREFIX&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 1. Check OS SecretStorage&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secretsKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stored&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stored&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Zero-touch migration from legacy workspaceState&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;legacyKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspaceState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secretsKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;legacyKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secretsKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;legacyKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspaceState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secretsKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Secure cleanup&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;legacyKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Cryptographically secure 256-bit key generation&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secretsKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The migration is completely transparent to the user, executing silently upon extension activation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Verification
&lt;/h2&gt;

&lt;p&gt;Both the TypeScript extension and the Python backend are verified by end-to-end test suites:&lt;/p&gt;

&lt;h3&gt;
  
  
  DotEnvy Extension (VS Code)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🧪 Running Complete DotEnvy Test Suite

✅ [Encryption Algorithms &amp;amp; PBKDF2]           8/8 passed
✅ [L1–L4 Multi-Layer AI Scanner &amp;amp; HMAC]      4/4 passed  
✅ [Master Key Lifecycle, Password Migration]  9/9 passed

🎉 21/21 TESTS PASSED
npm run compile   → 0 errors
npm run lint      → 0 warnings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Aegis Backend Service (FastAPI / PyTorch)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ Feature extractor: 35 features verified - OK
✅ Neural model architecture - loss=1.1534
✅ Forward pass evaluation - prediction: high
✅ Full analyze pipeline execution - confidence: medium
✅ Database round-trip test - weights save/load OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Next Challenge: Shipping the Detector
&lt;/h2&gt;

&lt;p&gt;Designing a 4-layer AI scanner was only half the journey. &lt;/p&gt;

&lt;p&gt;When we attempted to package this extension into a &lt;code&gt;.vsix&lt;/code&gt; bundle and distribute it through the VS Code Marketplace and Open VSX, we collided with two massive engineering road hazards:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The VSIX Trap&lt;/strong&gt;: How our attempt to authenticate extension requests with our backend accidentally created a critical secret leak vector.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Scanner Paradox&lt;/strong&gt;: Why static analysis bots accused DotEnvy of leaking secrets simply because it contained the regex patterns needed to detect them!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 &lt;strong&gt;Read the complete post-mortem in Part 2&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://dev.to/freerave/the-vsix-packaging-trap-how-i-eliminated-embedded-client-secrets-from-a-vs-code-extension-2650"&gt;The VSIX Packaging Trap: How I Eliminated Embedded Client Secrets from a VS Code Extension&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Links &amp;amp; Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;VS Code Marketplace&lt;/strong&gt;: &lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotenvy" rel="noopener noreferrer"&gt;marketplace.visualstudio.com/items?itemName=FreeRave.dotenvy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Open VSX Registry&lt;/strong&gt;: &lt;a href="https://open-vsx.org/extension/freerave/dotenvy" rel="noopener noreferrer"&gt;open-vsx.org/extension/freerave/dotenvy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/kareem2099/dotenvy" rel="noopener noreferrer"&gt;github.com/kareem2099/dotenvy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;strong&gt;Backend Health&lt;/strong&gt;: &lt;code&gt;https://aegis.dotsuite.dev/health&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;Changelog&lt;/strong&gt;: &lt;a href="https://github.com/kareem2099/dotenvy/blob/main/CHANGELOG.md" rel="noopener noreferrer"&gt;CHANGELOG.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Written by FreeRave. Contributions and community feedback are always welcome.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>security</category>
      <category>typescript</category>
      <category>python</category>
    </item>
    <item>
      <title>DotGhostBoard 2.0.0 'Cerberus': Building a Native Cryptographic Clipboard &amp; Vault for Linux</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Tue, 22 Sep 2026 12:56:36 +0000</pubDate>
      <link>https://dev.to/freerave/dotghostboard-200-cerberus-building-a-native-cryptographic-clipboard-vault-for-linux-43n0</link>
      <guid>https://dev.to/freerave/dotghostboard-200-cerberus-building-a-native-cryptographic-clipboard-vault-for-linux-43n0</guid>
      <description>&lt;h2&gt;
  
  
  Meet DotGhostBoard 2.0.0 — a lightweight, zero-telemetry Linux clipboard manager featuring an encrypted Vault, Shannon entropy secret detection, multi-channel updates, tiling WM support, and native notifications.
&lt;/h2&gt;

&lt;p&gt;Every developer and power user on Linux has wrestled with the clipboard dilemma:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Classic Utilities:&lt;/strong&gt; Tools like &lt;code&gt;xclip&lt;/code&gt; or basic clipboards do their job, but lack visual search, organization, and security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Modern Web Wrappers:&lt;/strong&gt; Modern tools often arrive packaged in Electron, consuming 400MB+ of RAM just to hold text strings, with opaque network calls and zero encryption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Security Risk:&lt;/strong&gt; Your clipboard regularly holds your most sensitive data — database passwords, GitHub personal access tokens, AWS keys, JWT tokens, and SSH commands. Storing that in plaintext on disk is a massive vulnerability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We built &lt;strong&gt;&lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;DotGhostBoard&lt;/a&gt;&lt;/strong&gt; to solve this: a &lt;strong&gt;native, lightweight, privacy-first, and cryptographic clipboard security station&lt;/strong&gt; designed specifically for Linux.&lt;/p&gt;

&lt;p&gt;Today, after months of development, architectural refactoring, and rigorous testing, we are excited to release &lt;strong&gt;DotGhostBoard v2.0.0 "Cerberus"&lt;/strong&gt; — our biggest milestone yet! 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ What Makes DotGhostBoard Different?
&lt;/h2&gt;

&lt;p&gt;DotGhostBoard is engineered with pure native technologies: &lt;strong&gt;Python 3.11+&lt;/strong&gt;, &lt;strong&gt;PyQt6&lt;/strong&gt;, &lt;strong&gt;SQLite&lt;/strong&gt;, and &lt;strong&gt;cryptography&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Cloud &amp;amp; Zero Telemetry:&lt;/strong&gt; Everything stays strictly local on your device. No analytics, no phone-home pings, no external network requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite Secure Deletion:&lt;/strong&gt; Uses &lt;code&gt;PRAGMA secure_delete = ON&lt;/code&gt; to reduce residual deleted data in SQLite storage by overwriting freed SQLite database pages, paired with explicit handling of Write-Ahead Logs (WAL) and storage cleanup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast Global Hotkeys:&lt;/strong&gt; Low-overhead global hotkey listeners (&lt;code&gt;Ctrl+Alt+V&lt;/code&gt; for Dashboard, &lt;code&gt;Ctrl+Alt+Space&lt;/code&gt; for Spotlight Quick Search) with responsive window summoning and instant focus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ultra-Lightweight Footprint:&lt;/strong&gt; Starts near-instantaneously and uses a fraction of the memory footprint of web-based alternatives.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 What Changed in 2.0.0
&lt;/h2&gt;

&lt;p&gt;Cerberus is not a single feature release. It is an architectural rebuild focused on four foundational areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Cryptographic Storage:&lt;/strong&gt; AES-256-GCM envelope encryption with ephemeral in-memory reveal for credentials and tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret Detection and Handling:&lt;/strong&gt; Real-time Shannon entropy heuristics that intercept sensitive tokens before clipboard exposure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe Release Channels:&lt;/strong&gt; Multi-tier delivery (Stable, Beta, Alpha) with strict opt-in pre-releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Linux Desktop Integration:&lt;/strong&gt; Direct X11/EWMH workspace migration and FreeDesktop notification support.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛡️ The Architecture of 2.0.0: Core Subsystems
&lt;/h2&gt;

&lt;p&gt;Here is an engineering deep-dive into everything under the hood:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Encrypted Vault UI Subsystem (&lt;code&gt;ui/vault/&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;While DotGhostBoard has always featured &lt;strong&gt;Eclipse Mode&lt;/strong&gt; for local item encryption, 2.0.0 introduces &lt;strong&gt;The Vault&lt;/strong&gt; — a dedicated, sliding drawer panel accessible via &lt;code&gt;Ctrl+Shift+V&lt;/code&gt; or the sidebar button.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Envelope Encryption (AES-256-GCM):&lt;/strong&gt; Secrets are protected with authenticated symmetric encryption; plaintexts are never persisted to disk unencrypted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Category Filtering:&lt;/strong&gt; Organize passwords, API keys, tokens, SSH credentials, and secure notes with real-time filtering pills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-Memory Ephemeral Reveal:&lt;/strong&gt; Secrets stay masked (&lt;code&gt;••••••••••••••••&lt;/code&gt;) by default to prevent shoulder surfing, revealing only on-demand in monospace font and auto-scrubbing from memory when locked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Plaintext Deduplication:&lt;/strong&gt; Computes an in-memory HMAC digest of candidate secrets and evaluates them against existing in-memory secret signatures using constant-time &lt;code&gt;hmac.compare_digest&lt;/code&gt;. This prevents storing duplicate secrets without ever persisting plaintext hashes or pre-images into SQLite storage.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Zero-Log Password &amp;amp; Secret Detector
&lt;/h3&gt;

&lt;p&gt;One of the most dangerous clipboard events is accidentally copying a production secret. DotGhostBoard 2.0.0 integrates a real-time detection engine (&lt;code&gt;core/security/detector.py&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shannon Entropy Analysis:&lt;/strong&gt; Computes the mathematical information entropy ($\ge 3.0$) of copied text alongside character class distribution (mixed casing, digits, symbols).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Heuristics:&lt;/strong&gt; Identifies API tokens (AWS keys, GitHub PATs, JWTs, Stripe keys, generic credentials).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False-Positive Reduction &amp;amp; Guardrails:&lt;/strong&gt; Intelligently filters file paths, environment variables (like &lt;code&gt;$PWD&lt;/code&gt;), git branch names, code function calls, and multiline snippets to significantly minimize false positives while preserving true secret catches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Loss Auto-Encryption:&lt;/strong&gt; If you copy a secret and miss the toast prompt, the 60-second TTL fallback automatically encrypts the clip into Eclipse history rather than discarding it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Direct "Send to Vault" Workflow
&lt;/h3&gt;

&lt;p&gt;Found an API token in your clipboard history that you want to keep permanently safe?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text cards now feature a dedicated &lt;strong&gt;🛡️ Send to Vault&lt;/strong&gt; button and context menu action.&lt;/li&gt;
&lt;li&gt;Automatically prefills the secret dialog, decrypts on the fly if previously encrypted under Eclipse, and cleans up the history card seamlessly upon confirmation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Multi-Channel Update Engine (Stable, Beta, Alpha)
&lt;/h3&gt;

&lt;p&gt;Keeping local native desktop apps updated without waiting for distribution package maintainers can be tedious. DotGhostBoard 2.0.0 introduces an integrated &lt;strong&gt;Multi-Channel Release Engine&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select your desired update track in &lt;strong&gt;Settings → General&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stable:&lt;/strong&gt; Verified, production-ready releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beta:&lt;/strong&gt; Pre-releases and release candidates for early adopters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpha:&lt;/strong&gt; Bleeding-edge experimental builds.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe Channel Guarantee:&lt;/strong&gt; &lt;strong&gt;Stable is the default channel. Pre-release builds (Beta and Alpha) are strictly opt-in.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The update dialog features live byte-progress indicators, changelog display, and seamless one-click binary restart.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. System-Native FreeDesktop Notifications
&lt;/h3&gt;

&lt;p&gt;Instead of relying solely on system tray balloons, 2.0.0 talks directly to FreeDesktop notification daemons (&lt;code&gt;/usr/bin/notify-send&lt;/code&gt; and D-Bus):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rich desktop alerts for secret detections, sync events, and updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Click Callback:&lt;/strong&gt; Clicking a notification immediately foregrounds DotGhostBoard on your active monitor.&lt;/li&gt;
&lt;li&gt;Graceful fallback to &lt;code&gt;QSystemTrayIcon&lt;/code&gt; if an external notification daemon is not running.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  6. Tiling Window Manager &amp;amp; EWMH Workspace Migration
&lt;/h3&gt;

&lt;p&gt;Tiling window manager users (tested on Qtile, and compatible with EWMH-compliant window managers) often suffer from popup clipboard managers getting stuck on inactive workspaces or behaving strangely when toggled.&lt;/p&gt;

&lt;p&gt;DotGhostBoard 2.0.0 implements direct &lt;strong&gt;EWMH (Extended Window Manager Hints)&lt;/strong&gt; interaction using Python's standard &lt;code&gt;ctypes&lt;/code&gt; directly against &lt;code&gt;libX11.so.6&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you summon DotGhostBoard (&lt;code&gt;Ctrl+Alt+V&lt;/code&gt; or &lt;code&gt;dotghostboard --toggle&lt;/code&gt;) from &lt;strong&gt;Workspace 2&lt;/strong&gt; while the window was previously opened on &lt;strong&gt;Workspace 1&lt;/strong&gt;, DotGhostBoard:

&lt;ol&gt;
&lt;li&gt;Detects &lt;code&gt;_NET_CURRENT_DESKTOP&lt;/code&gt; vs &lt;code&gt;_NET_WM_DESKTOP&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Resolves the X11 limitation where Qt reports &lt;code&gt;isVisible() == True&lt;/code&gt; even on unmapped workspaces.&lt;/li&gt;
&lt;li&gt;Sends &lt;code&gt;_NET_WM_DESKTOP&lt;/code&gt; and &lt;code&gt;_NET_ACTIVE_WINDOW&lt;/code&gt; ClientMessages with pager priority (&lt;code&gt;source=2&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Automatically migrates the window to your active workspace and focuses it instantly without hiding!&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modal Safety:&lt;/strong&gt; Dialogs (&lt;code&gt;LockScreen&lt;/code&gt;, &lt;code&gt;UnlockDialog&lt;/code&gt;) are prepared with &lt;code&gt;prepare_dialog_for_current_workspace()&lt;/code&gt; before &lt;code&gt;exec()&lt;/code&gt;, guaranteeing modal focus without breaking the Qt event loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kill Switch:&lt;/strong&gt; &lt;code&gt;DOTGHOST_NO_EWMH=1&lt;/code&gt; is supported for users who prefer traditional window manager handling.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎨 Cyber-Stealth Phantom Visual Identity
&lt;/h2&gt;

&lt;p&gt;With 2.0.0, we retired the legacy 8-bit ghost icon in favor of the &lt;strong&gt;Cyber-Stealth Phantom&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dark graphite matte squircle paired with a radiant neon green visor (&lt;code&gt;#00ff41&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;High-precision downsampling pipeline using Lanczos resampling and unsharp masking, ensuring pixel-perfect sharpness from &lt;code&gt;16x16&lt;/code&gt; system tray icons up to &lt;code&gt;512x512&lt;/code&gt; desktop launchers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Engineering Quality &amp;amp; Verification
&lt;/h2&gt;

&lt;p&gt;We believe security and privacy utilities must be held to the highest code quality standards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;489 Automated Tests (100% Passing):&lt;/strong&gt; Unit tests, mock isolation, raw disk zero-overwrite verification, and live integration tests running inside virtual X11 displays (&lt;code&gt;Xvfb&lt;/code&gt;) against both &lt;strong&gt;Openbox&lt;/strong&gt; and real &lt;strong&gt;Qtile 0.36.0&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Modularity &amp;amp; File Budgets:&lt;/strong&gt; Architecture guardrails ensure complex UI components remain decoupled and maintainable (&lt;code&gt;ui/dashboard.py&lt;/code&gt; strictly adheres to a $\le 500$ LOC limit to eliminate God-object bloat).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Targeted Code Quality:&lt;/strong&gt; Core coordination modules, window management routines, and security controllers adhere strictly to PEP8/flake8 standards.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 How to Get DotGhostBoard 2.0.0
&lt;/h2&gt;

&lt;p&gt;DotGhostBoard is 100% open source under the &lt;strong&gt;Apache-2.0 License&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. OpenDesktop / KDE Store / Pling
&lt;/h3&gt;

&lt;p&gt;You can grab the release package, AppImage, or leave a review on OpenDesktop:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://www.opendesktop.org/p/2353623/" rel="noopener noreferrer"&gt;DotGhostBoard on OpenDesktop / Pling&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. GitHub Repository &amp;amp; Releases
&lt;/h3&gt;

&lt;p&gt;Download standalone binaries, AppImages, Debian &lt;code&gt;.deb&lt;/code&gt; packages, or inspect the source code:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;GitHub: kareem2099/DotGhostBoard&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Install from Source:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repository&lt;/span&gt;
git clone https://github.com/kareem2099/DotGhostBoard.git
&lt;span class="nb"&gt;cd &lt;/span&gt;DotGhostBoard

&lt;span class="c"&gt;# Set up environment&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Run DotGhostBoard&lt;/span&gt;
python3 main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enable Global Shortcuts:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Toggle Dashboard:&lt;/strong&gt; &lt;code&gt;Ctrl+Alt+V&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spotlight Quick Search:&lt;/strong&gt; &lt;code&gt;Ctrl+Alt+Space&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toggle Encrypted Vault:&lt;/strong&gt; &lt;code&gt;Ctrl+Shift+V&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Join the Community
&lt;/h2&gt;

&lt;p&gt;Whether you're on Arch, Debian, Ubuntu, Fedora, or Kali Linux — and whether you use GNOME, KDE, or Qtile — DotGhostBoard was built to give you total control and security over your clipboard.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⭐ Star the repo on &lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 Share feedback and submit feature requests via &lt;a href="https://github.com/kareem2099/DotGhostBoard/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 Check out our listing on &lt;a href="https://www.opendesktop.org/p/2353623/" rel="noopener noreferrer"&gt;OpenDesktop&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cerberus is ultimately about one principle: sensitive clipboard data should remain under the user's control — locally stored, explicitly protected, and never silently promoted to the network.&lt;/p&gt;

&lt;p&gt;Happy hacking and secure copying! 👻🔒&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>python</category>
      <category>security</category>
    </item>
    <item>
      <title>From Monolith to Modular Architecture: Refactoring a 2,353-Line PyQt6 Desktop App Without Regressions</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Wed, 16 Sep 2026 15:04:44 +0000</pubDate>
      <link>https://dev.to/freerave/from-monolith-to-modular-architecture-refactoring-a-2353-line-pyqt6-desktop-app-without-1jlo</link>
      <guid>https://dev.to/freerave/from-monolith-to-modular-architecture-refactoring-a-2353-line-pyqt6-desktop-app-without-1jlo</guid>
      <description>&lt;h2&gt;
  
  
  How we transformed DotGhostBoard from a monolithic desktop app into a decoupled, test-driven modular architecture — decomposing monolithic classes, isolating SQLite, and adding 86 tests with zero regressions.
&lt;/h2&gt;

&lt;p&gt;A 2,353-line &lt;code&gt;Dashboard&lt;/code&gt; class is rarely just a large file. It is usually a symptom that storage, business logic, security, synchronization, and UI behavior have all collapsed into the same boundary.&lt;/p&gt;

&lt;p&gt;That was the state of &lt;strong&gt;&lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;DotGhostBoard&lt;/a&gt;&lt;/strong&gt; v1.5 — an open-source, privacy-first clipboard manager for Linux built with Python and PyQt6.&lt;/p&gt;

&lt;p&gt;What began as a snappy, native desktop tool had accumulated layers of complexity: local AES-GCM encryption, dynamic database queries inside widget click handlers, regex secret detectors on keystrokes, and peer-to-peer LAN sync. Modifying a single button callback risked tripping up the entire Qt event loop.&lt;/p&gt;

&lt;p&gt;To prepare the codebase for its upcoming v2.0 milestone (native Wayland protocol support, end-to-end device sync, and extensible plugins), we undertook a comprehensive four-phase refactoring initiative.&lt;/p&gt;

&lt;p&gt;The outcome:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui/dashboard.py&lt;/code&gt; shrank from 2,353 to 1,535 lines (-35% LOC).&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The automated test suite expanded from 220 to 306 tests across 25 modules (+39% tests).&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The entire refactor passed the test suite with zero detected user-facing regressions.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the exact architectural blueprint, design patterns, and lessons learned.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛑 The "Before" Architecture: The Desktop App Debt Trap
&lt;/h2&gt;

&lt;p&gt;Desktop applications built with GUI frameworks like Qt, Tkinter, or wxWidgets are notoriously susceptible to the &lt;strong&gt;monolithic "Blob" antipattern&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ THE MONOLITHIC ARCHITECTURE ]
┌──────────────────────────────────────────────────────────────────┐
│ Dashboard (ui/dashboard.py) — 2,353 Lines                        │
│  - Raw SQL queries (`cursor.execute(...)`)                       │
│  - AES-GCM crypto encryption/decryption                          │
│  - Card widget lifecycle &amp;amp; pagination                            │
│  - LAN socket broadcasting                                       │
│  - Password prompt modals &amp;amp; session key caching                  │
└──────────────┬──────────────────┬─────────────────┬──────────────┘
               │                  │                 │
      Direct Storage Calls   Qt Event Loop    Tightly Bound Polling
               ▼                  ▼                 ▼
     [ Monolithic SQLite ]   [ UI Signals ]   [ QClipboard Event ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three critical pain points made future feature work fragile:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The 2,353-Line Monolithic Dashboard&lt;/strong&gt;: Button callbacks were directly reading from SQLite, instantiating cipher suites, managing session timers, and firing off network broadcasts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 1,100-Line Storage Monolith (&lt;code&gt;core/storage.py&lt;/code&gt;)&lt;/strong&gt;: One file handled connection lifecycle, schema migrations, clip CRUD, tag management, collection associations, and peer credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform-Tied Clipboard Listener&lt;/strong&gt;: Capturing clipboard data was tied directly to PyQt's &lt;code&gt;QClipboard.dataChanged&lt;/code&gt; event loop. Headless unit testing without an X11 display server was difficult, and supporting Wayland's native &lt;code&gt;wlr-data-control&lt;/code&gt; protocol was functionally impossible.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🎯 The Core Architectural Principle
&lt;/h2&gt;

&lt;p&gt;To untangle this, we established a strict rule of separation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Controllers coordinate UI behavior. Services own business rules. Repositories own persistence. Backends own platform integration.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UI (Widgets / Dialogs)
      │
      ▼
Controllers (ui/controllers/ - QObject Behavioral glue)
      │
      ▼
Services (core/services/ - Headless business logic)
      │
      ▼
Repositories (core/storage/repositories/ - Domain data access)
      │
      ▼
Database (core/storage/database.py - SQLite context &amp;amp; migrations)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Phase 1: Modularizing Storage with the Repository &amp;amp; Facade Patterns
&lt;/h2&gt;

&lt;p&gt;Rather than allowing UI components to issue raw SQL queries, we decomposed &lt;code&gt;core/storage.py&lt;/code&gt; into a focused package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;core/storage/
├── __init__.py           # 100% Backward-compatible Facade
├── database.py           # Context-managed connection layer &amp;amp; test paths
├── migrations.py         # Transactional schema migration engine
└── repositories/
    ├── clips.py          # CRUD, AES-256-GCM encryption, image deduplication
    ├── tags.py           # Normalization, tag extraction, rename/delete
    ├── collections.py    # Grouping, filtering, cascade rules
    ├── peers.py          # LAN device trust &amp;amp; credentials
    └── stats.py          # Aggregations &amp;amp; performance metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Backward-Compatible Facade Pattern
&lt;/h3&gt;

&lt;p&gt;A common blunder when refactoring persistence is forcing a sweeping rewrite across every caller at once. &lt;/p&gt;

&lt;p&gt;To keep Git diffs manageable and avoid breaking other branches, &lt;code&gt;core/storage/__init__.py&lt;/code&gt; serves as a facade, re-exporting original function signatures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/storage/__init__.py (Facade)
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.database&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;init_db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;close_db&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.repositories.clips&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;save_clip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_clips&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delete_clip&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.repositories.tags&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_all_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;normalize_tag&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.repositories.collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_collections&lt;/span&gt;

&lt;span class="c1"&gt;# Existing callers continued to function without changing an import!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Transactional Schema Migrations
&lt;/h3&gt;

&lt;p&gt;We implemented an in-house, zero-dependency migration engine (&lt;code&gt;core/storage/migrations.py&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every schema migration executes within an atomic transaction.&lt;/li&gt;
&lt;li&gt;Legacy schema detection auto-promotes pre-existing v1.5 databases.&lt;/li&gt;
&lt;li&gt;Includes downgrade guards to prevent older versions from corrupting newer schemas.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Phase 2: Decoupling the Clipboard Engine with Protocols
&lt;/h2&gt;

&lt;p&gt;Previously, the clipboard listener was embedded inside Qt widget callbacks. We extracted this into a headless policy engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Raw Clipboard Event ]
          │
          ▼
┌─────────────────────────────────────────────────────────────┐
│                 ClipboardPipeline (Pure Logic)              │
│                                                             │
│  1. Validation      ──► Ignore empty or malformed payloads  │
│  2. App Whitelist   ──► Filter out sensitive applications   │
│  3. Paranoia Filter ──► Check private browsing &amp;amp; incognito  │
│  4. Secret Detector ──► Scan for API keys, tokens, SSH keys │
└─────────────────────────────┬───────────────────────────────┘
                              │
                    CaptureDecision (Action)
                              │
          ┌───────────────────┼───────────────────┐
          ▼                   ▼                   ▼
    [ SAVE_NORMAL ]    [ SECRET_CANDIDATE ]    [ IGNORE ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Protocol-Based Backends
&lt;/h3&gt;

&lt;p&gt;By specifying a clean Python &lt;code&gt;typing.Protocol&lt;/code&gt;, the pipeline doesn't care whether events originate from X11, Qt, or Wayland:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# core/clipboard/backend.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.events&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ClipboardEvent&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClipboardBackend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;ClipboardEvent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_current_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We wrapped Qt's clipboard event handling into &lt;code&gt;QtClipboardBackend&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We introduced a lightweight &lt;code&gt;MockClipboardBackend&lt;/code&gt; for unit tests, enabling headless test execution in under 4 seconds without Xvfb.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wayland readiness&lt;/strong&gt;: The architecture is decoupled so a native Wayland backend can be introduced cleanly in v2.0.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Phase 3: Domain Service Layer &amp;amp; Cryptographic Hardening
&lt;/h2&gt;

&lt;p&gt;Desktop apps frequently leak business logic into UI event listeners. For instance, calculating whether a snippet should trigger an "Auto-Pin" recommendation based on copy frequency was embedded inside a widget slot.&lt;/p&gt;

&lt;p&gt;We extracted pure Python service classes into &lt;code&gt;core/services/&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HistoryService&lt;/code&gt;: Manages pagination windows, debounced search, duplicate suppression, and copy thresholds (&lt;code&gt;PIN_SUGGESTION_THRESHOLD = 5&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CollectionService&lt;/code&gt;: Handles categorization rules and cascade unlinking.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SecurityService&lt;/code&gt;: Manages master password verification, session lock timeouts, and key rotation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SyncService&lt;/code&gt;: Validates LAN peer trust handshakes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cryptographic Rigor &amp;amp; Envelope Encryption
&lt;/h3&gt;

&lt;p&gt;DotGhostBoard features an encrypted storage mode (&lt;strong&gt;The Vault&lt;/strong&gt;). We hardened key derivation and isolation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Two-Tier Key Derivation Chain&lt;/strong&gt;:
$$\text{Master Password} \xrightarrow{\text{PBKDF2-HMAC-SHA256 (600,000 iter + Salt)}} \text{Base Key} \xrightarrow{\text{HKDF-SHA256 (Domain Context)}} \text{Vault KEK}$$

&lt;ul&gt;
&lt;li&gt;Passwords first pass through &lt;strong&gt;PBKDF2-HMAC-SHA256&lt;/strong&gt; with 600,000 iterations and a persistent 256-bit random salt.&lt;/li&gt;
&lt;li&gt;The resulting base key is then fed through &lt;strong&gt;HKDF-SHA256&lt;/strong&gt; with domain context &lt;code&gt;b"dotghostboard:vault:v2"&lt;/code&gt;. This guarantees that the Vault key is cryptographically independent from other application keys.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Physical Database Isolation &amp;amp; Envelope Encryption&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Vault items live in a physically distinct SQLite database (&lt;code&gt;vault.db&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Items are encrypted using a fast Data Encryption Key (DEK). The DEK is encrypted with the Key Encryption Key (KEK).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant Password Rotation&lt;/strong&gt;: Changing the master password only requires re-wrapping the 32-byte DEK (a constant-time operation taking ~2ms in our local benchmarks), rather than re-encrypting gigabytes of history data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defense-in-Depth&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;secure_zero()&lt;/code&gt; providing &lt;strong&gt;best-effort memory scrubbing&lt;/strong&gt; for sensitive mutable &lt;code&gt;bytearray&lt;/code&gt; buffers after cryptographic operations.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Phase 4: Decomposing the 2,353-Line Monolithic Qt Dashboard
&lt;/h2&gt;

&lt;p&gt;Decomposing the central &lt;code&gt;Dashboard&lt;/code&gt; window was the most delicate step. &lt;/p&gt;

&lt;p&gt;Rather than letting the main window handle every event, we introduced &lt;strong&gt;Behavioral &lt;code&gt;QObject&lt;/code&gt; Controllers&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌────────────────────────┐
                    │       Dashboard        │
                    │  (ui/dashboard.py)     │
                    │   Layouts &amp;amp; Visuals    │
                    └───────────┬────────────┘
         ┌───────────────┬──────┴────────┬───────────────┐
         ▼               ▼               ▼               ▼
┌─────────────────┐ ┌──────────┐ ┌───────────────┐ ┌───────────┐
│HistoryController│ │Collection│ │SecurityContr. │ │SyncContr. │
│• Infinite scroll│ │• Sidebar │ │• Vault unlock │ │• LAN P2P  │
│• Search debounce│ │• Drag/drop│ │• Secret reveal│ │• Pairing  │
│• Card lifecycle │ │• Category│ │• Session timer│ │• Discovery│
└─────────────────┘ └──────────┘ └───────────────┘ └───────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each controller is a dedicated &lt;code&gt;QObject&lt;/code&gt; wired through dependency injection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HistoryController&lt;/code&gt;: Manages card pagination, card lifecycle, and 150ms search query debouncing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CollectionController&lt;/code&gt;: Manages category navigation, drag-and-drop targeting, and folder CRUD dialogs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SecurityController&lt;/code&gt;: Oversees session lock/unlock events, secret masking, and unlock prompts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SyncController&lt;/code&gt;: Coordinates peer discovery listings, pairing dialogs, and network status styling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Impact:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ui/dashboard.py&lt;/code&gt; shrank by 818 lines&lt;/strong&gt; (2,353 → 1,535 lines).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero raw SQL or crypto primitives remain in the UI layer.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Extracted &lt;code&gt;PinSuggestionToast&lt;/code&gt; into its own reusable widget module (&lt;code&gt;ui/widgets/pin_toast.py&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🐛 4 Subtle Bugs Discovered (and Fixed) During Refactoring
&lt;/h2&gt;

&lt;p&gt;A comprehensive refactor with high test coverage inevitably unearths long-standing subtle bugs:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Recursive Clipboard Sync Loop
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issue&lt;/strong&gt;: When a user clicked an existing snippet card in the GUI to copy it to their system clipboard, the clipboard watcher detected the change and triggered a LAN broadcast as if it were a new external capture, creating an infinite echo loop between paired devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix&lt;/strong&gt;: Enforced strict signal boundaries. The LAN sync broadcast is triggered &lt;em&gt;only&lt;/em&gt; by physical captures originating from &lt;code&gt;Watcher&lt;/code&gt;, never from internal UI card copy actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The $O(N)$ In-Memory Collection Calculation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issue&lt;/strong&gt;: Populating collection card counts loaded the entire history table into Python and computed counts using list comprehensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix&lt;/strong&gt;: Replaced with a single SQL query utilizing &lt;code&gt;LEFT JOIN&lt;/code&gt; and &lt;code&gt;COUNT(clips.id) GROUP BY collections.id&lt;/code&gt;, slashing dashboard initialization time from ~210ms to under 8ms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. N+1 Deletes in Periodic Cleanup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issue&lt;/strong&gt;: The routine cleaning old clips performed individual &lt;code&gt;DELETE FROM clips WHERE id = ?&lt;/code&gt; calls inside a Python iteration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix&lt;/strong&gt;: Refactored to bulk &lt;code&gt;DELETE FROM clips WHERE id IN (...)&lt;/code&gt; executed inside a single transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Encapsulation Leaks in Session Management
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issue&lt;/strong&gt;: Widgets were directly reading and mutating private session key attributes across controller instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix&lt;/strong&gt;: Replaced with a validated &lt;code&gt;set_session_key()&lt;/code&gt; public method enforcing explicit lifecycle transitions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📊 Before vs. After: Metrics
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before (v1.5.7)&lt;/th&gt;
&lt;th&gt;After (v1.6.0 Phantom)&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dashboard File Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2,353 lines&lt;/td&gt;
&lt;td&gt;1,535 lines&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;-35% LOC (-818 lines)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage Architecture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1 Monolithic File&lt;/td&gt;
&lt;td&gt;7 Decoupled Modules&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Repository Pattern + Facade&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automated Tests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;220 tests&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;306 tests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+39% tests (+86 tests across 25 modules)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Test Execution Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;14.2s (with Qt displays)&lt;/td&gt;
&lt;td&gt;3.8s (Mock Backends)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.7x faster test execution&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User-Facing Regressions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0 detected regressions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Verified via test suite &amp;amp; manual pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Wayland Readiness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Qt-coupled&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Protocol-abstracted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Architecture prepared for native backend&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📐 How We Measured
&lt;/h2&gt;

&lt;p&gt;To ensure our metrics were empirical and reproducible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lines of Code&lt;/strong&gt;: Measured using &lt;code&gt;cloc&lt;/code&gt; excluding comments, docstrings, and blank lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Counts &amp;amp; Speed&lt;/strong&gt;: Measured via &lt;code&gt;pytest&lt;/code&gt; run times on an identical Ubuntu 24.04 environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Latencies&lt;/strong&gt;: Profiled with &lt;code&gt;sqlite3&lt;/code&gt; &lt;code&gt;EXPLAIN QUERY PLAN&lt;/code&gt; and Python's &lt;code&gt;time.perf_counter_ns()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regression Verification&lt;/strong&gt;: Confirmed across 306 automated unit/integration tests and a full manual smoke test on X11 and Wayland sessions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Key Takeaways for Refactoring Desktop Apps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Do Not Start Refactoring Without a Fast Safety Net&lt;/strong&gt;:
Our initial 220-test suite gave us a fast safety net and exposed breaking changes as the refactor progressed. Build your test harness &lt;em&gt;before&lt;/em&gt; you touch architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Facades to Keep PRs Manageable&lt;/strong&gt;:
Maintain backwards compatibility at module boundaries. Your refactoring doesn't need to break every import path simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decouple Event Loops from Business Logic&lt;/strong&gt;:
Never let UI event loops govern application state. Pure Python classes with &lt;code&gt;Protocol&lt;/code&gt; definitions make your business logic portable, maintainable, and lightning-fast to test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolate Signal Flow Early&lt;/strong&gt;:
GUI architectures crumble when signals cascade unpredictably. Define explicit component boundaries for what generates data versus what consumes it.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 What's Next?
&lt;/h2&gt;

&lt;p&gt;With the architecture of &lt;strong&gt;DotGhostBoard v1.6.0 "Phantom"&lt;/strong&gt; stabilized, we are actively developing the &lt;strong&gt;v2.0.0 "Cerberus"&lt;/strong&gt; roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native Wayland clipboard engine (&lt;code&gt;wlr-data-control&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Authenticated peer-to-peer device sync.&lt;/li&gt;
&lt;li&gt;Extension and plugin system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔗 Links &amp;amp; Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;Download v1.6.0 "Phantom"&lt;/strong&gt;: &lt;a href="https://github.com/kareem2099/DotGhostBoard/releases/tag/v1.6.0" rel="noopener noreferrer"&gt;GitHub Release (AppImage, .deb, Arch)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;OpenDesktop / Pling Store&lt;/strong&gt;: &lt;a href="https://www.opendesktop.org/p/2353623/" rel="noopener noreferrer"&gt;DotGhostBoard on OpenDesktop&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⭐ &lt;strong&gt;Source Code &amp;amp; Documentation&lt;/strong&gt;: &lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Have you ever refactored a monolithic desktop application? What patterns helped you untangle complex legacy UI code? Share your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>architecture</category>
      <category>opensource</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>When "Fast" Became the Only Rule</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Sun, 06 Sep 2026 12:37:37 +0000</pubDate>
      <link>https://dev.to/freerave/when-fast-became-the-only-rule-3p8f</link>
      <guid>https://dev.to/freerave/when-fast-became-the-only-rule-3p8f</guid>
      <description>&lt;h2&gt;
  
  
  A developer's honest look at what really changed between the Roadmap era and the "ship it in five minutes" era — and why the real cost isn't hours worked, it's fragmented attention.
&lt;/h2&gt;

&lt;p&gt;It's almost 1 AM. The screen is still on, and I've been staring at the same line of code for ten minutes. Not because it's complicated — no, because my brain is just empty. Then a message pops up: "Cool, but can we drop this feature and swap in something else? We need it fast."&lt;/p&gt;

&lt;p&gt;Fast. How fast? Five minutes.&lt;/p&gt;

&lt;p&gt;I'm not exaggerating — this has become a daily shape of my work. And every time I sit with it, I realize the real problem isn't the feature or the code. It's something else entirely: we're working in an era that forgot how to wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back Then: There Was Room for Patience
&lt;/h2&gt;

&lt;p&gt;I remember when I was starting out, there was this thing called a "roadmap." You'd specialize, read, struggle, fail, try again, and after a couple of months you'd actually feel like you'd made progress. I specialized in just Next.js and Python, and that wasn't a flaw — it was the natural path. Go deep on one thing until you master it, then expand.&lt;/p&gt;

&lt;p&gt;Even at work, if I changed something small in the UI, it counted as an achievement. Changing a button's look got called "amazing work," even though in reality it was light work. I'd be doing frontend and somehow it felt like I'd shipped an entire backend. Change used to happen once a month, and that was enough to make noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now: Everything Has to "Explode" Every 12 Hours
&lt;/h2&gt;

&lt;p&gt;Today the picture has completely flipped. Same hours, same effort, but the rhythm changed entirely. There's now an expectation that you ship something "huge" every half a day. Not an update, not an improvement — something that wows. And if what you shipped was light or simple, in the client's eyes you're suddenly a "bad developer," even if the task genuinely didn't need more than that.&lt;/p&gt;

&lt;p&gt;The strange part is that a lot of the market feels increasingly iterative rather than genuinely innovative — companies keep circling similar ideas while the expected shipping speed keeps rising. Even big companies now ship products fast and patch the bugs later, on the fly, because nobody wants to wait.&lt;/p&gt;

&lt;p&gt;The result? Your client sees that model and expects the same speed from their small project, without understanding that not everything is the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Tires Me Out Isn't the Work — It's the Constant Urgency
&lt;/h2&gt;

&lt;p&gt;This is the point I most want to get across. The technical effort itself isn't the problem. The problem is working inside an environment with zero patience. You're expected to add a feature and remove it in under five minutes, as if the system were a light switch you flip on and off. But what actually happens is that every "add and remove" shakes other things inside the architecture, affects things you didn't anticipate, and the system starts wearing down from constant changes with no real foundation behind them.&lt;/p&gt;

&lt;p&gt;Then comes the question the client throws at you: "You're using AI, why would you even be tired?"&lt;/p&gt;

&lt;p&gt;That question genuinely hurts, because it comes from a real misunderstanding. AI can cut down how long something takes to write — it doesn't remove the responsibility for deciding what to write. &lt;strong&gt;AI can accelerate execution. It cannot absorb accountability.&lt;/strong&gt; If something breaks in production, the client isn't going to go argue with a model — I'm the one holding the consequence of that call. My eyes get tired from the screen, and my brain gets tired from constantly switching between decision and decision — that's real fatigue even if my body never moved. Tiredness isn't always physical; sometimes it's nerve fatigue, and that's the kind nobody sees unless they're the one living it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI made code cheaper to produce. It didn't make change cheaper to understand.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Helped Me Survive This Workflow
&lt;/h2&gt;

&lt;p&gt;I won't pretend I have a silver-bullet answer, but a few things have actually reduced the pressure for me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Draw a clear, spoken line between a "light touch" and a "core change."&lt;/strong&gt; When someone asks to swap a feature out for another, calmly explain that this isn't a light switch — it takes time to make sure the system doesn't break. Transparency here protects you more than anything else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Try to batch scattered requests instead of reacting to each one instantly.&lt;/strong&gt; Instead of replying the moment a message lands, suggest that requests get grouped and prioritized, even informally. It gives you thinking space instead of constant reflex-mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use feature flags instead of directly ripping code in and out.&lt;/strong&gt; This lets you "turn off" or "turn on" something without touching the foundation, and it actually saves real time and effort down the line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Say "no" professionally when a request doesn't make sense.&lt;/strong&gt; You don't have to agree to everything just because the client is in a hurry. Explain what rushing would actually cost, and let them make the call with the full picture in front of them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Protect your time without guilt.&lt;/strong&gt; You don't have to respond outside working hours just because a message arrived. A quick "I'll look at this in the morning" beats a rushed decision made at 1 AM.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing: Speed Isn't the Problem — Treating Patience as a Luxury Is
&lt;/h2&gt;

&lt;p&gt;I'm not saying speed is a bad thing, or that every impatient client is wrong. The market genuinely changed, and expectations changed with it. But there's a real difference between "speed" and "urgency without understanding." Speed needs structure. Urgency just needs a little patience so nobody gets burned out.&lt;/p&gt;

&lt;p&gt;At the end of the day, I can still end up at my desk from around 9 AM to 1 AM — not something I'd call healthy or sustainable, just an honest description of where I am right now. But the strange part is that the number of hours isn't really what changed. The fragmentation did: back then those hours were long, connected stretches of exploring and learning; now they're broken into reactions, all day, to whatever just landed in the chat. Maybe that's the real challenge for developers in this era: not learning some new technology, but learning how to protect your attention — and your sanity — around people who forgot how to wait.&lt;/p&gt;

&lt;p&gt;Have you dealt with something like this? How do you handle an impatient client who won't give you room to breathe? Let me know in the comments 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Inside DotFetch v2.1.0: Auth Boundaries, WebView Security, and Request Architecture</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Thu, 20 Aug 2026 14:05:17 +0000</pubDate>
      <link>https://dev.to/freerave/inside-dotfetch-v210-auth-boundaries-webview-security-and-request-architecture-4knf</link>
      <guid>https://dev.to/freerave/inside-dotfetch-v210-auth-boundaries-webview-security-and-request-architecture-4knf</guid>
      <description>&lt;p&gt;A deep dive into building DotFetch v2.1.0: Modular architecture in VS Code WebViews, RFC 6749 OAuth 2.0, backend-owned Basic Auth with environment variables, and safe credential isolation.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Context Switching Problem
&lt;/h2&gt;

&lt;p&gt;Context switching is one of the most frustrating parts of building backend services.&lt;/p&gt;

&lt;p&gt;Every time you write an API endpoint in VS Code, you switch windows to a standalone API client, wait for it to load, configure environment variables, run the request, and switch back to your editor.&lt;/p&gt;

&lt;p&gt;We created &lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotfetch" rel="noopener noreferrer"&gt;DotFetch&lt;/a&gt;&lt;/strong&gt; to bring a lightweight, dark-themed HTTP client directly into your VS Code workspace — native &lt;code&gt;.env&lt;/code&gt; variable support, collections, cURL import/export, and zero UI bloat.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;v2.0.0&lt;/strong&gt;, we built the initial request builder with structured parameter and header tables.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;v2.1.0&lt;/strong&gt;, our focus shifted to engineering &lt;strong&gt;a hardened authentication and security layer designed for real-world API workflows&lt;/strong&gt;. The challenge was resolving the architectural edge cases that appeared once authentication, persistence, and environment substitution started interacting.&lt;/p&gt;

&lt;p&gt;Here is an inside look at how we designed and refactored &lt;strong&gt;DotFetch v2.1.0&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ 1. Architecture: Modular Frontend in a Sandboxed WebView
&lt;/h2&gt;

&lt;p&gt;A common problem in VS Code extension development is stuffing DOM manipulation, business logic, and IPC handling into a single monolithic script.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;DotFetch v2.1.0&lt;/strong&gt;, we structured the frontend into an &lt;strong&gt;MVC-inspired modular frontend architecture&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DotFetch Architecture
├── Extension Host (Node.js Runtime)
│   ├── RequestService.ts       ← Axios execution engine, SSL Agent, OAuth token fetcher
│   ├── DataManager.ts          ← globalState persistence (History &amp;amp; Collections)
│   ├── EnvironmentManager.ts   ← .env parsing &amp;amp; {{VAR}} substitution
│   └── webviewPanel.ts         ← IPC Message Router &amp;amp; CSP builder
│
└── Frontend WebView (Browser Runtime - src/webview/)
    ├── main.js                 ← Central Controller &amp;amp; event dispatcher
    ├── request.js              ← Form state, live assembly &amp;amp; send logic
    ├── auth.js                 ← Auth rendering, live previews &amp;amp; RFC validation
    ├── ui.js                   ← Structured tables, response tabs &amp;amp; badges
    ├── shortcuts.js            ← Configurable keyboard shortcuts
    ├── state.js                ← Single source of truth &amp;amp; canonical schemas
    └── api.js                  ← postMessage transport layer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Bundling Strategy under Strict CSP
&lt;/h3&gt;

&lt;p&gt;DotFetch applies a strict Content-Security-Policy to its VS Code WebView, using nonce-based script execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Content-Security-Policy"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"default-src 'none'; script-src 'nonce-${nonce}'; ..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bundling simplifies WebView resource loading and CSP management while keeping the source code modular during development.&lt;/p&gt;

&lt;p&gt;We maintain clean ES modules in &lt;code&gt;src/webview/&lt;/code&gt; during development, and use &lt;code&gt;esbuild&lt;/code&gt; to bundle &lt;code&gt;src/webview/main.js&lt;/code&gt; into a single &lt;strong&gt;IIFE bundle&lt;/strong&gt; (&lt;code&gt;media/script.js&lt;/code&gt;) in &lt;strong&gt;~30ms local build time in our development setup&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"esbuild-base"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node &amp;amp;&amp;amp; esbuild ./src/webview/main.js --bundle --outfile=media/script.js --format=iife --platform=browser"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the codebase modular and readable in source control while shipping a single, CSP-compliant script at runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 2. The Authentication Suite
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔑 API Key Authentication (Header vs. Query Mode)
&lt;/h3&gt;

&lt;p&gt;APIs accept keys differently. Some require custom HTTP headers (&lt;code&gt;X-API-Key: secret&lt;/code&gt;), while others expect query parameters (&lt;code&gt;?api_key=secret&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;We built an interactive UI that lets developers switch modes with real-time visual previews and a copy button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/webview/auth.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateApiKeyPreview&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keyName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyName&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyValue&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keyIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyIn&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keyName&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;keyValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keyIn&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;keyName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;keyValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`?&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;keyName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;keyValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt;&amp;lt;button type="button" class="tool-btn" id="copy-auth-preview"&amp;gt;Copy&amp;lt;/button&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdtk2qb6ycewue5kbytwq.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%2Fdtk2qb6ycewue5kbytwq.png" alt="API Key auth with real-time masked header preview and instant response inspection." width="800" height="830"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When sent in &lt;strong&gt;Query Parameter mode&lt;/strong&gt;, the headers table remains untouched and &lt;code&gt;RequestService&lt;/code&gt; injects the key into the URL string on the Node.js side right before execution.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚡ OAuth 2.0 (Client Credentials Flow)
&lt;/h3&gt;

&lt;p&gt;Machine-to-machine APIs (Spotify, Twitch, Azure, Auth0) frequently rely on OAuth 2.0 Client Credentials.&lt;/p&gt;

&lt;p&gt;Instead of writing separate shell scripts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter your &lt;code&gt;Token URL&lt;/code&gt;, &lt;code&gt;Client ID&lt;/code&gt;, &lt;code&gt;Client Secret&lt;/code&gt;, and &lt;code&gt;Scope&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"⚡ Fetch &amp;amp; Inject Token"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;DotFetch contacts the OAuth provider, extracts the &lt;code&gt;access_token&lt;/code&gt;, displays an active token status card with expiration metadata, and injects &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt; into your live requests.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/requestService.ts - RFC 6749 §2.3.1 Compliance&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetchOAuthToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;webview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Webview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environmentManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substituteVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clientId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environmentManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substituteVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clientSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environmentManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substituteVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environmentManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substituteVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;grant_type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;client_credentials&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scope&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// RFC 6749 §2.3.1: client_id &amp;amp; client_secret MUST be URL-encoded before Base64 encoding&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formEncode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/%20/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;basicCreds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;formEncode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;formEncode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Basic &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;basicCreds&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// Returns access_token, token_type, expires_in to WebView...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwiamvevkfx726v8d1l0d.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%2Fwiamvevkfx726v8d1l0d.png" alt="OAuth 2.0 Token Fetching with active token card, expiry tracking, and toast feedback" width="800" height="830"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🛡️ SSL/TLS Toggle for Local Development
&lt;/h3&gt;

&lt;p&gt;When testing microservices locally with self-signed SSL certificates (&lt;code&gt;https://localhost:8080&lt;/code&gt;), Node.js rejects the connection with certificate verification errors.&lt;/p&gt;

&lt;p&gt;DotFetch v2.1.0 provides an &lt;strong&gt;SSL Toggle&lt;/strong&gt; with a prominent toolbar warning badge (&lt;code&gt;⚠️ SSL Ignored&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpsAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sslVerify&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;rejectUnauthorized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To prevent accidental security gaps, every request load enforces a &lt;strong&gt;secure default&lt;/strong&gt; (&lt;code&gt;sslVerify: true&lt;/code&gt;).&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%2F6g0332ytkh6effy1g32q.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%2F6g0332ytkh6effy1g32q.png" alt="SSL/TLS verification toggle with active toolbar warning badge and self-signed localhost 200 OK response" width="800" height="830"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ 3. Solving the Hard Architectural Edge Cases
&lt;/h2&gt;

&lt;p&gt;The auth features were straightforward. The difficult part was keeping authentication, persistence, and request execution from contaminating each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧩 1. The "Draft vs. Wire" Headers Contamination
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; When you send a request with Bearer Auth, the client injects &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt; into the outgoing wire headers. If the user clicked &lt;strong&gt;"Save to Collection"&lt;/strong&gt;, that injected header was saved into the raw headers table. Later, loading that request and switching to "No Auth" caused the old token to remain in manual headers and still be sent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; We decoupled &lt;strong&gt;Draft Data&lt;/strong&gt; (for storage) from &lt;strong&gt;Wire Data&lt;/strong&gt; (for execution):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/webview/request.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getRequestData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;forSend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;serializeHeaders&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Wire headers get auth injection; Saved draft headers stay clean&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;forSend&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;applyAuthHeaderToRawHeaders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawHeaders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rawHeaders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Live send keeps in-memory secrets; Storage strips them&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;forSend&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createPersistableAuthConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;constructFullUrl&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;sslVerify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sslVerify&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧩 2. Basic Auth + Environment Variables Base64 Deadlock
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; The UI allows &lt;code&gt;Username: {{API_USER}}&lt;/code&gt; and &lt;code&gt;Password: {{API_PASS}}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the WebView constructs &lt;code&gt;Authorization: Basic ${btoa(&lt;/code&gt;${user}:${pass}&lt;code&gt;)}&lt;/code&gt;, it produces Base64 ciphertext of the literal string &lt;code&gt;{{API_USER}}:{{API_PASS}}&lt;/code&gt;. When the Extension Host receives it, it cannot substitute the environment variables because they are locked inside Base64.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Make Basic Auth &lt;strong&gt;100% Backend-Owned&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The WebView strips any conflicting manual &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RequestService&lt;/code&gt; on the Extension Host performs variable substitution &lt;em&gt;first&lt;/em&gt;, and &lt;em&gt;then&lt;/em&gt; computes the Base64 header in Node.js runtime:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/requestService.ts&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;basic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawPass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environmentManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substituteVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectedEnv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environmentManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substituteVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawPass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectedEnv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;basicCreds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;substitutedHeaders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Basic &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;basicCreds&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧩 3. Zero-Persistence Plaintext Secrets across Collections, Favorites &amp;amp; History
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; &lt;code&gt;vscode.ExtensionContext.globalState&lt;/code&gt; is used for persisting collections and history. Storing raw passwords, tokens, API key values, or OAuth secrets as plaintext JSON in globalState is an unnecessary security risk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Plaintext runtime credentials are stripped before DotFetch persists request metadata to globalState across Collections, Favorites, and History:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/webview/state.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createPersistableAuthConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;keyValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tokenReceivedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a request executes, &lt;code&gt;sendRequest()&lt;/code&gt; passes both &lt;code&gt;requestData&lt;/code&gt; (live wire credentials) and &lt;code&gt;historyData&lt;/code&gt; (sanitized snapshot). On success, &lt;code&gt;webviewPanel.ts&lt;/code&gt; persists only the sanitized snapshot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/webviewPanel.ts&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;capturedResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;safeRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;historyData&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;historyEntry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;safeRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;safeRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;safeRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Clean manual headers&lt;/span&gt;
        &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;safeRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// Stripped secrets&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;capturedResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;capturedResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;historyEntry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧩 4. Guarding Against Memory-Exploding Payloads
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; If an API endpoint returns a 50MB JSON payload, transferring that full payload across the VS Code &lt;code&gt;postMessage&lt;/code&gt; IPC boundary will freeze the WebView and lag the editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; We implemented double-layered response protection:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Network Layer:&lt;/strong&gt; Axios enforces &lt;code&gt;maxContentLength: 10 * 1024 * 1024&lt;/code&gt; (10 MB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Display Layer:&lt;/strong&gt; If the response exceeds 1 MB (&lt;code&gt;DISPLAY_THRESHOLD&lt;/code&gt;), we compute accurate UTF-8 byte length via &lt;code&gt;Buffer.byteLength()&lt;/code&gt; and truncate the WebView preview to the first 1000 characters with a helpful badge:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/requestService.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serializedResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responseSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;byteLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serializedResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLarge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;responseSize&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;RequestService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DISPLAY_THRESHOLD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;webview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responseSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isLarge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isLarge&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`[Response too large: &lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;responseSize&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; KB]\n\nFirst 1000 characters:\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;serializedResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;...`&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 4. How We Verified It
&lt;/h2&gt;

&lt;p&gt;Before tagging v2.1.0, we run our quality gates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm run compile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm run typecheck&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm run lint&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then we validate the runtime test matrix manually across scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Auth&lt;/strong&gt;: Raw headers sent unchanged; no injected tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic Auth (Literal)&lt;/strong&gt;: Safe UTF-8 Base64 encoding; manual headers overridden&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic Auth (Variables)&lt;/strong&gt;: &lt;code&gt;{{USER}}&lt;/code&gt; &amp;amp; &lt;code&gt;{{PASS}}&lt;/code&gt; substituted before Base64&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bearer Token&lt;/strong&gt;: Injected on wire only; excluded from saved collections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Key (Header)&lt;/strong&gt;: Custom header injection; live preview works&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Key (Query)&lt;/strong&gt;: Injected into URL query string; headers table untouched&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth 2.0 Flow&lt;/strong&gt;: RFC 6749 URL encoding; active token card display; expired token blocks send&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save &amp;amp; Reload&lt;/strong&gt;: Schema restored cleanly; zero header contamination&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;History Sanitization&lt;/strong&gt;: Plaintext secrets omitted from globalState&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL Toggle&lt;/strong&gt;: Localhost bypasses SSL when disabled with active warning badge&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Guard&lt;/strong&gt;: Payloads &amp;gt; 1MB safely truncated in preview&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cancel &amp;amp; Retry&lt;/strong&gt;: AbortController halts execution; network retry with exponential backoff&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📊 Summary of What DotFetch v2.1.0 Delivers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature Area&lt;/th&gt;
&lt;th&gt;What You Get&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bearer Token, Basic Auth (env-aware), API Key (Header &amp;amp; Query), OAuth 2.0 Client Credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UI &amp;amp; Visibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Interactive eye toggles (👁️ / 🙈), Response Headers Inspector table, Live previews&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security &amp;amp; Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Zero-persistence plaintext secret policy across Collections, Favorites &amp;amp; History, SSL Toggle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10MB payload size limits, 1MB large response truncation, modular WebView source bundled into a single CSP-compatible runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code Health&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Zero TypeScript typecheck errors, strict ESLint pass, clean IPC separation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🚀 Try DotFetch
&lt;/h2&gt;

&lt;p&gt;DotFetch is free, open-source, and built for developers who appreciate clean tools.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;📦 &lt;strong&gt;VS Code Marketplace:&lt;/strong&gt; &lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotfetch" rel="noopener noreferrer"&gt;Install DotFetch&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🌐 &lt;strong&gt;Open VSX Registry:&lt;/strong&gt; &lt;a href="https://open-vsx.org/extension/freerave/dotfetch" rel="noopener noreferrer"&gt;Install DotFetch&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⭐ &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotFetch" rel="noopener noreferrer"&gt;kareem2099/DotFetch&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Have feedback or feature suggestions for v2.2? Drop a comment below or open an issue on GitHub!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>vscode</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Building DotGhostBoard v1.5.5: Spotlight Search, SHA-256 Image Deduplication &amp; Zero-Trust Clipboard Security in PyQt6</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Thu, 06 Aug 2026 13:31:27 +0000</pubDate>
      <link>https://dev.to/freerave/building-dotghostboard-v155-spotlight-search-sha-256-image-deduplication-zero-trust-clipboard-2b11</link>
      <guid>https://dev.to/freerave/building-dotghostboard-v155-spotlight-search-sha-256-image-deduplication-zero-trust-clipboard-2b11</guid>
      <description>&lt;h2&gt;
  
  
  How we built a Kali Linux-native, privacy-first clipboard manager featuring a floating Spotlight search overlay (Ctrl+Shift+F), smart image hashing, search input debouncing, and Master Password security.
&lt;/h2&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%2Fuc8rt3sczn7fnd7hbmkg.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%2Fuc8rt3sczn7fnd7hbmkg.png" alt="DotGhostBoard v1.5.5 Hero Dashboard" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was working on Kali Linux, taking multiple screenshot captures of terminal error tracebacks and copying temporary API bearer tokens, when I realized two frustrating things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My disk was getting littered with dozens of duplicate PNG screenshots (&lt;code&gt;capture_1427.png&lt;/code&gt;, &lt;code&gt;capture_1428.png&lt;/code&gt;) taking up space and cluttering my feed.&lt;/li&gt;
&lt;li&gt;The clipboard managers available on Linux were either heavy Electron apps devouring 350MB+ RAM just sitting in the tray, or basic plain-text loggers that stored sensitive API keys unencrypted on disk.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's why we built &lt;strong&gt;&lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;DotGhostBoard&lt;/a&gt;&lt;/strong&gt; — a Kali Linux-native, privacy-first, zero-trust clipboard manager built with &lt;strong&gt;Python 3&lt;/strong&gt; and &lt;strong&gt;PyQt6&lt;/strong&gt;. It features AES-256-GCM encryption, local SQLite storage, global hotkey overlays, and a dark neon aesthetic — using ~85 MB of Full Runtime RAM.&lt;/p&gt;

&lt;p&gt;In this article, we'll dive deep into the architecture, design choices, and &lt;strong&gt;actual Python code&lt;/strong&gt; behind the new features introduced in &lt;strong&gt;v1.5.5 (Nexus Polish &amp;amp; Spotlight)&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Key Features Introduced in v1.5.5
&lt;/h2&gt;

&lt;p&gt;Here is what we engineered for this release:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Spotlight Quick Search Overlay (&lt;code&gt;ui/spotlight.py&lt;/code&gt;)&lt;/strong&gt;: A frameless, floating quick-search popup accessible globally via &lt;code&gt;Ctrl+Shift+F&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🖼️ &lt;strong&gt;Smart Image SHA-256 Deduplication (&lt;code&gt;core/storage.py&lt;/code&gt;)&lt;/strong&gt;: Automatic pixel hashing that prevents duplicate screenshots from cluttering disk space or UI feeds.&lt;/li&gt;
&lt;li&gt;🔐 &lt;strong&gt;Master Password Protection for Secret Copying (&lt;code&gt;ui/dashboard.py&lt;/code&gt;)&lt;/strong&gt;: Zero-leak in-memory decryption for encrypted clipboard items.&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Search Input Debouncing (&lt;code&gt;QTimer&lt;/code&gt;)&lt;/strong&gt;: 150ms–200ms non-blocking debounce timers to eliminate UI lag during rapid typing.&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Dashboard Stats Header &amp;amp; Relative Time Refresh&lt;/strong&gt;: Real-time state summary banner and relative timestamps ("just now", "5m ago", "2h ago").&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Spotlight Quick Search Overlay (&lt;code&gt;ui/spotlight.py&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;A core goal of v1.5.5 was allowing users to query their clipboard history from &lt;strong&gt;any application&lt;/strong&gt; without switching windows manually.&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%2Frmjm637ewn1vvvnkdtnk.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%2Frmjm637ewn1vvvnkdtnk.png" alt="Spotlight Quick Search Overlay (Ctrl+Shift+F)" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We designed &lt;code&gt;SpotlightSearchDialog&lt;/code&gt; using PyQt6's &lt;code&gt;QDialog&lt;/code&gt; with frameless window hints and active screen auto-centering:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub Source Code:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/blob/main/ui/spotlight.py" rel="noopener noreferrer"&gt;&lt;code&gt;ui/spotlight.py&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PyQt6.QtWidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;QDialog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QVBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLineEdit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QListWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;QListWidgetItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QHBoxLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;QApplication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QGraphicsDropShadowEffect&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PyQt6.QtCore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pyqtSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QTimer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PyQt6.QtGui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QKeyEvent&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SpotlightSearchDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QDialog&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Spotlight-style floating search overlay.
    - Frameless, stays on top, centered on active monitor.
    - Up / Down / Enter keyboard navigation.
    - Emits sig_item_selected(item) when user picks an item.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;sig_item_selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pyqtSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setWindowFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WindowType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FramelessWindowHint&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WindowType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WindowStaysOnTopHint&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WindowType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tool&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WidgetAttribute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WA_TranslucentBackground&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFixedWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;640&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFixedHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;420&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pending_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

        &lt;span class="c1"&gt;# 150ms search debounce timer
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSingleShot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_do_search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_build_ui&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_center_on_screen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keyboard Navigation &amp;amp; Focus Loss
&lt;/h3&gt;

&lt;p&gt;To make Spotlight feel as smooth as macOS Spotlight or Raycast:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;eventFilter&lt;/code&gt; captures &lt;code&gt;Up&lt;/code&gt;, &lt;code&gt;Down&lt;/code&gt;, &lt;code&gt;Enter&lt;/code&gt;, and &lt;code&gt;Esc&lt;/code&gt; keys regardless of whether focus is on the &lt;code&gt;QLineEdit&lt;/code&gt; or &lt;code&gt;QListWidget&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Encrypted secret items (&lt;code&gt;is_secret == 1&lt;/code&gt;) are masked with &lt;code&gt;🔒 Secret Item (Encrypted)&lt;/code&gt; to prevent sensitive data leaks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;changeEvent&lt;/code&gt; listens for &lt;code&gt;ActivationChange&lt;/code&gt; to automatically hide Spotlight when the user clicks outside.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;eventFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;QEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KeyPress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;QKeyEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;
            &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key_Escape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key_Down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentRow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCurrentRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key_Up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentRow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCurrentRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key_Return&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key_Enter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;current_item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentItem&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_on_item_activated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;eventFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;changeEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;QEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ActivationChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isActiveWindow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;changeEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Smart Image Deduplication via SHA-256 (&lt;code&gt;core/storage.py&lt;/code&gt;)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;When capturing screenshots or images from the system clipboard, &lt;code&gt;QImage.save()&lt;/code&gt; creates a new temporary PNG file (e.g., &lt;code&gt;capture_20260805_142748.png&lt;/code&gt;). Because each file gets a timestamped path, traditional string matching (&lt;code&gt;WHERE content = ?&lt;/code&gt;) fails to recognize identical images. This led to duplicate cards filling the dashboard and wasting disk space.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: SHA-256 Image Hashing
&lt;/h3&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%2Fx7p8l58vdnmg53k4gf1y.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%2Fx7p8l58vdnmg53k4gf1y.png" alt="Image SHA-256 Deduplication Feed" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;storage.add_item()&lt;/code&gt;, when an image is saved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compute the SHA-256 checksum of the new PNG file.&lt;/li&gt;
&lt;li&gt;Query existing &lt;code&gt;image&lt;/code&gt; rows in SQLite.&lt;/li&gt;
&lt;li&gt;If an existing image has the exact same SHA-256 hash:

&lt;ul&gt;
&lt;li&gt;Purge the newly generated temporary PNG file from disk (&lt;code&gt;os.remove()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Execute &lt;code&gt;UPDATE clipboard_items SET updated_at = NOW, copy_count = copy_count + 1 WHERE id = ?&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Return the existing item ID so the UI floats the original image card to the top with an updated frequency badge (&lt;code&gt;×2&lt;/code&gt;, &lt;code&gt;×3&lt;/code&gt;, &lt;code&gt;🔥 ×10&lt;/code&gt;)!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub Source Code:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/blob/main/core/storage.py" rel="noopener noreferrer"&gt;&lt;code&gt;core/storage.py&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_file_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate SHA-256 hash of a file for image duplicate detection.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Add a new item to the database using a 3-stage cascade for optimal performance:
    - Stage 1: Fast O(1) string match (avoids unnecessary disk IO).
    - Stage 2: SHA-256 pixel hash match for images (resolves timestamped file duplicates).
    - Stage 3: Clean SQL insertion for brand new unique items.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# ── STAGE 1: Direct Content Match ──
&lt;/span&gt;    &lt;span class="c1"&gt;# Check text strings or identical paths first. This is an immediate SQL lookup,
&lt;/span&gt;    &lt;span class="c1"&gt;# avoiding heavy disk reads if the exact same text or path was already recorded.
&lt;/span&gt;    &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_item_by_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPDATE clipboard_items SET updated_at = ?, copy_count = copy_count + 1 WHERE id = ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# ── STAGE 2: SHA-256 Image Content Hash Match ──
&lt;/span&gt;    &lt;span class="c1"&gt;# If content paths differ (e.g. capture_1001.png vs capture_1002.png), compare actual pixel hashes.
&lt;/span&gt;    &lt;span class="c1"&gt;# We filter by file size first (os.path.getsize) to avoid computing SHA-256 on non-matching sizes!
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;new_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_get_file_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;new_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getsize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT id, content FROM clipboard_items WHERE type = &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; ORDER BY updated_at DESC LIMIT 100&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;existing_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing_path&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;existing_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="c1"&gt;# Fast pre-check: Compare file size before hashing disk bytes
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getsize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;existing_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;new_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;_get_file_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;existing_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;new_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                            &lt;span class="c1"&gt;# Duplicate image pixels detected! Delete the new redundant temporary file
&lt;/span&gt;                            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="k"&gt;pass&lt;/span&gt;

                            &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPDATE clipboard_items SET updated_at = ?, copy_count = copy_count + 1 WHERE id = ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                                &lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# ── STAGE 3: New Unique Item Insertion ──
&lt;/span&gt;    &lt;span class="c1"&gt;# If neither string content nor SHA-256 hash matched, insert as a brand new item.
&lt;/span&gt;    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            INSERT INTO clipboard_items (type, content, preview, is_pinned, copy_count, created_at, updated_at)
            VALUES (?, ?, ?, 0, 1, ?, ?)
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastrowid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Zero-Leak Master Password Verification (&lt;code&gt;ui/dashboard.py&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;DotGhostBoard allows users to encrypt sensitive clips (e.g., API keys, passwords) using AES-256-GCM. &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%2Fatr8aj7qf8gxy5snlhw3.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%2Fatr8aj7qf8gxy5snlhw3.png" alt="Master Password Secret Lock Screen &amp;amp; Decryption" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a user copies a secret item from Spotlight or the Dashboard:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;_on_copy(item_id)&lt;/code&gt; checks if &lt;code&gt;item.get("is_secret")&lt;/code&gt; is true.&lt;/li&gt;
&lt;li&gt;If the session is locked (&lt;code&gt;_active_key is None&lt;/code&gt;), it prompts for the Master Password via &lt;code&gt;LockScreen&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The content is decrypted &lt;strong&gt;in-memory only&lt;/strong&gt; for copying to the OS clipboard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;watcher.mark_self_paste()&lt;/code&gt; informs the clipboard watcher to ignore the newly pasted plaintext so it is &lt;strong&gt;never saved back to the database as an unencrypted card&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;🛡️ &lt;strong&gt;Zero-Leak Security Architecture:&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero Disk Leak:&lt;/strong&gt; Decryption happens strictly in-memory during copy (&lt;code&gt;storage.decrypt_item&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watcher Interception:&lt;/strong&gt; &lt;code&gt;watcher.mark_self_paste()&lt;/code&gt; intercepts the next clipboard polling tick, updating &lt;code&gt;_last_content&lt;/code&gt; to ignore the text and preventing the watcher thread from re-saving the unencrypted secret back into SQLite.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI RAM Purge:&lt;/strong&gt; When locking the session, &lt;code&gt;on_session_locked()&lt;/code&gt; immediately purges plaintext from Qt UI labels (&lt;code&gt;setText("")&lt;/code&gt;) so sensitive data never lingers in widget memory.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Note: These protections completely prevent secrets from leaking back into DotGhostBoard's SQLite database or UI widgets. They do not yet control how long the plaintext sits on the OS-level clipboard buffer after pasting — which is why our upcoming v2.0 release introduces an automated 30-second clipboard wipe.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub Source Code:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/blob/main/ui/dashboard.py" rel="noopener noreferrer"&gt;&lt;code&gt;ui/dashboard.py&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_on_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_item_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is_secret&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# Check if session is unlocked
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_active_key&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;dlg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LockScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;dlg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;LockScreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DialogCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Accepted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_active_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dlg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_key&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_reset_auto_lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;statusBar&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;showMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;⚠ Session is locked — unlock to copy secret.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt;

            &lt;span class="c1"&gt;# Decrypt item content in-memory for copying
&lt;/span&gt;            &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_active_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;statusBar&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;showMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;⚠ Decryption failed — wrong key or corrupted data.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;

            &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;

        &lt;span class="c1"&gt;# Mark as self-paste so watcher updates _last_content without re-capturing
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;watcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mark_self_paste&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;watcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste_item_to_clipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Increment copy count in DB and refresh UI badge
&lt;/span&gt;        &lt;span class="n"&gt;new_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment_copy_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_cards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_copy_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;statusBar&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;showMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Copied! ⏘  (×&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;new_count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Search Input Debouncing with &lt;code&gt;QTimer&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Connecting &lt;code&gt;QLineEdit.textChanged&lt;/code&gt; directly to database queries causes UI freezing during rapid typing because every single keystroke executes an SQL query and clears/rebuilds PyQt6 widgets.&lt;/p&gt;

&lt;p&gt;We implemented a single-shot &lt;code&gt;QTimer&lt;/code&gt; debounce pattern in both the main Dashboard (200ms) and Spotlight (150ms):&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub Source Code:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/blob/main/ui/dashboard.py" rel="noopener noreferrer"&gt;&lt;code&gt;ui/dashboard.py&lt;/code&gt;&lt;/a&gt; | &lt;a href="https://github.com/kareem2099/DotGhostBoard/blob/main/ui/spotlight.py" rel="noopener noreferrer"&gt;&lt;code&gt;ui/spotlight.py&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# Inside Dashboard.__init__
&lt;/span&gt;    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSingleShot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_do_search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pending_search_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_on_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Debounce search box input by 200ms.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pending_search_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_do_search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Instant clear on empty input
&lt;/span&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_search_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_do_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute SQL query &amp;amp; UI rebuild after 200ms pause in typing.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_pending_search_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# ... SQL search &amp;amp; widget pagination ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Dashboard State Summary Banner (&lt;code&gt;StatsHeaderCard&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;At the top of the history feed, &lt;code&gt;StatsHeaderCard&lt;/code&gt; provides a live state summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;📋 Today&lt;/strong&gt;: Total clips captured today.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔥 Top&lt;/strong&gt;: Most frequently copied clip created today (excluding encrypted secrets).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📍 Pinned&lt;/strong&gt;: Total count of pinned clips.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc1wei1dwq2hu6mve4wnu.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%2Fc1wei1dwq2hu6mve4wnu.png" alt="Dashboard Stats Header Card" width="798" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub Source Code:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/blob/main/core/storage.py" rel="noopener noreferrer"&gt;&lt;code&gt;core/storage.py&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_today_stats&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;today_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cur1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT COUNT(*) as cnt FROM clipboard_items WHERE created_at LIKE ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today_prefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;total_today&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cur1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cnt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;cur3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            SELECT preview, content, copy_count
            FROM clipboard_items
            WHERE copy_count &amp;gt; 0
              AND created_at LIKE ?
              AND COALESCE(is_secret, 0) = 0
            ORDER BY copy_count DESC, updated_at DESC
            LIMIT 1
            &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today_prefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;top_row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cur3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# ... format &amp;amp; return dict ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Testing &amp;amp; Verification
&lt;/h2&gt;

&lt;p&gt;We maintained strict TDD practices throughout development, writing 184 unit tests using &lt;code&gt;pytest&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub Test Suite:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/blob/main/tests/test_v155_polish.py" rel="noopener noreferrer"&gt;&lt;code&gt;tests/test_v155_polish.py&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;=============================&lt;/span&gt; 184 passed &lt;span class="k"&gt;in &lt;/span&gt;8.40s &lt;span class="o"&gt;==============================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every component — from relative timestamp calculation (&lt;code&gt;_format_time&lt;/code&gt;) to SHA-256 image deduplication and &lt;code&gt;reset_copy_count&lt;/code&gt; boolean return values — is covered by automated unit tests in &lt;code&gt;tests/test_v155_polish.py&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Packaging &amp;amp; Installation on Linux
&lt;/h2&gt;

&lt;p&gt;DotGhostBoard is packaged for multiple Linux distributions including AppImage, &lt;code&gt;.deb&lt;/code&gt;, Arch Linux (&lt;code&gt;.pkg.tar.zst&lt;/code&gt;), and generic &lt;code&gt;.tar.gz&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;You can download pre-built release assets from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;GitHub Release v1.5.5:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/releases/tag/v1.5.5" rel="noopener noreferrer"&gt;https://github.com/kareem2099/DotGhostBoard/releases/tag/v1.5.5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🛍️ &lt;strong&gt;OpenDesktop / Pling Store:&lt;/strong&gt; &lt;a href="https://www.opendesktop.org/p/2353623/" rel="noopener noreferrer"&gt;https://www.opendesktop.org/p/2353623/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build DEB package locally&lt;/span&gt;
./scripts/build_deb.sh

&lt;span class="c"&gt;# Install on Kali Linux / Debian / Ubuntu&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; dotghostboard_1.5.5_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔮 What's Next? The Roadmap to DotGhostBoard v2.x (Cerberus)
&lt;/h2&gt;

&lt;p&gt;With the v1.5.x milestone complete, we are officially transitioning development to &lt;strong&gt;DotGhostBoard v2.x&lt;/strong&gt;! &lt;/p&gt;

&lt;p&gt;Here is a sneak peek at the exciting features engineered for the upcoming &lt;strong&gt;v2.0.0 (Cerberus)&lt;/strong&gt; release:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔒 &lt;strong&gt;The Vault (&lt;code&gt;vault.db&lt;/code&gt;)&lt;/strong&gt;: An isolated, zero-knowledge encrypted database completely separate from &lt;code&gt;ghost.db&lt;/code&gt;, protected by an independent Master Password for ultimate credential security.&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Regex Smart Secret Detection&lt;/strong&gt;: Pattern-based heuristic detection for API Keys, AWS credentials (&lt;code&gt;AKIA...&lt;/code&gt;), GitHub PATs (&lt;code&gt;ghp_...&lt;/code&gt;), JWT tokens, and high-entropy secrets — automatically prompting users to move them into The Vault.&lt;/li&gt;
&lt;li&gt;⏳ &lt;strong&gt;30-Second Auto-Wipe&lt;/strong&gt;: Automatic clipboard buffer wiping 30 seconds after pasting sensitive tokens from the Vault.&lt;/li&gt;
&lt;li&gt;🕵️ &lt;strong&gt;Paranoia / Zero-Logging Mode&lt;/strong&gt;: A single-click stealth mode toggle that temporarily halts all local database logging.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌟 Conclusion &amp;amp; Performance Benchmarks
&lt;/h2&gt;

&lt;p&gt;Building &lt;strong&gt;DotGhostBoard v1.5.5&lt;/strong&gt; proved that Linux desktop utilities don't need heavy web runtimes to deliver modern, fluid UI experiences. By choosing Python 3, PyQt6, and SQLite, we measured significant performance advantages in our local testing compared to typical Electron alternatives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;Full Runtime RAM:&lt;/strong&gt; &lt;strong&gt;~85 MB&lt;/strong&gt; process RSS (GUI + SQLite DB + Spotlight dialog loaded) vs &lt;strong&gt;~350 MB+&lt;/strong&gt; in typical Electron clipboard tools.&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Spotlight Query Latency:&lt;/strong&gt; &lt;strong&gt;~3.5 ms&lt;/strong&gt; average execution time across 10 runs (min 2.23 ms, max 4.90 ms).&lt;/li&gt;
&lt;li&gt;💾 &lt;strong&gt;Disk Optimization:&lt;/strong&gt; SHA-256 deduplication saved &lt;strong&gt;~85% disk space&lt;/strong&gt; during screenshot-heavy debugging sessions.&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Automated Suite:&lt;/strong&gt; &lt;strong&gt;184 / 184 tests passing&lt;/strong&gt; in 8.32s.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the full source code, download release packages, and star the repository on GitHub:&lt;br&gt;
👉 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard" rel="noopener noreferrer"&gt;https://github.com/kareem2099/DotGhostBoard&lt;/a&gt;&lt;br&gt;
👉 &lt;strong&gt;GitHub Release (v1.5.5):&lt;/strong&gt; &lt;a href="https://github.com/kareem2099/DotGhostBoard/releases/tag/v1.5.5" rel="noopener noreferrer"&gt;https://github.com/kareem2099/DotGhostBoard/releases/tag/v1.5.5&lt;/a&gt;&lt;br&gt;
👉 &lt;strong&gt;OpenDesktop / Pling Store:&lt;/strong&gt; &lt;a href="https://www.opendesktop.org/p/2353623/" rel="noopener noreferrer"&gt;https://www.opendesktop.org/p/2353623/&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  💬 Technical Discussion
&lt;/h3&gt;

&lt;p&gt;If you were designing our &lt;strong&gt;v2.0 Regex Smart Secret Detection Engine&lt;/strong&gt;, what would be the very first pattern or entropy rule you'd include to catch leaked keys? Drop your regex patterns or PR suggestions below! 🚀&lt;/p&gt;

</description>
      <category>python</category>
      <category>pyqt6</category>
      <category>linux</category>
      <category>security</category>
    </item>
    <item>
      <title>How I Refactored My Developer Portfolio Into a Modular, Secure, and Playfully Destructive Playground (v1.1.0)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Fri, 17 Jul 2026 20:25:39 +0000</pubDate>
      <link>https://dev.to/freerave/how-i-refactored-my-developer-portfolio-into-a-modular-secure-and-playfully-destructive-2m1a</link>
      <guid>https://dev.to/freerave/how-i-refactored-my-developer-portfolio-into-a-modular-secure-and-playfully-destructive-2m1a</guid>
      <description>&lt;h2&gt;
  
  
  A deep dive into refactoring a 1500+ line JS monolith into elegant ES6 modules, boosting performance by 95%, fixing XSS vectors, and adding a treacherous text-based game easter egg.
&lt;/h2&gt;

&lt;p&gt;A developer's portfolio is more than just a resume—it is a playground. When I built &lt;strong&gt;dotUniverse&lt;/strong&gt;, a cyberpunk-themed portfolio simulating a Kali Linux terminal, it quickly grew into a massive playground. But like many rapid prototypes, it eventually hit a wall: a 1500+ line monolithic &lt;code&gt;script.js&lt;/code&gt; file, performance lag on mobile, security warnings, and missing interactive elements.&lt;/p&gt;

&lt;p&gt;In this article, I will walk you through how I completed a &lt;strong&gt;1.1.0 Modular Refactor&lt;/strong&gt;, boosting performance by 95%, hardening security, and adding a highly engaging (and slightly treacherous) easter egg game that lets users "destroy" and restore the site.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ The Architecture: Breaking the Monolith
&lt;/h2&gt;

&lt;p&gt;Originally, the terminal commands, particle physics, scrolling, and UI triggers lived in a single script. I refactored this into clean, scoped &lt;strong&gt;ES6 Modules&lt;/strong&gt; managed by a single entry point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;js/
├── app.js                      # Entry point (initializes modules &amp;amp; defines commands)
└── modules/
    ├── particle-system.js       # Custom canvas particles + spatial grid optimization
    ├── math-eval.js             # Safe mathematical parser (No eval/new Function)
    ├── terminal-emulator.js     # CLI input handling &amp;amp; tab-completion state
    ├── challenges.js            # Challenge progress tracking
    ├── scroll-effects.js        # Lazy-loading scroll reveals
    └── theme-manager.js         # Color theme manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fal62ytz55tfbimnmojtq.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%2Fal62ytz55tfbimnmojtq.png" alt="VS Code Folder Structure of ES6 modules" width="309" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Terminal State Controller
&lt;/h3&gt;

&lt;p&gt;To allow interactive sub-prompts (like confirmations or games), I introduced a &lt;code&gt;promptHook&lt;/code&gt; mechanism in the terminal. When a command sets &lt;code&gt;promptHook&lt;/code&gt;, all subsequent keypresses are redirected to that function instead of being parsed as new terminal commands.&lt;/p&gt;

&lt;p&gt;Here is the key logic in &lt;a href="https://github.com/kareem2099/dotuniverse/blob/main/js/modules/terminal-emulator.js" rel="noopener noreferrer"&gt;terminal-emulator.js&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Inside TerminalEmulator&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;executeCommand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPromptLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;histIdx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Intercept input if an active game/prompt hook is set&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promptHook&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;promptHook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COMMANDS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COMMANDS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`  &amp;lt;span class="t-error"&amp;gt;Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: command not found&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔒 Hardening Security: Banishing &lt;code&gt;new Function&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The terminal calculator (&lt;code&gt;calc&lt;/code&gt;) originally used &lt;code&gt;new Function()&lt;/code&gt; to execute math operations. While convenient, parsing unsanitized input is a dangerous vector for &lt;strong&gt;Cross-Site Scripting (XSS)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I replaced it with a safe evaluation parsing engine in &lt;a href="https://github.com/kareem2099/dotuniverse/blob/main/js/modules/math-eval.js" rel="noopener noreferrer"&gt;math-eval.js&lt;/a&gt; using strict whitelist validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Whitelist pattern allowing numbers, basic math operators, parentheses, and letters&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[\d\s&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;/&lt;/span&gt;&lt;span class="sr"&gt;%().^a-zA-Z&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid characters&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚡ Performance: 95% CPU Savings
&lt;/h2&gt;

&lt;p&gt;Rendering dozens of floating particles that connect with lines is notoriously heavy. An $O(n^2)$ double-loop checking distances between every particle leads to massive lag at 60 FPS. &lt;/p&gt;

&lt;p&gt;I implemented a &lt;strong&gt;Spatial Grid Algorithm&lt;/strong&gt; in &lt;a href="https://github.com/kareem2099/dotuniverse/blob/main/js/modules/particle-system.js" rel="noopener noreferrer"&gt;particle-system.js&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The canvas is divided into grid cells of 150px.&lt;/li&gt;
&lt;li&gt;Each particle is registered in its corresponding cell.&lt;/li&gt;
&lt;li&gt;Instead of checking against all particles, a particle only checks the 9 cells surrounding it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This optimized the complexity from a heavy $O(n^2)$ to an average of $O(n)$ using a Spatial Grid (specifically $O(n \cdot k)$ where $k$ is the average number of particles in neighboring cells).&lt;/p&gt;

&lt;p&gt;Additionally, I integrated &lt;strong&gt;Mobile Optimizations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Touch Device Detection&lt;/strong&gt;: Automatically halves the particle count.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FPS Cap&lt;/strong&gt;: Capped mobile frames at 30 FPS instead of 60 FPS, reducing CPU usage by over 90% while keeping animations smooth.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjr37im5ryg84x34ku29s.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%2Fjr37im5ryg84x34ku29s.png" alt="Particle System Connected Nodes Background" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎮 The Fun Part: The Quantum Root Key Betrayal
&lt;/h2&gt;

&lt;p&gt;In Kali Linux, typing &lt;code&gt;rm -rf / --no-preserve-root&lt;/code&gt; is the ultimate destructive command. To pay homage to this, I built an interactive easter egg game called &lt;code&gt;game&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Set Up
&lt;/h3&gt;

&lt;p&gt;When the user types &lt;code&gt;game&lt;/code&gt;, they enter the "Quantum Key" mini-game. The terminal generates a secret number between 1 and 100 and gives them &lt;strong&gt;3 attempts&lt;/strong&gt; to guess it, providing &lt;code&gt;Too high 👆&lt;/code&gt; or &lt;code&gt;Too low 👇&lt;/code&gt; feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Betrayal
&lt;/h3&gt;

&lt;p&gt;No matter what happens, the game is rigged to betray them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If they lose&lt;/strong&gt;: Access is denied, and the system executes &lt;code&gt;rm -rf / --no-preserve-root&lt;/code&gt; as a penalty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If they win&lt;/strong&gt;: It announces success, loads &lt;code&gt;reward.exe&lt;/code&gt;... and then triggers a fake XSS exploit, executing &lt;code&gt;rm -rf / --no-preserve-root&lt;/code&gt; anyway!&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0xydqz3rsf8nu5wy4cii.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%2F0xydqz3rsf8nu5wy4cii.png" alt="CLI Guess the Number Game and Purge sequence" width="800" height="805"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the implementation inside &lt;a href="https://github.com/kareem2099/dotuniverse/blob/main/js/app.js" rel="noopener noreferrer"&gt;app.js&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// game command definition in app.js&lt;/span&gt;
&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-accent2"&amp;gt;🎮  MINIGAME: GUESS THE SECRET NUMBER  🎮&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-info"&amp;gt;I have chosen a secret number between 1 and 100.&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-info"&amp;gt;You have 3 attempts to guess it. Good luck!&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-prompt"&amp;gt;Enter your first guess [1-100]:&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;targetNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promptHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-error"&amp;gt;✖ Invalid input! Please enter a number between 1 and 100:&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;targetNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promptHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`  &amp;lt;span class="t-success"&amp;gt;🎉 CORRECT! The secret number was indeed &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;targetNum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-info"&amp;gt;Loading your reward.exe...&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-error"&amp;gt;⚠️  ERROR: Unexpected token in reward.exe!&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-error"&amp;gt;Wait, what is this...? Root payload detected: rm -rf /&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-accent2"&amp;gt;Pranked! Total betrayal! 😂 Execute self-destruction:&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;triggerPurge&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;targetNum&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Too low 👇&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Too high 👆&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`  &amp;lt;span class="t-error"&amp;gt;❌ Incorrect! &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`  &amp;lt;span class="t-accent2"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; attempt(s) remaining. Enter guess:&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promptHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`  &amp;lt;span class="t-error"&amp;gt;❌ GAME OVER! The secret number was &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;targetNum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-info"&amp;gt;Penalty authorized: rm -rf /hope --no-preserve-root&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &amp;lt;span class="t-error"&amp;gt;Executing purge... 💀&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;triggerPurge&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;triggerPurge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;removing /tools/DotGhostBoard... &amp;lt;span class="t-error"&amp;gt;✖ GONE&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;removing /tools/dotcommand...    &amp;lt;span class="t-error"&amp;gt;✖ GONE&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;removing /tools/CodeTune...      &amp;lt;span class="t-error"&amp;gt;✖ GONE&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;removing /platforms/dev.to...    &amp;lt;span class="t-error"&amp;gt;✖ GONE&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;removing /stats/followers...     &amp;lt;span class="t-error"&amp;gt;✖ GONE&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;span class="t-error"&amp;gt;💀 FATAL: filesystem destroyed&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;span class="t-error"&amp;gt;💀 FATAL: career.exe has stopped working&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;span class="t-dim"&amp;gt;Segmentation fault (core dumped)&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;triggerDestruction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;triggerDestruction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💻 The Ultimate Failsafe: Reverting via &lt;code&gt;git reverse&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Once the purge executes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All elements on the screen collapse, slide off, and blur out.&lt;/li&gt;
&lt;li&gt;The Blue Screen of Death (BSOD) prints simulated deletion logs and counts to 100%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Raw HTML Failsafe&lt;/strong&gt;: The page transitions into a completely blank white screen showing a raw, unstyled HTML page.

&lt;ul&gt;
&lt;li&gt;Standard default black text.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Times New Roman&lt;/code&gt; font.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;h1&amp;gt;Hello World&amp;lt;/h1&amp;gt;&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;A basic browser &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; with absolutely no CSS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;To fix the system, the user is required to write &lt;code&gt;git reverse&lt;/code&gt; in the text area. 
&lt;em&gt;(Note for the Git purists: yes, in real Git we use &lt;code&gt;git restore&lt;/code&gt; or &lt;code&gt;git revert&lt;/code&gt;. But in this hacker-themed scenario, typing &lt;code&gt;git reverse&lt;/code&gt; felt like the perfect theatrical command to undo the payload).&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&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%2Fnbib51ron3go9hlxf8n4.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%2Fnbib51ron3go9hlxf8n4.png" alt="Raw Hello World HTML Page without CSS" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Entering the command triggers a dark progress bar showing the git status restoration from &lt;strong&gt;0% to 100%&lt;/strong&gt;, rebuilding all project files and restoring the site layout.&lt;/li&gt;
&lt;/ol&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%2F4lbgto56ryb8rhxgqpag.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%2F4lbgto56ryb8rhxgqpag.png" alt="Restoring Environment Progress Bar" width="800" height="805"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the raw HTML restoration flow implemented in &lt;a href="https://github.com/kareem2099/dotuniverse/blob/main/script.js" rel="noopener noreferrer"&gt;script.js&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;showBlankScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;blank&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blankScreen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;blank&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    position: fixed; inset: 0; background: white; color: black;
    z-index: 99999; padding: 50px; overflow: auto; text-align: left;
    font-family: 'Times New Roman', Times, serif;
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;blank&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;h1&amp;gt;Hello World&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;Index of /&amp;lt;/p&amp;gt;
    &amp;lt;hr&amp;gt;
    &amp;lt;p&amp;gt;The server has encountered a critical failure. All active resources have been unlinked.&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;To reverse this action and restore the system to its last commit, please type the recovery command below and press Enter.&amp;lt;/p&amp;gt;
    &amp;lt;div style="margin-top: 20px;"&amp;gt;
      &amp;lt;textarea id="recoveryTextArea" rows="4" cols="50" placeholder="Type command here..." style="all: revert; font-family: monospace; font-size: 14px; width: 100%; max-width: 500px; padding: 5px;"&amp;gt;&amp;lt;/textarea&amp;gt;
      &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;
      &amp;lt;button id="recoveryBtn" style="all: revert; cursor: pointer; padding: 5px 15px;"&amp;gt;Execute Command&amp;lt;/button&amp;gt;
      &amp;lt;p id="recoveryError" style="color: red; font-weight: bold; margin-top: 10px; display: none;"&amp;gt;Invalid recovery command!&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blank&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recoveryTextArea&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recoveryBtn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recoveryError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleRecovery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;git reverse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;blank&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;runSystemRestoredProgress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleRecovery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;handleRecovery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📈 Summary of Improvements
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before Refactor (v1.0.0)&lt;/th&gt;
&lt;th&gt;After Refactor (v1.1.0)&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JS File Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1500+ line Monolith&lt;/td&gt;
&lt;td&gt;Modular ES6 Files&lt;/td&gt;
&lt;td&gt;Easy maintenance and debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Particle Physics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$O(n^2)$ complexity&lt;/td&gt;
&lt;td&gt;Average of $O(n)$ Spatial Grid&lt;/td&gt;
&lt;td&gt;95% CPU savings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile Refresh Rate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uncapped 60 FPS (heavy CPU lag)&lt;/td&gt;
&lt;td&gt;Capped at 30 FPS + 50% particles&lt;/td&gt;
&lt;td&gt;Smooth experience, low battery drain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security Risk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High XSS risk via &lt;code&gt;new Function&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Mitigated (strict whitelist parsing)&lt;/td&gt;
&lt;td&gt;Zero code execution vulnerability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interactive Easter Eggs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Static logs&lt;/td&gt;
&lt;td&gt;Rigged &lt;code&gt;game&lt;/code&gt; + &lt;code&gt;git reverse&lt;/code&gt; prompt&lt;/td&gt;
&lt;td&gt;Unforgettable user experience 🎮&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Refactoring doesn't have to be boring. By restructuring the codebase of &lt;strong&gt;dotUniverse&lt;/strong&gt; into modular pieces, we didn't just gain a massive performance speedup and security hardening—we opened up the architecture to support complex interactive behaviors. Adding this easter egg turned a static portfolio page into a memorable, interactive game that web developers can love.&lt;/p&gt;

&lt;p&gt;What is your favorite terminal easter egg? Let me know in the comments below! 🚀&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>performance</category>
      <category>security</category>
    </item>
  </channel>
</rss>
