-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
361 lines (347 loc) · 29.5 KB
/
Copy pathindex.html
File metadata and controls
361 lines (347 loc) · 29.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>helix — Health data that can't become someone else's bankruptcy asset.</title>
<meta name="description" content="Health data that can't become someone else's bankruptcy asset.">
<meta name="author" content="Independent explainer for stuinfla's helix — built by Stuart Kerr at ISOvision.ai">
<link rel="canonical" href="https://helix-explainer.netlify.app/">
<meta name="theme-color" content="#2ee6d6">
<meta property="og:type" content="website">
<meta property="og:title" content="helix — Health data that can't become someone else's bankruptcy asset.">
<meta property="og:description" content="Health data that can't become someone else's bankruptcy asset.">
<meta property="og:url" content="https://helix-explainer.netlify.app/">
<meta property="og:image" content="https://helix-explainer.netlify.app/assets/social-card.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="helix — Health data that can't become someone else's bankruptcy asset.">
<meta name="twitter:description" content="Health data that can't become someone else's bankruptcy asset.">
<meta name="twitter:image" content="https://helix-explainer.netlify.app/assets/social-card.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/favicon-16.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32.png">
<link rel="icon" type="image/png" sizes="48x48" href="assets/favicon-48.png">
<link rel="icon" type="image/png" sizes="192x192" href="assets/favicon-192.png">
<link rel="icon" type="image/png" sizes="512x512" href="assets/favicon-512.png">
<link rel="icon" href="assets/favicon.ico" sizes="any">
<link rel="apple-touch-icon" href="assets/apple-touch-icon.png">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600;9..144,700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap">
<link rel="stylesheet" href="styles.css">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "helix",
"description": "Health data that can't become someone else's bankruptcy asset.",
"url": "https://helix-explainer.netlify.app/",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Cross-platform",
"image": "https://helix-explainer.netlify.app/assets/social-card.png",
"author": {
"@type": "Person",
"name": "stuinfla"
},
"codeRepository": "https://github.com/stuinfla/helix",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
}
}
</script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<div class="prov-banner">
<div class="wrap prov-banner-inner">
<p class="prov-attr">An independent explainer for <strong>stuinfla</strong>'s <a href="https://github.com/stuinfla/helix" target="_blank" rel="noopener">helix</a> — built to help you actually implement it.</p>
<p class="prov-live"><span class="prov-dot" aria-hidden="true">●</span> source <code>github.com/stuinfla/helix</code></p>
</div>
</div>
<header class="site-head">
<div class="wrap">
<a class="brand" href="#top" aria-label="helix explainer home">
<svg class="logo" viewBox="0 0 32 32" aria-hidden="true">
<rect x="3" y="3" width="26" height="26" rx="8" fill="none" stroke="var(--accent)" stroke-width="2"></rect>
<rect x="9" y="9" width="14" height="14" rx="4" fill="var(--accent-2)"></rect>
<circle cx="16" cy="16" r="3" fill="var(--on-accent)"></circle>
</svg>
<span>helix</span>
</a>
<nav class="nav-links" aria-label="Sections">
<a href="#what-it-is">What it is</a>
<a href="#how-it-works">How it works</a>
<a href="#use-cases">Use cases</a>
<a href="#get-started">Get started</a>
<a href="#the-pack">AI pack</a>
<a href="https://github.com/stuinfla/helix" target="_blank" rel="noopener">GitHub ↗</a>
</nav>
</div>
</header>
<main id="main">
<a id="top"></a>
<section class="hero">
<div class="wrap">
<div class="hero-grid">
<div>
<span class="eyebrow">A health record built to survive the company that made it</span>
<h1>Keep your health data under your own control, not a company's</h1>
<p class="lede">Helix is software for keeping your own health information — lab results, genetic data, day-to-day readings — under your control instead of a company's. It's a Rust and JavaScript toolkit, built in the open, and every claim on this page is checked against the project's actual source code and design records rather than summarized from memory.</p>
<p class="sub">What follows shows the reasoning before the conclusion: the problem this is answering, what the project actually does about it, and how to run it yourself and check.</p>
<p class="attrib-lede">An <strong>independent explainer</strong> for <strong>stuart kerr <span class="attrib-handle">(stuinfla)</span></strong>'s <a href="https://github.com/stuinfla/helix" target="_blank" rel="noopener">helix</a> — built to take you from "never seen it" to "ready to implement".</p>
<div class="cta-row">
<a class="cta" href="#get-started">Get started</a>
<a class="cta ghost" href="https://github.com/stuinfla/helix" target="_blank" rel="noopener">View on GitHub</a>
</div>
<div class="meta-row"><span><b>Built with</b> Rust + npm (JavaScript/TypeScript)</span><span><b>Encrypted vault</b> Implemented and tested</span><span><b>Internal components</b> 32 packages</span></div>
</div>
<figure class="hero-art">
<button type="button" class="diagram-zoom" data-src="assets/hero.png" data-alt="helix: A double helix built not from base pairs but from proof: one strand carries vitals, genome, and lab scans; the other an unbroken chain of witnessed provenance; both twist downward and seal into a vault whose only key belongs to you." aria-label="Enlarge: helix: A double helix built not from base pairs but from proof: one strand carries vitals, genome, and lab scans; the other an unbroken chain of witnessed provenance; both twist downward and seal into a vault whose only key belongs to you."><img src="assets/hero.png" alt="helix: A double helix built not from base pairs but from proof: one strand carries vitals, genome, and lab scans; the other an unbroken chain of witnessed provenance; both twist downward and seal into a vault whose only key belongs to you."></button>
</figure>
</div>
</div>
</section>
<div class="sections">
<div class="wrap">
<details class="section" id="problem" open>
<summary>
<span class="num">01</span>
<span class="head-text">
<h2>What happens to your data when the company doesn't survive you</h2>
<span class="q">Why should I care?</span>
</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="body">
<p class="lead-in">Imagine handing a stranger a sample that reveals your ancestry, your disease risks, and clues about your relatives — then trusting that stranger to keep it safe forever, because unlike a password, you can never get a new one.</p>
<p>That's roughly the deal behind consumer genetic testing. On March 23, 2025, one of the best-known companies in that business, 23andMe, filed for bankruptcy — holding a database of genetic information from about 15 million people, built up over a decade of selling genetic test kits directly to customers. When a company files for bankruptcy, its assets get sold off to pay what it owes, and a court approved selling that same genetic database to a newly formed buyer.</p>
<p>Most people assume information this personal is automatically protected by law. It usually isn't, here: the main U.S. medical privacy law, HIPAA (a law that limits what hospitals, insurers, and doctors' offices can do with your medical records), only covers care providers like those. A company that sells you a genetic test straight from its website, with no doctor involved, falls outside it — so this kind of data can move through a breach, a sale, or a bankruptcy with none of the legal protection a hospital chart would carry.</p>
<p>And the stakes are lopsided in a way a leaked password never is. You can cancel a stolen credit card and reset a compromised login. You cannot issue yourself new genetic material. Once genetic or health data leaves your control — through a breach, or simply because the company holding it changed hands — there is no undo.</p>
<figure class="figure">
<span class="tier friendly">The problem</span>
<button type="button" class="diagram-zoom" data-src="assets/problem.png" data-alt="helix: the problem" aria-label="Enlarge: helix: the problem"><img src="assets/problem.png" alt="helix: the problem" loading="lazy"></button>
</figure>
</div>
</details>
<details class="section" id="what-it-is" open>
<summary>
<span class="num">02</span>
<span class="head-text">
<h2>A record that lives with you, not with a company</h2>
<span class="q">What is this, actually?</span>
</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="body">
<p class="lead-in">Helix takes the opposite arrangement: your health data sits in a personal, encrypted file on your own device, and the software is built so that file — not a company's server — is the one copy that matters.</p>
<p>The project's own name for this is 'local-first' storage: instead of your information living primarily on a company's server, it lives primarily on your own device, encrypted, and nothing more than what you choose ever needs to leave it. The project's own design write-up for this choice, marked Implemented, describes it as a user-owned, encrypted health vault, and the encryption itself is built and has its own passing tests inside the project. That's the whole point of the arrangement: the vault doesn't check whether the company that built it is still in business before it opens.</p>
<p>In practice, that vault is meant to hold more than one kind of record — lab results, genetic test files, day-to-day health readings — and the rest of the project, more than thirty separate internal pieces by its own count, is built to read, score, and explain what's inside that vault without needing to move it somewhere else first.</p>
<figure class="figure diagram concept">
<span class="tier tech">The big idea</span>
<button type="button" class="diagram-zoom" data-src="assets/big-idea.svg" data-alt="Every reading is captured, provenance-stamped, scored, witnessed, and sealed into a vault only you can open." aria-label="Enlarge: Every reading is captured, provenance-stamped, scored, witnessed, and sealed into a vault only you can open."><img src="assets/big-idea.svg" alt="Every reading is captured, provenance-stamped, scored, witnessed, and sealed into a vault only you can open." loading="lazy"></button>
</figure>
<table class="tbl"><caption class="visually-hidden">What changes versus a typical health app</caption>
<thead><tr><th>Aspect</th><th>Detail</th></tr></thead>
<tbody>
<tr><td>Where the data lives</td><td>Encrypted, on your own device — not primarily on a company's server</td></tr>
<tr><td>Who can unlock it</td><td>You. The vault is described as user-owned by design in the project's own design record, and marked as implemented</td></tr>
<tr><td>What it's built to hold</td><td>Lab results, genetic files, day-to-day health readings, and more</td></tr>
<tr><td>How it's built</td><td>Rust for the core engine and the vault itself; npm/JavaScript for tooling and browser-facing parts</td></tr>
</tbody>
</table>
</div>
</details>
<details class="section" id="the-insight" open>
<summary>
<span class="num">03</span>
<span class="head-text">
<h2>One rule, applied to everything it touches</h2>
<span class="q">What's the one thing I need to get?</span>
</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="body">
<p class="lead-in">Local, encrypted storage solves where your data sits. It doesn't automatically solve what the software is allowed to tell you about it — and that's the part Helix seems most careful about.</p>
<p>Every piece of information that goes into Helix carries a running note of where it came from and how much weight it's allowed to carry — a lab-confirmed result is treated differently from a guess inferred from a wifi signal in your house, and the system is built to keep that difference visible rather than flattening everything into one number.</p>
<p>The second half of the rule: nothing Helix shows you is allowed to read as a diagnosis. The project's own design notes describe its outputs as screening flags: a possible-distress reading, or an aging estimate, is meant as a prompt to go check with someone actually qualified to diagnose something — not a verdict, and deliberately capped in how confident it's allowed to sound.</p>
<figure class="figure diagram concept">
<span class="tier tech">The aha</span>
<button type="button" class="diagram-zoom" data-src="assets/insight.svg" data-alt="Cryptographic proof is attached the instant data is captured, so trust travels with the data instead of depending on a central server." aria-label="Enlarge: Cryptographic proof is attached the instant data is captured, so trust travels with the data instead of depending on a central server."><img src="assets/insight.svg" alt="Cryptographic proof is attached the instant data is captured, so trust travels with the data instead of depending on a central server." loading="lazy"></button>
</figure>
<p class="oh">The most important thing Helix does isn't sense, score, or store your health data — it's refuse to let any of those things sound more certain than they've actually earned.</p>
</div>
</details>
<details class="section" id="how-it-works" open>
<summary>
<span class="num">04</span>
<span class="head-text">
<h2>Underneath: one spine, several senses feeding it</h2>
<span class="q">How does it actually work?</span>
</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="body">
<p class="lead-in">The architecture follows that rule fairly literally. Most of Helix's internal components — the project counts more than thirty — are built to depend on one shared piece: the one that carries the where-did-this-come-from-and-how-sure-are-we note, which the project calls a provenance record.</p>
<p>Different kinds of health information get pulled in through their own dedicated pieces, but each writes into that same shared record. A scanned or photographed lab report gets read by an OCR component (optical character recognition — software that turns an image of text into text a computer can search). A genetic test file gets checked against known pharmacogenomics markers (how a person's genes affect their response to specific medications). Sensor-style signals — the project's example is inferring things like a possible fall or a long stretch of inactivity from ordinary wifi signals in a home — run through a component it calls an escalation guardian, which is deliberately narrow: it only outputs one of a small number of plain risk words, the project's own examples being 'none,' 'urgent,' and 'critical,' never a specific claim about what's actually wrong.</p>
<p>One concrete example ships in the project's own demo: a biological-age estimate using PhenoAge, a published formula that reads blood-panel markers and estimates how old a body's biology looks versus its calendar age — shown on Helix's dashboard as a difference, with the project's own worked example reading 42.5 years, 7.5 years younger than calendar age, next to an explicit note that it is not a medical diagnosis. A separate search component lets Helix find related pieces of a person's own history by meaning rather than requiring an exact keyword match.</p>
<p>When Helix contributes information to a wider research group instead of just showing it back to one person, it adds an extra step: values get grouped together, any group small enough to point back to one identifiable person gets suppressed, and a calibrated amount of random statistical noise — a differential-privacy technique, a mathematical way of adding just enough randomness that no individual's data can be picked back out of the result — gets layered on top. If that process can't be done safely, the component is built to refuse to answer rather than guess.</p>
<div class="dual">
<figure class="figure diagram">
<span class="tier tech">Architecture</span>
<button type="button" class="diagram-zoom" data-src="assets/architecture.svg" data-alt="helix-provenance sits at the core; sensing, genome, OCR, and retrieval components all feed evidence into it, while the vault, verifier, and scoring/dashboard layers all depend on that same provenance record." aria-label="Enlarge: helix-provenance sits at the core; sensing, genome, OCR, and retrieval components all feed evidence into it, while the vault, verifier, and scoring/dashboard layers all depend on that same provenance record."><img src="assets/architecture.svg" alt="helix-provenance sits at the core; sensing, genome, OCR, and retrieval components all feed evidence into it, while the vault, verifier, and scoring/dashboard layers all depend on that same provenance record." loading="lazy"></button>
<figcaption>Architecture — modules, components and how they depend on each other.</figcaption>
</figure>
<figure class="figure diagram">
<span class="tier tech">Data flow</span>
<button type="button" class="diagram-zoom" data-src="assets/flow.svg" data-alt="A reading is captured, stamped with provenance, checked against escalation thresholds, cryptographically verified, then sealed into the user's local encrypted vault." aria-label="Enlarge: A reading is captured, stamped with provenance, checked against escalation thresholds, cryptographically verified, then sealed into the user's local encrypted vault."><img src="assets/flow.svg" alt="A reading is captured, stamped with provenance, checked against escalation thresholds, cryptographically verified, then sealed into the user's local encrypted vault." loading="lazy"></button>
<figcaption>Data flow — how a request moves through the system at runtime.</figcaption>
</figure>
</div>
</div>
</details>
<details class="section" id="use-cases" open>
<summary>
<span class="num">05</span>
<span class="head-text">
<h2>Where this actually gets used</h2>
<span class="q">Where would I actually use this?</span>
</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="body">
<p class="lead-in">None of this matters if it doesn't map onto something you'd actually sit down and do. Three shapes that fit what's built:</p>
<figure class="figure">
<span class="tier friendly">In the real world</span>
<button type="button" class="diagram-zoom" data-src="assets/useCase.png" data-alt="helix in use" aria-label="Enlarge: helix in use"><img src="assets/useCase.png" alt="helix in use" loading="lazy"></button>
</figure>
<div class="gallery"><div class="grid">
<details class="case" open>
<summary>
<span class="uc-num">1</span>
<span class="uc-title">Turning a drawer of old lab PDFs into one legible timeline</span>
<span class="uc-tag">For anyone with years of scattered results</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="uc-body">
<p>If your lab results are spread across three patient portals and a shoebox of scanned printouts from old visits, Helix's OCR component is built to read exactly that kind of file, and its onboarding script is built to bring it into your own encrypted vault rather than yet another company's server.</p>
<p>Once it's in, the point isn't a new place to lose the paperwork — it's a single, on-device timeline you can search by meaning, not by remembering which folder a result is sitting in.</p>
</div>
</details>
<details class="case" open>
<summary>
<span class="uc-num">2</span>
<span class="uc-title">Getting a more specific read on a DNA kit you already have</span>
<span class="uc-tag">For someone who already has a raw genetic file</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="uc-body">
<p>Consumer DNA kits are usually sold for ancestry and broad risk estimates. Helix's genome-ingestion component is built to instead check that same file against known pharmacogenomics markers — how specific genes affect the way a body processes particular medications — surfaced as a screening flag with a stated confidence, worth bringing to a pharmacist or doctor, not a substitute for one.</p>
<p>It also means that raw file doesn't need to be re-uploaded to a third site to get that read — it's checked inside the vault it already sits in.</p>
</div>
</details>
<details class="case" open>
<summary>
<span class="uc-num">3</span>
<span class="uc-title">Contributing to research without handing over your raw record</span>
<span class="uc-tag">For a cohort or research contributor</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="uc-body">
<p>Researchers usually need patterns across many people, not any one person's raw file. Helix's cohort-federation component is built for exactly that boundary — generalizing, suppressing small groups, adding calibrated statistical noise, and refusing outright when it can't do that safely — so what leaves your device is aggregate and privacy-protected by design, never your raw record.</p>
</div>
</details>
</div></div>
</div>
</details>
<details class="section" id="get-started" open>
<summary>
<span class="num">06</span>
<span class="head-text">
<h2>Run it yourself</h2>
<span class="q">Can I run this myself, right now?</span>
</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="body">
<p class="lead-in">Helix is a mixed Rust-and-npm project, so its own test commands call both toolchains. Here's the real sequence, taken straight from the project's own scripts and Makefile.</p>
<div class="install-block"><pre class="code-block"><code>npm install</code></pre></div>
<ol class="steps">
<li><strong>Install the prerequisites</strong> You'll need Node.js (for npm install) and the Rust toolchain, including cargo, since several of the project's own test commands call cargo directly.</li>
<li><strong>Clone the repository and install the JavaScript side</strong> git clone https://github.com/stuinfla/helix, then cd helix && npm install. You'll see npm resolve the project's JavaScript-side dependencies, including its local embedding-model and vector-storage libraries.</li>
<li><strong>Build and test the whole project</strong> Run make build, then make test. If both finish clean, you have a working local build of Helix's crates — including the vault and the scoring pipeline — compiled and passing their own test suite.</li>
<li><strong>Run the Rust-side checks directly</strong> cargo test -p cog-helix-health -p helix-rvf-index runs the test suites for two of the core crates. cargo fmt -p cog-helix-health --check and cargo fmt -p helix-rvf-index --check confirm formatting; cargo clippy -p cog-helix-health -p helix-rvf-index --all-targets checks for lint issues. All should exit without errors.</li>
<li><strong>Bring in a real record</strong> node scripts/onboard_person.mjs --tenant <slug> --source <path> --sex <f|m|x> [--life-stage …] encodes a source file — a lab export, a genetic file — into that person's own encrypted vault under a tenant slug you choose. This is the step where it stops being a codebase you built and starts being a record you own.</li>
<li><strong>See it summarized</strong> node scripts/daily_brief.mjs generates a plain-language brief from whatever is in the vault so far — a natural next step once you've onboarded a real or test record, and a quick way to see the provenance and screening-flag framing described above actually rendered.</li>
</ol>
</div>
</details>
<details class="section" id="the-pack" open>
<summary>
<span class="num">07</span>
<span class="head-text">
<h2>Take the deeper layer with you</h2>
<span class="q">Does my AI get it too?</span>
</span>
<span class="chev" aria-hidden="true">›</span>
</summary>
<div class="body">
<p class="lead-in">This page moves at a walking pace on purpose. The knowledge pack behind it holds the source this page was built from — the project's design records, the component map, the passage-level excerpts — so you (or the skeptical engineer you forward this to) can check any claim above against the original.</p>
<div class="tree" style="white-space:pre"><span class="cmt"># helix-knowledge-pack.zip</span>
<span class="d">for-ai/</span> <span class="cmt"># wire this into your agent</span>
<span class="f">helix-kb.rvf</span> <span class="cmt"># 384-dim vector brain (semantic search)</span>
<span class="f">helix-kb.passages.jsonl</span> <span class="cmt"># full passage text (search returns TEXT)</span>
<span class="f">helix-symbols.json</span> <span class="cmt"># exact public API</span>
<span class="f">helix-dep-graph.json</span> <span class="cmt"># what depends on what</span>
<span class="f">helix-entrypoints.json</span> <span class="cmt"># build / test / run commands</span>
<span class="f">ask-kb.mjs</span> · <span class="f">kb-mcp-server.mjs</span> <span class="cmt"># CLI + MCP search server</span>
<span class="d heart">for-humans/</span> <span class="cmt"># read first</span>
<span class="f heart">helix-primer.md</span> <span class="cmt"># the human orientation</span></div>
<div class="dl-cta"><a class="cta" href="helix-knowledge-pack.zip" download>Download the knowledge pack</a><span class="dl-meta">RVF vector KB + MCP server — drop it into your own agent.</span></div>
<a class="dropzone" href="helix-knowledge-pack.zip" download><span class="dz-icon" aria-hidden="true">↓</span><strong>Give your AI the same understanding</strong><span class="dz-hint">helix-knowledge-pack.zip</span></a>
</div>
</details>
</div>
</div>
</main>
<footer class="explainer-footer" role="contentinfo">
<div class="wrap explainer-footer-inner">
<p class="ef-credit">
Explainer page created by <strong><a href="https://stuart-kerr-card.netlify.app" rel="author noopener" target="_blank">Stuart Kerr</a></strong> at
<a href="https://isovision.ai" rel="noopener" target="_blank">ISOvision</a>
<span class="ef-fine">Built with the open-source <a href="https://github.com/stuinfla/Repo-Explainer" rel="noopener" target="_blank">explainmyrepo</a> engine.
Found this valuable? <a href="https://github.com/stuinfla/Repo-Explainer" rel="noopener" target="_blank">A star on GitHub</a> genuinely helps —
and if something's off, <a href="https://github.com/stuinfla/Repo-Explainer/issues" rel="noopener" target="_blank">open an issue</a>: happy to help fix it.</span>
</p>
<a class="ef-cta" href="https://explainmyrepo.isovision.ai" target="_blank" rel="noopener">
<span class="ef-cta-lead">Would you like your own repo explainer page?</span>
<strong>Generate one here</strong>
<span class="ef-arrow" aria-hidden="true">→</span>
</a>
</div>
</footer>
<dialog class="diagram-lightbox" id="diagram-lightbox" aria-label="Enlarged diagram">
<button type="button" class="lightbox-close" data-close aria-label="Close">×</button>
<img id="diagram-lightbox-img" src="" alt="">
</dialog>
<script>
(function () {
var dlg = document.getElementById('diagram-lightbox');
if (!dlg || typeof dlg.showModal !== 'function') return;
var img = document.getElementById('diagram-lightbox-img');
document.querySelectorAll('.diagram-zoom').forEach(function (btn) {
btn.addEventListener('click', function () {
img.src = btn.getAttribute('data-src');
img.alt = btn.getAttribute('data-alt') || '';
dlg.showModal();
});
});
dlg.addEventListener('click', function (e) {
if (e.target === dlg || e.target.hasAttribute('data-close')) dlg.close();
});
})();
</script>
</body>
</html>