<!-- CANARY: REQ=REQ-SEC-AUDIT-LOG-001; FEATURE="Security"; ASPECT=AuditLog; STATUS=TESTED; OWNER=security; UPDATED=2026-01-16 --> <h2 id="field-level-encryption-guide" class="position-relative d-flex align-items-center group"> <span>Field-Level Encryption Guide</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="field-level-encryption-guide" aria-haspopup="dialog" aria-label="Share link: Field-Level Encryption Guide"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h2><div id="headingShareModal" class="heading-share-modal" role="dialog" aria-modal="true" aria-labelledby="headingShareTitle" hidden> <div class="hsm-dialog" role="document"> <div class="hsm-header"> <h2 id="headingShareTitle" class="h6 mb-0 fw-bold">Share this section</h2> <button type="button" class="hsm-close" aria-label="Close"> <i class="fa-solid fa-xmark"></i> </button> </div> <div class="hsm-body"> <label for="headingShareInput" class="form-label small text-muted mb-1 text-uppercase fw-bold" style="font-size: 0.7rem; letter-spacing: 0.5px;">Permalink</label> <div class="input-group mb-4 hsm-url-group"> <input id="headingShareInput" type="text" class="form-control font-monospace" readonly aria-readonly="true" style="font-size: 0.85rem;" /> <button class="btn btn-primary hsm-copy" type="button" aria-label="Copy" title="Copy"> <i class="fa-duotone fa-clipboard" aria-hidden="true"></i> </button> </div> <div class="small fw-bold mb-2 text-muted text-uppercase" style="font-size: 0.7rem; letter-spacing: 0.5px;">Share via</div> <div class="hsm-share-grid"> <a id="share-twitter" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-twitter me-2"></i>Twitter </a> <a id="share-linkedin" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-linkedin me-2"></i>LinkedIn </a> <a id="share-facebook" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-facebook me-2"></i>Facebook </a> </div> </div> </div> </div> <style> .heading-share-modal { position: fixed; inset: 0; display: flex; justify-content: center; align-items: center; background: rgba(0, 0, 0, 0.6); z-index: 1050; padding: 1rem; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); } .heading-share-modal[hidden] { display: none !important; } .hsm-dialog { max-width: 420px; width: 100%; background: var(--bs-body-bg, #fff); color: var(--bs-body-color, #212529); border: 1px solid var(--bs-border-color, rgba(0,0,0,0.1)); border-radius: 1rem; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); overflow: hidden; animation: hsm-fade-in 0.2s ease-out; } @keyframes hsm-fade-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } [data-bs-theme="dark"] .hsm-dialog { background: #1e293b; border-color: rgba(255,255,255,0.1); color: #f8f9fa; } .hsm-header { display: flex; justify-content: space-between; align-items: center; padding: 1rem 1.5rem; border-bottom: 1px solid var(--bs-border-color, rgba(0,0,0,0.1)); background: rgba(0,0,0,0.02); } [data-bs-theme="dark"] .hsm-header { background: rgba(255,255,255,0.02); border-color: rgba(255,255,255,0.1); } .hsm-close { background: transparent; border: none; color: inherit; opacity: 0.5; padding: 0.25rem 0.5rem; border-radius: 0.25rem; font-size: 1.2rem; line-height: 1; transition: opacity 0.2s; } .hsm-close:hover { opacity: 1; } .hsm-body { padding: 1.5rem; } .hsm-url-group { display: flex !important; align-items: stretch; } .hsm-url-group .form-control { flex: 1; min-width: 0; margin: 0; background: var(--bs-secondary-bg, #f8f9fa); border-color: var(--bs-border-color, #dee2e6); border-top-right-radius: 0; border-bottom-right-radius: 0; height: 42px; } .hsm-url-group .btn { flex: 0 0 auto; margin: 0; margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; height: 42px; display: flex; align-items: center; justify-content: center; padding: 0 1.25rem; z-index: 2; } [data-bs-theme="dark"] .hsm-url-group .form-control { background: #0f172a; border-color: #334155; color: #e2e8f0; } .hsm-share-grid { display: flex; flex-direction: column; gap: 0.5rem; } .hsm-share-grid .btn { display: flex; align-items: center; justify-content: center; font-size: 0.9rem; padding: 0.6rem; border-color: var(--bs-border-color); width: 100%; } [data-bs-theme="dark"] .hsm-share-grid .btn { color: #e2e8f0; border-color: #475569; } [data-bs-theme="dark"] .hsm-share-grid .btn:hover { background: #334155; border-color: #cbd5e1; } </style> <script> (function(){ const modal = document.getElementById('headingShareModal'); if(!modal) return; const input = modal.querySelector('#headingShareInput'); const copyBtn = modal.querySelector('.hsm-copy'); const twitter = modal.querySelector('#share-twitter'); const linkedin = modal.querySelector('#share-linkedin'); const facebook = modal.querySelector('#share-facebook'); const closeBtn = modal.querySelector('.hsm-close'); let lastFocus=null; let trapBound=false; function buildUrl(id){ return window.location.origin + window.location.pathname + '#' + id; } function isOpen(){ return !modal.hasAttribute('hidden'); } function hydrate(id){ const url=buildUrl(id); input.value=url; const enc=encodeURIComponent(url); const text=encodeURIComponent(document.title); if(twitter) twitter.href=`https://twitter.com/intent/tweet?url=${enc}&text=${text}`; if(linkedin) linkedin.href=`https://www.linkedin.com/sharing/share-offsite/?url=${enc}`; if(facebook) facebook.href=`https://www.facebook.com/sharer/sharer.php?u=${enc}`; } function openModal(id){ lastFocus=document.activeElement; hydrate(id); if(!isOpen()){ modal.removeAttribute('hidden'); } requestAnimationFrame(()=>{ input.focus(); }); trapFocus(); } function closeModal(){ if(!isOpen()) return; modal.setAttribute('hidden',''); if(lastFocus && typeof lastFocus.focus==='function') lastFocus.focus(); } function copyCurrent(){ try{ navigator.clipboard.writeText(input.value).then(()=>feedback(true),()=>fallback()); } catch(e){ fallback(); } } function fallback(){ input.select(); try{ document.execCommand('copy'); feedback(true);}catch(e){ feedback(false);} } function feedback(ok){ if(!copyBtn) return; const icon=copyBtn.querySelector('i'); if(!icon) return; const prev=copyBtn.getAttribute('data-prev')||icon.className; if(!copyBtn.getAttribute('data-prev')) copyBtn.setAttribute('data-prev',prev); icon.className= ok ? 'fa-duotone fa-clipboard-check':'fa-duotone fa-circle-exclamation'; setTimeout(()=>{ icon.className=prev; },1800); } function handleShareClick(e){ e.preventDefault(); const btn=e.currentTarget; const id=btn.getAttribute('data-share-target'); if(id) openModal(id); } function bindShareButtons(){ document.querySelectorAll('.h-share').forEach(btn=>{ if(!btn.dataset.hShareBound){ btn.addEventListener('click', handleShareClick); btn.dataset.hShareBound='1'; } }); } bindShareButtons(); if(document.readyState==='loading'){ document.addEventListener('DOMContentLoaded', bindShareButtons); } else { requestAnimationFrame(bindShareButtons); } document.addEventListener('click', function(e){ const shareBtn=e.target.closest && e.target.closest('.h-share'); if(shareBtn && !shareBtn.dataset.hShareBound){ handleShareClick.call(shareBtn, e); } }, true); document.addEventListener('click', e=>{ if(e.target===modal) closeModal(); if(e.target.closest && e.target.closest('.hsm-close')){ e.preventDefault(); closeModal(); } if(copyBtn && (e.target===copyBtn || (e.target.closest && e.target.closest('.hsm-copy')))) { e.preventDefault(); copyCurrent(); } }); document.addEventListener('keydown', e=>{ if(e.key==='Escape' && isOpen()) closeModal(); }); function trapFocus(){ if(trapBound) return; trapBound=true; modal.addEventListener('keydown', f=>{ if(f.key==='Tab' && isOpen()){ const focusable=[...modal.querySelectorAll('a[href],button,input,textarea,select,[tabindex]:not([tabindex="-1"])')].filter(el=>!el.hasAttribute('disabled')); if(!focusable.length) return; const first=focusable[0]; const last=focusable[focusable.length-1]; if(f.shiftKey && document.activeElement===first){ f.preventDefault(); last.focus(); } else if(!f.shiftKey && document.activeElement===last){ f.preventDefault(); first.focus(); } } }); } if(closeBtn) closeBtn.addEventListener('click', e=>{ e.preventDefault(); closeModal(); }); })(); </script><p>Geode provides native, application-level field-level encryption (FLE) with transparent encryption/decryption, equality search on encrypted fields, and online key rotation.</p> <blockquote> <p><strong>Known issue (2026-03-30)</strong></p> <p><code>GAP-0271</code> tracks a remaining parser bug on <code>main</code>: semicolon-delimited role input must be rejected or sanitized to prevent unintended plaintext access to FLE-protected fields. Until that patch ships, treat all role lists as trusted server-side data and reject <code>;</code> in any caller-controlled role parameter.</p> </blockquote> <h3 id="overview" class="position-relative d-flex align-items-center group"> <span>Overview</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="overview" aria-haspopup="dialog" aria-label="Share link: Overview"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="what-is-field-level-encryption" class="position-relative d-flex align-items-center group"> <span>What is Field-Level Encryption?</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="what-is-field-level-encryption" aria-haspopup="dialog" aria-label="Share link: What is Field-Level Encryption?"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Field-Level Encryption allows you to encrypt specific sensitive fields in your graph database while keeping the rest of the data in plaintext. This provides:</p> <ul> <li><strong>Selective Protection</strong>: Encrypt only PII, PHI, or other sensitive data</li> <li><strong>Transparent Access</strong>: Authorized users see plaintext automatically</li> <li><strong>Searchable Encryption</strong>: Equality queries on encrypted fields via blind indexes</li> <li><strong>Key Rotation</strong>: Online re-encryption with zero downtime</li> <li><strong>RBAC Integration</strong>: Role-based access to plaintext values</li> </ul> <h4 id="key-features" class="position-relative d-flex align-items-center group"> <span>Key Features</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="key-features" aria-haspopup="dialog" aria-label="Share link: Key Features"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ul> <li>✅ <strong>AEAD Encryption</strong>: AES-256-GCM (hardware-accelerated) or ChaCha20-Poly1305</li> <li>✅ <strong>Blind Indexes</strong>: Equality search without decryption</li> <li>✅ <strong>Hierarchical Keys</strong>: Multi-layer key derivation (TRK → SK → FEK → BIK)</li> <li>✅ <strong>Online Rotation</strong>: Zero-downtime key rotation with background re-encryption</li> <li>✅ <strong>RBAC Gates</strong>: Fine-grained access control to plaintext</li> <li>✅ <strong>Audit Trail</strong>: Complete encryption/decryption audit logs</li> </ul> <h3 id="architecture" class="position-relative d-flex align-items-center group"> <span>Architecture</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="architecture" aria-haspopup="dialog" aria-label="Share link: Architecture"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="key-hierarchy" class="position-relative d-flex align-items-center group"> <span>Key Hierarchy</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="key-hierarchy" aria-haspopup="dialog" aria-label="Share link: Key Hierarchy"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Geode uses a four-level key hierarchy for maximum security and flexibility:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Master Key (Environment/KMS) </span></span><span class="line"><span class="cl"> └─ TRK (Tenant Root Key) </span></span><span class="line"><span class="cl"> └─ SK (Schema Key, per tenant+schema) </span></span><span class="line"><span class="cl"> ├─ FEK (Field Encryption Key, per field+version) </span></span><span class="line"><span class="cl"> └─ BIK (Blind Index Key, for searchable fields) </span></span></code></pre></div><p><strong>Key Derivation</strong>: HKDF-SHA256 with context strings ensures cryptographic separation.</p> <h4 id="encryption-algorithms" class="position-relative d-flex align-items-center group"> <span>Encryption Algorithms</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="encryption-algorithms" aria-haspopup="dialog" aria-label="Share link: Encryption Algorithms"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><table> <thead> <tr> <th>Algorithm</th> <th>Use Case</th> <th>Performance Notes</th> <th>Platform</th> </tr> </thead> <tbody> <tr> <td><strong>AES-256-GCM</strong></td> <td>Default for AES-NI hardware</td> <td>Hardware-accelerated</td> <td>x86-64, ARM with AES support</td> </tr> <tr> <td><strong>ChaCha20-Poly1305</strong></td> <td>Fallback for non-AES platforms</td> <td>Constant-time</td> <td>All platforms</td> </tr> </tbody> </table> <p>Both algorithms provide <strong>authenticated encryption with associated data (AEAD)</strong>, protecting against tampering and context-swapping attacks.</p> <h4 id="envelope-format" class="position-relative d-flex align-items-center group"> <span>Envelope Format</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="envelope-format" aria-haspopup="dialog" aria-label="Share link: Envelope Format"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Encrypted fields are stored as binary envelopes:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[alg:u8][version:u16][nonce:12][tag:16][ciphertext_len:u32][ciphertext] </span></span></code></pre></div><ul> <li><strong>Algorithm ID</strong>: 1=AES-256-GCM, 2=ChaCha20-Poly1305</li> <li><strong>Key Version</strong>: For rotation tracking</li> <li><strong>Nonce</strong>: 96-bit unique value</li> <li><strong>Tag</strong>: 128-bit authentication tag</li> <li><strong>Ciphertext</strong>: Encrypted field value</li> </ul> <h4 id="blind-indexes-for-search" class="position-relative d-flex align-items-center group"> <span>Blind Indexes for Search</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="blind-indexes-for-search" aria-haspopup="dialog" aria-label="Share link: Blind Indexes for Search"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>For searchable encrypted fields, Geode maintains a blind index:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">BI = HMAC-SHA256(BIK, normalize(plaintext)) </span></span></code></pre></div><p><strong>Normalization</strong>: ASCII lowercase + whitespace trim</p> <p>This allows equality searches (<code>WHERE email = '[email protected]'</code>) on encrypted fields without decryption.</p> <p><strong>Trade-off</strong>: Reveals equality patterns (same plaintext → same BI) and value frequency.</p> <h3 id="getting-started" class="position-relative d-flex align-items-center group"> <span>Getting Started</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="getting-started" aria-haspopup="dialog" aria-label="Share link: Getting Started"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="prerequisites" class="position-relative d-flex align-items-center group"> <span>Prerequisites</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="prerequisites" aria-haspopup="dialog" aria-label="Share link: Prerequisites"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ul> <li>Geode 0.2.x</li> <li>Understanding of your data classification requirements</li> <li>RBAC/roles configured for your users</li> </ul> <h4 id="quick-start-example" class="position-relative d-flex align-items-center group"> <span>Quick Start Example</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="quick-start-example" aria-haspopup="dialog" aria-label="Share link: Quick Start Example"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">1</span><span class="err">.</span><span class="w"> </span><span class="py">Create</span><span class="w"> </span><span class="py">node</span><span class="w"> </span><span class="kd">type</span><span class="w"> </span><span class="nc">with</span><span class="w"> </span><span class="py">encrypted</span><span class="w"> </span><span class="py">fields</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Customer</span><span class="w"> </span><span class="p">(</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">id</span><span class="w"> </span><span class="py">UUID</span><span class="w"> </span><span class="py">PRIMARY</span><span class="w"> </span><span class="py">KEY</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">name</span><span class="w"> </span><span class="py">STRING</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">email</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@searchable</span><span class="p">(</span><span class="nc">index</span><span class="p">:</span><span class="s">&#34;blind-hmac-sha256&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">ssn</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;Restricted&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@visible</span><span class="p">(</span><span class="nc">to_roles</span><span class="p">:[</span><span class="s">&#34;compliance_officer&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">credit_score</span><span class="w"> </span><span class="py">INT</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">2</span><span class="err">.</span><span class="w"> </span><span class="py">Insert</span><span class="w"> </span><span class="py">data</span><span class="w"> </span><span class="p">(</span><span class="py">encryption</span><span class="w"> </span><span class="py">happens</span><span class="w"> </span><span class="py">automatically</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="p">(:</span><span class="nc">Customer</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">id</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">550e8400</span><span class="err">-</span><span class="py">e29b</span><span class="err">-</span><span class="py">41d4</span><span class="err">-</span><span class="py">a716</span><span class="err">-</span><span class="py">446655440000</span><span class="err">&#39;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">name</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">Alice</span><span class="w"> </span><span class="py">Johnson</span><span class="err">&#39;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">email</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">alice</span><span class="nd">@example</span><span class="err">.</span><span class="py">com</span><span class="err">&#39;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">ssn</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">123</span><span class="err">-</span><span class="py">45</span><span class="err">-</span><span class="py">6789</span><span class="err">&#39;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">credit_score</span><span class="p">:</span><span class="w"> </span><span class="nc">720</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">})</span><span class="err">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">3</span><span class="err">.</span><span class="w"> </span><span class="py">Query</span><span class="w"> </span><span class="py">with</span><span class="w"> </span><span class="py">automatic</span><span class="w"> </span><span class="py">decryption</span><span class="w"> </span><span class="p">(</span><span class="py">for</span><span class="w"> </span><span class="py">authorized</span><span class="w"> </span><span class="py">users</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">MATCH</span><span class="w"> </span><span class="p">(</span><span class="py">c</span><span class="p">:</span><span class="nc">Customer</span><span class="w"> </span><span class="p">{</span><span class="py">email</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">alice</span><span class="nd">@example</span><span class="err">.</span><span class="py">com</span><span class="err">&#39;</span><span class="p">})</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">RETURN</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">name</span><span class="p">,</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">email</span><span class="p">,</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">ssn</span><span class="err">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Authorized</span><span class="w"> </span><span class="py">user</span><span class="w"> </span><span class="py">sees</span><span class="w"> </span><span class="py">plaintext</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Unauthorized</span><span class="w"> </span><span class="py">user</span><span class="w"> </span><span class="py">sees</span><span class="w"> </span><span class="s">&#34;[REDACTED]&#34;</span><span class="w"> </span><span class="py">for</span><span class="w"> </span><span class="py">ssn</span><span class="w"> </span></span></span></code></pre></div> <h3 id="schema-annotations" class="position-relative d-flex align-items-center group"> <span>Schema Annotations</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="schema-annotations" aria-haspopup="dialog" aria-label="Share link: Schema Annotations"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><p>Geode extends GQL with field-level encryption annotations (non-standard, Geode-specific):</p> <h4 id="encrypted" class="position-relative d-flex align-items-center group"> <span>@encrypted</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="encrypted" aria-haspopup="dialog" aria-label="Share link: @encrypted"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Enable encryption for a field:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">,</span><span class="w"> </span><span class="nc">key_scope</span><span class="p">:</span><span class="s">&#34;field&#34;</span><span class="p">,</span><span class="w"> </span><span class="nc">rotate</span><span class="p">:</span><span class="s">&#34;90d&#34;</span><span class="p">)</span><span class="w"> </span></span></span></code></pre></div><p><strong>Parameters</strong>:</p> <ul> <li><code>alg</code>: &ldquo;AES-256-GCM&rdquo; (default) or &ldquo;CHACHA20-POLY1305&rdquo;</li> <li><code>key_scope</code>: &ldquo;field&rdquo; (per-field key) or &ldquo;schema&rdquo; (shared schema key)</li> <li><code>rotate</code>: Optional rotation interval hint (e.g., &ldquo;90d&rdquo;, &ldquo;1y&rdquo;)</li> </ul> <h4 id="searchable" class="position-relative d-flex align-items-center group"> <span>@searchable</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="searchable" aria-haspopup="dialog" aria-label="Share link: @searchable"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Enable equality search via blind index:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="nd">@searchable</span><span class="p">(</span><span class="py">index</span><span class="p">:</span><span class="s">&#34;blind-hmac-sha256&#34;</span><span class="p">)</span><span class="w"> </span></span></span></code></pre></div><p><strong>Parameters</strong>:</p> <ul> <li><code>index</code>: &ldquo;blind-hmac-sha256&rdquo; (only supported option)</li> </ul> <p><strong>Use case</strong>: Email addresses, usernames, account IDs</p> <p><strong>Security note</strong>: Reveals equality patterns and frequency distribution.</p> <h4 id="visible" class="position-relative d-flex align-items-center group"> <span>@visible</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="visible" aria-haspopup="dialog" aria-label="Share link: @visible"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>RBAC gate for plaintext access:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="nd">@visible</span><span class="p">(</span><span class="py">to_roles</span><span class="p">:[</span><span class="s">&#34;admin&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;compliance_officer&#34;</span><span class="p">])</span><span class="w"> </span></span></span></code></pre></div><p><strong>Parameters</strong>:</p> <ul> <li><code>to_roles</code>: List of roles permitted to see plaintext</li> </ul> <p>Users without these roles see <code>&quot;[REDACTED]&quot;</code> or ciphertext.</p> <h4 id="classify" class="position-relative d-flex align-items-center group"> <span>@classify</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="classify" aria-haspopup="dialog" aria-label="Share link: @classify"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Sensitivity classification tags:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="nd">@classify</span><span class="p">(</span><span class="py">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;PHI&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;Restricted&#34;</span><span class="p">])</span><span class="w"> </span></span></span></code></pre></div><p><strong>Parameters</strong>:</p> <ul> <li><code>tags</code>: Classification labels for audit and compliance</li> </ul> <h3 id="common-use-cases" class="position-relative d-flex align-items-center group"> <span>Common Use Cases</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="common-use-cases" aria-haspopup="dialog" aria-label="Share link: Common Use Cases"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="use-case-1-healthcare---patient-records" class="position-relative d-flex align-items-center group"> <span>Use Case 1: Healthcare - Patient Records</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="use-case-1-healthcare---patient-records" aria-haspopup="dialog" aria-label="Share link: Use Case 1: Healthcare - Patient Records"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Patient</span><span class="w"> </span><span class="p">(</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">patient_id</span><span class="w"> </span><span class="py">UUID</span><span class="w"> </span><span class="py">PRIMARY</span><span class="w"> </span><span class="py">KEY</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">name</span><span class="w"> </span><span class="py">STRING</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">date_of_birth</span><span class="w"> </span><span class="py">DATE</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PHI&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;Sensitive&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">ssn</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PHI&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;Restricted&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@visible</span><span class="p">(</span><span class="nc">to_roles</span><span class="p">:[</span><span class="s">&#34;physician&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;compliance&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">medical_record_number</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@searchable</span><span class="p">(</span><span class="nc">index</span><span class="p">:</span><span class="s">&#34;blind-hmac-sha256&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PHI&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">diagnosis</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PHI&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@visible</span><span class="p">(</span><span class="nc">to_roles</span><span class="p">:[</span><span class="s">&#34;physician&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;nurse&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div><p><strong>Access control</strong>:</p> <ul> <li>Physicians: See all PHI fields</li> <li>Nurses: See diagnosis, not SSN</li> <li>Billing staff: Search by MRN, see redacted diagnosis</li> </ul> <h4 id="use-case-2-finance---customer-data" class="position-relative d-flex align-items-center group"> <span>Use Case 2: Finance - Customer Data</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="use-case-2-finance---customer-data" aria-haspopup="dialog" aria-label="Share link: Use Case 2: Finance - Customer Data"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Account</span><span class="w"> </span><span class="p">(</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">account_id</span><span class="w"> </span><span class="py">UUID</span><span class="w"> </span><span class="py">PRIMARY</span><span class="w"> </span><span class="py">KEY</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">customer_name</span><span class="w"> </span><span class="py">STRING</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">account_number</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@searchable</span><span class="p">(</span><span class="nc">index</span><span class="p">:</span><span class="s">&#34;blind-hmac-sha256&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;PCI&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">routing_number</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PCI&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">balance</span><span class="w"> </span><span class="py">DECIMAL</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">credit_card_number</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PCI-DSS&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;Restricted&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@visible</span><span class="p">(</span><span class="nc">to_roles</span><span class="p">:[</span><span class="s">&#34;fraud_analyst&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;compliance&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div> <h4 id="use-case-3-e-commerce---user-profiles" class="position-relative d-flex align-items-center group"> <span>Use Case 3: E-commerce - User Profiles</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="use-case-3-e-commerce---user-profiles" aria-haspopup="dialog" aria-label="Share link: Use Case 3: E-commerce - User Profiles"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="py">CREATE</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">User</span><span class="w"> </span><span class="p">(</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">user_id</span><span class="w"> </span><span class="py">UUID</span><span class="w"> </span><span class="py">PRIMARY</span><span class="w"> </span><span class="py">KEY</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">username</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@searchable</span><span class="p">(</span><span class="py">index</span><span class="p">:</span><span class="s">&#34;blind-hmac-sha256&#34;</span><span class="p">),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">email</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@searchable</span><span class="p">(</span><span class="nc">index</span><span class="p">:</span><span class="s">&#34;blind-hmac-sha256&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">phone</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@visible</span><span class="p">(</span><span class="nc">to_roles</span><span class="p">:[</span><span class="s">&#34;customer_service&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;admin&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">shipping_address</span><span class="w"> </span><span class="py">STRING</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="nc">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">]),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">preferences</span><span class="w"> </span><span class="kc">OBJECT</span><span class="w"> </span><span class="err">--</span><span class="w"> </span><span class="py">Not</span><span class="w"> </span><span class="py">encrypted</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div> <h3 id="query-operations" class="position-relative d-flex align-items-center group"> <span>Query Operations</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="query-operations" aria-haspopup="dialog" aria-label="Share link: Query Operations"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="inserting-data" class="position-relative d-flex align-items-center group"> <span>Inserting Data</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="inserting-data" aria-haspopup="dialog" aria-label="Share link: Inserting Data"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Encryption</span><span class="w"> </span><span class="py">happens</span><span class="w"> </span><span class="py">automatically</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">CREATE</span><span class="w"> </span><span class="p">(:</span><span class="nc">Customer</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">id</span><span class="p">:</span><span class="w"> </span><span class="nc">gen_uuid</span><span class="p">(),</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">name</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">Bob</span><span class="w"> </span><span class="py">Smith</span><span class="err">&#39;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">email</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">bob</span><span class="nd">@example</span><span class="err">.</span><span class="py">com</span><span class="err">&#39;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">ssn</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">987</span><span class="err">-</span><span class="py">65</span><span class="err">-</span><span class="py">4321</span><span class="err">&#39;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">})</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div><p><strong>What happens</strong>:</p> <ol> <li>Geode detects <code>@encrypted</code> annotation on <code>email</code> and <code>ssn</code></li> <li>Generates unique nonce</li> <li>Encrypts values with appropriate FEK</li> <li>Computes blind index for <code>email</code> (if <code>@searchable</code>)</li> <li>Stores encrypted envelope</li> </ol> <h4 id="querying-encrypted-fields" class="position-relative d-flex align-items-center group"> <span>Querying Encrypted Fields</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="querying-encrypted-fields" aria-haspopup="dialog" aria-label="Share link: Querying Encrypted Fields"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Equality search</strong> (requires <code>@searchable</code>):</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="py">MATCH</span><span class="w"> </span><span class="p">(</span><span class="py">c</span><span class="p">:</span><span class="nc">Customer</span><span class="w"> </span><span class="p">{</span><span class="py">email</span><span class="p">:</span><span class="w"> </span><span class="err">&#39;</span><span class="nc">alice</span><span class="nd">@example</span><span class="err">.</span><span class="py">com</span><span class="err">&#39;</span><span class="p">})</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">RETURN</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">name</span><span class="p">,</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">email</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div><p><strong>What happens</strong>:</p> <ol> <li>Geode computes blind index: <code>BI = HMAC(BIK, '[email protected]')</code></li> <li>Looks up records with matching BI</li> <li>For authorized users, decrypts <code>email</code> field</li> <li>Returns plaintext to authorized users, <code>&quot;[REDACTED]&quot;</code> to others</li> </ol> <p><strong>Non-searchable fields</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">ERROR</span><span class="p">:</span><span class="w"> </span><span class="nc">Cannot</span><span class="w"> </span><span class="py">filter</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">non</span><span class="err">-</span><span class="py">searchable</span><span class="w"> </span><span class="py">encrypted</span><span class="w"> </span><span class="py">field</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">MATCH</span><span class="w"> </span><span class="p">(</span><span class="py">c</span><span class="p">:</span><span class="nc">Customer</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHERE</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">ssn</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">&#39;</span><span class="py">123</span><span class="err">-</span><span class="py">45</span><span class="err">-</span><span class="py">6789</span><span class="err">&#39;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">RETURN</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">name</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div> <h4 id="explicit-projection-control" class="position-relative d-flex align-items-center group"> <span>Explicit Projection Control</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="explicit-projection-control" aria-haspopup="dialog" aria-label="Share link: Explicit Projection Control"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Force</span><span class="w"> </span><span class="py">plaintext</span><span class="w"> </span><span class="p">(</span><span class="py">requires</span><span class="w"> </span><span class="py">READ_PLAINTEXT</span><span class="w"> </span><span class="py">privilege</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">RETURN</span><span class="w"> </span><span class="py">PLAINTEXT</span><span class="p">(</span><span class="py">c</span><span class="err">.</span><span class="py">ssn</span><span class="p">)</span><span class="err">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">Force</span><span class="w"> </span><span class="py">ciphertext</span><span class="w"> </span><span class="p">(</span><span class="py">always</span><span class="w"> </span><span class="py">allowed</span><span class="w"> </span><span class="py">if</span><span class="w"> </span><span class="py">node</span><span class="w"> </span><span class="py">readable</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">RETURN</span><span class="w"> </span><span class="py">CIPHERTEXT</span><span class="p">(</span><span class="py">c</span><span class="err">.</span><span class="py">ssn</span><span class="p">)</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div> <h3 id="access-control" class="position-relative d-flex align-items-center group"> <span>Access Control</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="access-control" aria-haspopup="dialog" aria-label="Share link: Access Control"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="granting-plaintext-access" class="position-relative d-flex align-items-center group"> <span>Granting Plaintext Access</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="granting-plaintext-access" aria-haspopup="dialog" aria-label="Share link: Granting Plaintext Access"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Grant role access to plaintext</span> </span></span><span class="line"><span class="cl">GRANT READ_PLAINTEXT ON Customer.ssn TO ROLE compliance_officer<span class="p">;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Revoke access</span> </span></span><span class="line"><span class="cl">REVOKE READ_PLAINTEXT ON Customer.ssn FROM ROLE analyst<span class="p">;</span> </span></span></code></pre></div> <h4 id="permissions-model" class="position-relative d-flex align-items-center group"> <span>Permissions Model</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="permissions-model" aria-haspopup="dialog" aria-label="Share link: Permissions Model"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><table> <thead> <tr> <th>Permission</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>READ_PLAINTEXT(schema.field)</code></td> <td>View decrypted value</td> </tr> <tr> <td><code>READ_CIPHERTEXT(schema.field)</code></td> <td>View ciphertext (always granted if node readable)</td> </tr> <tr> <td><code>WRITE(schema.field)</code></td> <td>Set value (automatically encrypted)</td> </tr> </tbody> </table> <h4 id="example-access-matrix" class="position-relative d-flex align-items-center group"> <span>Example Access Matrix</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="example-access-matrix" aria-haspopup="dialog" aria-label="Share link: Example Access Matrix"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><table> <thead> <tr> <th>Role</th> <th><code>Customer.name</code></th> <th><code>Customer.email</code></th> <th><code>Customer.ssn</code></th> </tr> </thead> <tbody> <tr> <td><code>customer_service</code></td> <td>Plaintext</td> <td>Plaintext</td> <td><code>[REDACTED]</code></td> </tr> <tr> <td><code>compliance_officer</code></td> <td>Plaintext</td> <td>Plaintext</td> <td>Plaintext</td> </tr> <tr> <td><code>analyst</code></td> <td>Plaintext</td> <td><code>[REDACTED]</code></td> <td><code>[REDACTED]</code></td> </tr> </tbody> </table> <h3 id="key-rotation" class="position-relative d-flex align-items-center group"> <span>Key Rotation</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="key-rotation" aria-haspopup="dialog" aria-label="Share link: Key Rotation"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="why-rotate-keys" class="position-relative d-flex align-items-center group"> <span>Why Rotate Keys?</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="why-rotate-keys" aria-haspopup="dialog" aria-label="Share link: Why Rotate Keys?"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ul> <li><strong>Compliance</strong>: Regulatory requirements (PCI-DSS, HIPAA)</li> <li><strong>Security</strong>: Limit blast radius of key compromise</li> <li><strong>Best Practice</strong>: Regular rotation reduces cryptographic exposure</li> </ul> <h4 id="online-rotation-process" class="position-relative d-flex align-items-center group"> <span>Online Rotation Process</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="online-rotation-process" aria-haspopup="dialog" aria-label="Share link: Online Rotation Process"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Rotate field encryption key (FEK)</span> </span></span><span class="line"><span class="cl">geode key rotate --tenant default --schema Customer --field ssn --scope FEK </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Check rotation status</span> </span></span><span class="line"><span class="cl">geode show rotation-status --tenant default </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Background re-encryption progress</span> </span></span><span class="line"><span class="cl"><span class="c1"># Records migrated: 12,450 / 50,000 (24.9%)</span> </span></span><span class="line"><span class="cl"><span class="c1"># Estimated completion: 2h 15m</span> </span></span></code></pre></div><p><strong>How it works</strong>:</p> <ol> <li><strong>Create new key version</strong> (vN+1)</li> <li><strong>New writes</strong> use vN+1 immediately</li> <li><strong>Background migration</strong> re-encrypts existing records</li> <li><strong>Mixed-version reads</strong> supported during migration</li> <li><strong>Opportunistic re-encryption</strong> on reads</li> </ol> <h4 id="rotation-scopes" class="position-relative d-flex align-items-center group"> <span>Rotation Scopes</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="rotation-scopes" aria-haspopup="dialog" aria-label="Share link: Rotation Scopes"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><table> <thead> <tr> <th>Scope</th> <th>Impact</th> <th>Downtime</th> <th>Use Case</th> </tr> </thead> <tbody> <tr> <td><strong>FEK</strong></td> <td>Re-encrypts field data</td> <td>None</td> <td>Regular rotation (90d-1y)</td> </tr> <tr> <td><strong>SK</strong></td> <td>Rewraps FEKs (no data change)</td> <td>None</td> <td>Schema key compromise</td> </tr> <tr> <td><strong>TRK</strong></td> <td>Rewraps all keys</td> <td>None</td> <td>Tenant key compromise</td> </tr> </tbody> </table> <h4 id="rotation-best-practices" class="position-relative d-flex align-items-center group"> <span>Rotation Best Practices</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="rotation-best-practices" aria-haspopup="dialog" aria-label="Share link: Rotation Best Practices"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ol> <li><strong>Schedule regular rotations</strong>: 90 days for PII, 365 days for less sensitive</li> <li><strong>Monitor progress</strong>: Check migration status regularly</li> <li><strong>Plan for load</strong>: Background re-encryption consumes I/O</li> <li><strong>Test in staging</strong>: Verify rotation process before production</li> <li><strong>Audit rotation</strong>: Log all key rotation events</li> </ol> <h3 id="migrating-existing-data" class="position-relative d-flex align-items-center group"> <span>Migrating Existing Data</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="migrating-existing-data" aria-haspopup="dialog" aria-label="Share link: Migrating Existing Data"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="scenario-adding-encryption-to-existing-schema" class="position-relative d-flex align-items-center group"> <span>Scenario: Adding Encryption to Existing Schema</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="scenario-adding-encryption-to-existing-schema" aria-haspopup="dialog" aria-label="Share link: Scenario: Adding Encryption to Existing Schema"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">1</span><span class="err">.</span><span class="w"> </span><span class="py">Alter</span><span class="w"> </span><span class="kd">schema</span><span class="w"> </span><span class="py">to</span><span class="w"> </span><span class="py">add</span><span class="w"> </span><span class="py">encryption</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Customer</span><span class="w"> </span><span class="py">ALTER</span><span class="w"> </span><span class="py">PROPERTY</span><span class="w"> </span><span class="py">ssn</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="nd">@encrypted</span><span class="p">(</span><span class="py">alg</span><span class="p">:</span><span class="s">&#34;AES-256-GCM&#34;</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">SET</span><span class="w"> </span><span class="nd">@classify</span><span class="p">(</span><span class="py">tags</span><span class="p">:[</span><span class="s">&#34;PII&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;Restricted&#34;</span><span class="p">])</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nc">SET</span><span class="w"> </span><span class="nd">@visible</span><span class="p">(</span><span class="py">to_roles</span><span class="p">:[</span><span class="s">&#34;compliance_officer&#34;</span><span class="p">])</span><span class="err">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="nc">2</span><span class="err">.</span><span class="w"> </span><span class="py">New</span><span class="w"> </span><span class="py">writes</span><span class="w"> </span><span class="py">are</span><span class="w"> </span><span class="py">encrypted</span><span class="w"> </span><span class="py">immediately</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="py">3</span><span class="err">.</span><span class="w"> </span><span class="py">Existing</span><span class="w"> </span><span class="py">plaintext</span><span class="w"> </span><span class="py">data</span><span class="w"> </span><span class="py">remains</span><span class="w"> </span><span class="py">until</span><span class="w"> </span><span class="py">migration</span><span class="w"> </span></span></span></code></pre></div> <h4 id="running-migration" class="position-relative d-flex align-items-center group"> <span>Running Migration</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="running-migration" aria-haspopup="dialog" aria-label="Share link: Running Migration"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Encrypt existing plaintext data</span> </span></span><span class="line"><span class="cl">geode migrate encrypt <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --tenant default <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --field Customer.ssn <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --batch <span class="m">1000</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --progress </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Output:</span> </span></span><span class="line"><span class="cl"><span class="c1"># Encrypting Customer.ssn...</span> </span></span><span class="line"><span class="cl"><span class="c1"># Batch 1: 1000/50000 (2.0%) - 1.2s</span> </span></span><span class="line"><span class="cl"><span class="c1"># Batch 2: 2000/50000 (4.0%) - 1.1s</span> </span></span><span class="line"><span class="cl"><span class="c1"># ...</span> </span></span><span class="line"><span class="cl"><span class="c1"># Complete: 50000/50000 (100%) - 62.5s</span> </span></span></code></pre></div><p><strong>Migration features</strong>:</p> <ul> <li><strong>Resumable</strong>: Can restart after failure</li> <li><strong>Batched</strong>: Processes records in configurable batches</li> <li><strong>Progress tracking</strong>: Real-time migration status</li> <li><strong>Zero downtime</strong>: Reads continue during migration</li> </ul> <h4 id="access-during-migration" class="position-relative d-flex align-items-center group"> <span>Access During Migration</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="access-during-migration" aria-haspopup="dialog" aria-label="Share link: Access During Migration"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><table> <thead> <tr> <th>User Role</th> <th>Before Migration</th> <th>During Migration</th> <th>After Migration</th> </tr> </thead> <tbody> <tr> <td>Authorized</td> <td>Plaintext</td> <td>Plaintext (auto-decrypt)</td> <td>Plaintext</td> </tr> <tr> <td>Unauthorized</td> <td>Plaintext</td> <td><code>[REDACTED]</code></td> <td><code>[REDACTED]</code></td> </tr> </tbody> </table> <h3 id="performance" class="position-relative d-flex align-items-center group"> <span>Performance</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="performance" aria-haspopup="dialog" aria-label="Share link: Performance"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="benchmarks" class="position-relative d-flex align-items-center group"> <span>Benchmarks</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="benchmarks" aria-haspopup="dialog" aria-label="Share link: Benchmarks"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><table> <thead> <tr> <th>Operation</th> <th>Expected Behavior</th> </tr> </thead> <tbody> <tr> <td>Encrypt field (AES-256-GCM)</td> <td>Microsecond-scale overhead</td> </tr> <tr> <td>Decrypt field (cache hit)</td> <td>Microsecond-scale overhead</td> </tr> <tr> <td>Blind index computation</td> <td>Microsecond-scale overhead</td> </tr> <tr> <td>Key cache lookup</td> <td>Microsecond-scale overhead</td> </tr> </tbody> </table> <p><strong>Hardware</strong>: x86-64 with AES-NI, 4-core CPU</p> <h4 id="optimization-tips" class="position-relative d-flex align-items-center group"> <span>Optimization Tips</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="optimization-tips" aria-haspopup="dialog" aria-label="Share link: Optimization Tips"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ol> <li><strong>Selective encryption</strong>: Only encrypt truly sensitive fields</li> <li><strong>Key caching</strong>: KeyManager maintains LRU cache (95%+ hit rate)</li> <li><strong>Batch operations</strong>: Encrypt/decrypt multiple fields in parallel</li> <li><strong>Hardware acceleration</strong>: AES-NI auto-detected and used</li> <li><strong>Searchable sparingly</strong>: Blind indexes add 30-50% overhead</li> </ol> <h4 id="monitoring" class="position-relative d-flex align-items-center group"> <span>Monitoring</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="monitoring" aria-haspopup="dialog" aria-label="Share link: Monitoring"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Check key cache performance</span> </span></span><span class="line"><span class="cl">geode stats key-cache </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Output:</span> </span></span><span class="line"><span class="cl"><span class="c1"># Key Cache Statistics:</span> </span></span><span class="line"><span class="cl"><span class="c1"># Hits: 125,340</span> </span></span><span class="line"><span class="cl"><span class="c1"># Misses: 5,612</span> </span></span><span class="line"><span class="cl"><span class="c1"># Hit Rate: 95.7%</span> </span></span><span class="line"><span class="cl"><span class="c1"># Evictions: 234</span> </span></span></code></pre></div> <h3 id="security-considerations" class="position-relative d-flex align-items-center group"> <span>Security Considerations</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="security-considerations" aria-haspopup="dialog" aria-label="Share link: Security Considerations"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="threat-model" class="position-relative d-flex align-items-center group"> <span>Threat Model</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="threat-model" aria-haspopup="dialog" aria-label="Share link: Threat Model"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Protected Against</strong>:</p> <ul> <li>✅ Data breach (ciphertext without keys)</li> <li>✅ Ciphertext tampering (authenticated encryption)</li> <li>✅ Context-swapping attacks (AAD binding)</li> <li>✅ Unauthorized plaintext access (RBAC gates)</li> <li>✅ Plaintext in logs (never logged)</li> </ul> <p><strong>Not Protected Against</strong>:</p> <ul> <li>❌ Master key compromise</li> <li>❌ Frequency analysis (blind indexes)</li> <li>❌ Access pattern leakage</li> <li>❌ Memory attacks (cold boot)</li> </ul> <h4 id="best-practices" class="position-relative d-flex align-items-center group"> <span>Best Practices</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="best-practices" aria-haspopup="dialog" aria-label="Share link: Best Practices"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Key Management</strong>:</p> <ul> <li>Store master keys in KMS (AWS KMS, Vault, Azure Key Vault)</li> <li>Rotate keys regularly (FEK: 90d, TRK: 1y)</li> <li>Separate tenant keys</li> <li>Monitor key access</li> </ul> <p><strong>Access Control</strong>:</p> <ul> <li>Principle of least privilege</li> <li>Regular access reviews</li> <li>Audit all READ_PLAINTEXT grants</li> <li>MFA for sensitive role assignment</li> </ul> <p><strong>Operational</strong>:</p> <ul> <li>Never log plaintext or keys</li> <li>Secure memory cleanup (<code>secureZero</code>)</li> <li>Monitor encryption/decryption rates</li> <li>Alert on unusual access patterns</li> </ul> <h4 id="compliance-alignment" class="position-relative d-flex align-items-center group"> <span>Compliance Alignment</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="compliance-alignment" aria-haspopup="dialog" aria-label="Share link: Compliance Alignment"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><table> <thead> <tr> <th>Standard</th> <th>Requirement</th> <th>Geode Support</th> </tr> </thead> <tbody> <tr> <td><strong>GDPR</strong></td> <td>Encryption at rest</td> <td>✅ FLE with AEAD</td> </tr> <tr> <td><strong>GDPR</strong></td> <td>Right to erasure</td> <td>✅ Key destruction</td> </tr> <tr> <td><strong>HIPAA</strong></td> <td>PHI encryption</td> <td>✅ AES-256-GCM</td> </tr> <tr> <td><strong>HIPAA</strong></td> <td>Access controls</td> <td>✅ RBAC gates</td> </tr> <tr> <td><strong>PCI-DSS</strong></td> <td>Cardholder data encryption</td> <td>✅ Field-level encryption</td> </tr> <tr> <td><strong>PCI-DSS</strong></td> <td>Key rotation</td> <td>✅ Online rotation</td> </tr> <tr> <td><strong>SOC 2</strong></td> <td>Confidentiality controls</td> <td>✅ Encryption + audit</td> </tr> </tbody> </table> <h3 id="troubleshooting" class="position-relative d-flex align-items-center group"> <span>Troubleshooting</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="troubleshooting" aria-haspopup="dialog" aria-label="Share link: Troubleshooting"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="issue-permission-denied-on-query" class="position-relative d-flex align-items-center group"> <span>Issue: Permission Denied on Query</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="issue-permission-denied-on-query" aria-haspopup="dialog" aria-label="Share link: Issue: Permission Denied on Query"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Error</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Error: SearchNotPermitted - Cannot filter on encrypted field &#39;ssn&#39; </span></span></code></pre></div><p><strong>Causes</strong>:</p> <ol> <li>Field not marked <code>@searchable</code></li> <li>User lacks <code>READ_PLAINTEXT</code> privilege</li> </ol> <p><strong>Solutions</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Option</span><span class="w"> </span><span class="py">1</span><span class="p">:</span><span class="w"> </span><span class="nc">Make</span><span class="w"> </span><span class="py">field</span><span class="w"> </span><span class="py">searchable</span><span class="w"> </span><span class="p">(</span><span class="py">if</span><span class="w"> </span><span class="py">appropriate</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ALTER</span><span class="w"> </span><span class="py">NODE</span><span class="w"> </span><span class="py">TYPE</span><span class="w"> </span><span class="py">Customer</span><span class="w"> </span><span class="py">ALTER</span><span class="w"> </span><span class="py">PROPERTY</span><span class="w"> </span><span class="py">ssn</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">SET</span><span class="w"> </span><span class="nd">@searchable</span><span class="p">(</span><span class="py">index</span><span class="p">:</span><span class="s">&#34;blind-hmac-sha256&#34;</span><span class="p">)</span><span class="err">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="err">--</span><span class="w"> </span><span class="nc">Option</span><span class="w"> </span><span class="py">2</span><span class="p">:</span><span class="w"> </span><span class="nc">Grant</span><span class="w"> </span><span class="py">user</span><span class="w"> </span><span class="py">access</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">GRANT</span><span class="w"> </span><span class="py">READ_PLAINTEXT</span><span class="w"> </span><span class="py">ON</span><span class="w"> </span><span class="py">Customer</span><span class="err">.</span><span class="py">ssn</span><span class="w"> </span><span class="py">TO</span><span class="w"> </span><span class="py">ROLE</span><span class="w"> </span><span class="py">analyst</span><span class="err">;</span><span class="w"> </span></span></span></code></pre></div> <h4 id="issue-decryption-failures" class="position-relative d-flex align-items-center group"> <span>Issue: Decryption Failures</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="issue-decryption-failures" aria-haspopup="dialog" aria-label="Share link: Issue: Decryption Failures"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Error</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Error: AuthenticationFailed - AEAD tag verification failed </span></span></code></pre></div><p><strong>Causes</strong>:</p> <ol> <li>Corrupted ciphertext</li> <li>Wrong key used</li> <li>AAD mismatch</li> </ol> <p><strong>Solutions</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Check key version consistency</span> </span></span><span class="line"><span class="cl">geode verify encryption --tenant default --schema Customer --field ssn </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Re-encrypt if needed</span> </span></span><span class="line"><span class="cl">geode key rotate --tenant default --schema Customer --field ssn --scope FEK --force </span></span></code></pre></div> <h4 id="issue-slow-query-performance" class="position-relative d-flex align-items-center group"> <span>Issue: Slow Query Performance</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="issue-slow-query-performance" aria-haspopup="dialog" aria-label="Share link: Issue: Slow Query Performance"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Symptom</strong>: Queries on encrypted fields are slow</p> <p><strong>Diagnosis</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Check cache hit rate</span> </span></span><span class="line"><span class="cl">geode stats key-cache </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Profile query</span> </span></span><span class="line"><span class="cl">PROFILE MATCH <span class="o">(</span>c:Customer <span class="o">{</span>email: <span class="s1">&#39;[email protected]&#39;</span><span class="o">})</span> RETURN c<span class="p">;</span> </span></span></code></pre></div><p><strong>Solutions</strong>:</p> <ol> <li>Ensure blind indexes are created</li> <li>Increase key cache size</li> <li>Review access patterns</li> <li>Consider hardware acceleration</li> </ol> <h3 id="advanced-topics" class="position-relative d-flex align-items-center group"> <span>Advanced Topics</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="advanced-topics" aria-haspopup="dialog" aria-label="Share link: Advanced Topics"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="custom-key-providers" class="position-relative d-flex align-items-center group"> <span>Custom Key Providers</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="custom-key-providers" aria-haspopup="dialog" aria-label="Share link: Custom Key Providers"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-zig" data-lang="zig"><span class="line"><span class="cl"><span class="c1">// Implement custom KMS integration </span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span><span class="w"> </span><span class="n">CustomKMSProvider</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kr">pub</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">deriveKey</span><span class="p">(</span><span class="n">context</span><span class="o">:</span><span class="w"> </span><span class="p">[]</span><span class="kr">const</span><span class="w"> </span><span class="kt">u8</span><span class="p">)</span><span class="w"> </span><span class="o">!</span><span class="p">[]</span><span class="kt">u8</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// Call external KMS </span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">};</span><span class="w"> </span></span></span></code></pre></div> <h4 id="streaming-large-fields" class="position-relative d-flex align-items-center group"> <span>Streaming Large Fields</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="streaming-large-fields" aria-haspopup="dialog" aria-label="Share link: Streaming Large Fields"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>For fields &gt;64KB:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-zig" data-lang="zig"><span class="line"><span class="cl"><span class="c1">// Use streaming encryption </span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span><span class="w"> </span><span class="n">encrypted_stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="n">aead</span><span class="p">.</span><span class="n">encryptStream</span><span class="p">(</span><span class="n">plaintext_reader</span><span class="p">,</span><span class="w"> </span><span class="n">fek</span><span class="p">);</span><span class="w"> </span></span></span></code></pre></div> <h4 id="post-quantum-cryptography" class="position-relative d-flex align-items-center group"> <span>Post-Quantum Cryptography</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="post-quantum-cryptography" aria-haspopup="dialog" aria-label="Share link: Post-Quantum Cryptography"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Future support for PQC:</p> <ul> <li>Kyber for key wrapping</li> <li>Dilithium for signatures</li> <li>CRYSTALS suite integration</li> </ul> <h3 id="next-steps" class="position-relative d-flex align-items-center group"> <span>Next Steps</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="next-steps" aria-haspopup="dialog" aria-label="Share link: Next Steps"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><ul> <li><a href="/docs/security/kms-integration/" >KMS Integration</a> - External key management</li> <li><a href="/docs/security/overview/" >Security Overview</a> - Complete security architecture</li> <li><a href="/docs/security/authorization/" >Authorization Guide</a> - Role-based access control</li> <li><a href="/docs/ops/audit-logging/" >Audit Logging</a> - Encryption audit trail</li> <li><a href="/docs/configuration/server-configuration/" >Server Configuration</a> - Encryption settings</li> </ul> <h3 id="references" class="position-relative d-flex align-items-center group"> <span>References</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="references" aria-haspopup="dialog" aria-label="Share link: References"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><ul> <li><a href="https://csrc.nist.gov/publications/detail/sp/800-38d/final" aria-label="NIST SP 800-38D – opens in new window" target="_blank" rel="noopener noreferrer" >NIST SP 800-38D <span aria-hidden="true" class="external-icon">↗</span> </a> - GCM specification</li> <li><a href="https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final" aria-label="NIST SP 800-57 – opens in new window" target="_blank" rel="noopener noreferrer" >NIST SP 800-57 <span aria-hidden="true" class="external-icon">↗</span> </a> - Key management</li> <li><a href="https://datatracker.ietf.org/doc/html/rfc5869" aria-label="RFC 5869 – opens in new window" target="_blank" rel="noopener noreferrer" >RFC 5869 <span aria-hidden="true" class="external-icon">↗</span> </a> - HKDF specification</li> <li><a href="https://www.iso.org/standard/76120.html" aria-label="ISO/IEC 39075:2024 – opens in new window" target="_blank" rel="noopener noreferrer" >ISO/IEC 39075:2024 <span aria-hidden="true" class="external-icon">↗</span> </a> - GQL standard</li> </ul> <hr> <p><strong>License</strong>: Apache License 2.0 <strong>Copyright</strong>: 2024-2025 CodePros <strong>Last Updated</strong>: January 2026</p>