Arkhelion
The intelligence that is on your side. Your life, connected.
01The proof
What the research found
Peer-reviewed measurements, not vendor surveys. The 79-app sample was the NHS's own accredited library, the curated end of the market rather than the open store, which makes zero the flattering figure for the field. Of 73 mental-health apps claiming effectiveness, one cited published literature.6 Symptom checkers gave the right diagnosis first 34% of the time.7 Around 11% of consumer wearables have been validated for even one biometric measure.8
Where this lands
| Strict | Generous | |
|---|---|---|
| Developers worldwide 10 | 47,200,000 | 47,200,000 |
| Build desktop software 11 | 4.3% | 53% |
| Write Rust 11 | 14.8% | 14.8% |
| Automated testing 11 | 56.3% | 56.3% |
| Verified backup restore 12 | 35% | 35% |
| Remaining | 59,190 | 729,552 |
Base is SlashData's bottom-up estimate, not GitHub's 180 million account count. Desktop share appears at both ends because two surveys ask different questions: 4.3% name it as their job title, 53% report any desktop activity. Two honest caveats: multiplying survey percentages assumes independence, and Rust developers skew toward desktop work, so the truth leans generous. Two of the four factors are measured per organisation rather than per person.
Rarer than any factor in that table
50 to 200 applications worldwide combine this stack.
Estimated. 80,288 Cargo manifests reference Tauri; only 754 reference SQLCipher across all of Rust. Taking Tauri's plausible share of those gives 75 to 190, less abandoned repositories. Observed 2026-07-26.
Under 1 in 1,000 applications encrypt their database this way at all.
SQLCipher's publisher claims thousands of applications against roughly 4.4 million in the two major stores.13 Signal uses it, which is the useful comparison: same library, same settings, checkable in Signal's public source.
The test suite sits in the top 15% of open-source projects.
38% of open-source projects have no tests at all and 85% have fewer than 100, measured across more than 20,000 projects.9 This has 240 test attributes, roughly one per 122 lines of Rust.
Under 1 in 200 individuals run a verified, automated restore.
Estimated from measured inputs: 33% back up regularly, 46% have never tested a restore, and a scheduled drill is stricter again. Organisations are the sanity check: 90% express confidence, 28% fully recovered when it mattered.12 This one ran on 2026-07-24 against a 935 MB encrypted vault and passed. It repeats weekly.
Around 1 in 5,000 developers build their own AI tooling.
Estimated. Roughly 4,900 files on GitHub sit in a .claude/hooks path and about 22,000 tool servers are published across registries, suggesting 5,000 to 25,000 people building rather than using. Against 47.2 million that is 0.01 to 0.05%. Stack Overflow found 52% of developers do not use AI agents at all.11
02What Arkhelion is
The idea
Your life produces signal constantly. Your body, your calendar, your work, the things you write down. It sits in a dozen services that never speak to each other, and nobody sees the whole picture. Not your doctor, not your apps, not you.
Arkhelion connects it and keeps it yours.
The architecture is a personal knowledge graph: typed entities and weighted relations, built from your own sources, held in an encrypted store on your machine, queried by AI that never gets custody of it. Bounded retrieval means a question pulls the relevant part of your life rather than shipping the whole of it anywhere.
Where it starts
Health first, because it is the hardest to get right and the place people are worst served.
The first users are people with chronic or unexplained symptoms. The ones who have seen many doctors and still have no answer.
Positioning is locked under decision token D-relock-2026-06-29-full. Health is the wedge, not the ceiling. Getting correlation, consent, and honesty right in the domain with the highest cost of error is what makes the rest defensible.
What connects today, and what does not
The desktop application is the surface shipping today, and it is the founder's own daily environment. Seven product pillars exist in the code; three are live, one is in progress, three are routed away from until they are real. That routing is enforced by tests, so a hidden pillar cannot appear by accident.
The one rule everything obeys
Your data is processed on your device. Nothing about you is held anywhere else.
A cloud sync worker existed once and was removed. Its absence is now enforced rather than assumed: no reference to any sync backend remains in the source, and a pre-commit hook rejects any change that reintroduces one. The constitution binds any future sync to opt-in, default-off, and a key only you hold.
03What it means for you
Does the AI run on my machine or in the cloud?
Both, for different jobs. Two models can run locally. Neither is bundled, and neither is required.
| Model | Job | Size | Default |
|---|---|---|---|
| MiniLM | Turns your notes into searchable meaning | 86 MB | Runs if present |
| Phi-3.5-mini | Reads health detail out of your writing | ~2.3 GB | Off |
The embedding model is ONNX all-MiniLM-L6-v2, 384 dimensions, on Apple's Neural Engine through CoreML. If it is absent the app falls back to keyword search rather than failing. The language model is a quantized GGUF through candle with Metal acceleration, gated behind both an environment variable and a file check, holding a semaphore of one so two loads cannot coexist.
Heavy reasoning happens in the cloud, using your own API keys. There is no Arkhelion server in the path.
What actually gets sent?
The relevant part of your graph and your recent conversation. Not your database.
Up to 20 retrieved entities, the last 50 messages, and any web results. Bounded in the query layer, not by convention.
One thing worth stating plainly: the story you write during setup is stored as a health entry and can be retrieved into a prompt like any other entry.
submit_opening_story keeps the first 1,500 characters verbatim as a health_context entity, and that type is on the retrieval allowlist. Local distillation of that story never leaves the machine, but retrieval is a separate path. A code comment claims otherwise and is wrong.
Where does it live, and how big is it?
| What | Where |
|---|---|
| Your database | ~/Library/Application Support/com.arkhelion.os/ |
| Your backups | a folder you choose during setup |
| Models, if installed | ~/.arkhelion/models/ |
| Your key | macOS Keychain |
The app and embedding model are small. The database grows with what you connect. The founder's own vault is 946 MB, which is not a useful guide: it takes continuous Gmail, Drive, Calendar, Notion, Oura and Apple Health ingestion behind credentials most people will not have. No typical figure exists, because the app collects no telemetry that would produce one.
How much space and memory?
| The app itself | about 13 MB |
| Embedding model, optional | 86 MB |
| Language model, optional and off | ~2.4 GB on disk, 3 to 3.5 GB in memory while running |
| Your database | grows with what you connect |
Measured figures from real builds. The database on the founder's machine went 282 MB in May to 946 MB now, but that is continuous Gmail, Drive, Calendar, Notion, Oura and Apple Health ingestion. Startup time, query latency and steady-state memory have not been measured, and are named as open work rather than estimated here.
Does it sync across my devices?
No, and that is the design. See section 2.
How is it backed up?
To a folder you choose, encrypted, once, when you press the button. Setup will not finish until a real backup has been written and verified. Nothing repeats it for you yet, and the app says so on that screen.
The copy is an AES-256-GCM encrypted whole file named by date, written to the folder you pick and checked for a non-empty result before setup advances. It used to also run daily and at launch on a 30-day pruning window; that scheduled worker was removed on 16 August 2026, because it had produced nothing for 67 days on the founder's own machine while remaining able to write about a gigabyte a day into a local folder nobody reads. An earlier version had defaulted to the founder's own cloud folder, which broke on other people's machines; the replacement default was a local directory, which is not off-site at all. Rather than describe a running backup that was not running, it is now one copy you trigger, and a plain statement that repeats are not built. That is a real gap and it is named here rather than smoothed over.
You get one copy plus the live database. The three copies on the founder's machine are operator tooling and do not ship.
Nightly replication of the founder's own encrypted vault to object storage, a second cloud copy, and a weekly restore drill. Shell scripts run by a scheduler on one Mac. Nothing in the shipped application references them.
The code is backed up separately, and never mixes with data.
Code lives in a private repository, which is the recovery source for the project. No user data is in it. Losing every working copy costs nothing.
What if I lose my key or my Mac?
Lose the Mac and you restore from your backup and your written key. Lose the key and the data is gone.
Setup forces you to write the key down and type it back before any data may persist. If the database exists but the key is missing, the app refuses to generate a new one rather than orphaning your data. There is no escrow and no recovery service. Nobody at Arkhelion can read your database, which is the same property that makes it private.
04How it is built
The shape
A Rust core does the work. A React interface displays results and computes nothing. A narrow bridge connects them, and only 41 named commands cross it.
React interface renders JSON · no keys · no network calls
|
| 41 named commands. Nothing else crosses.
|
Tauri bridge window control and notifications only
|
Rust core encryption · AI routing · graph · statistics
This inverts the usual desktop-web arrangement, where logic lives in JavaScript and the native layer is a wrapper. Here the native layer owns everything and the webview is a display surface. Checked rather than assumed: searching all 197 TypeScript files for fetch( returns nothing. No API key literal and no provider SDK appears anywhere.
The app cannot betray you, even if its code is compromised
The interface is granted the minimum it needs and nothing more.
Granted: window hide, show, focus, close, drag, and notifications. Withheld: filesystem read and write, shell execution, HTTP from the webview, dialogs, clipboard, process control, updater, OS info, window creation and positioning. Hostile code inside the bundle could not read a file or reach the network. It could call one of 41 named Rust commands, and that list is the entire attack surface. The set defined and the set registered match exactly, with no orphan on either side, and the test suite fails the build if they ever diverge.
Encrypted twice over
The whole database is encrypted. The most sensitive fields are encrypted again inside it.
Layer one is SQLCipher: AES-256-CBC over every page including indexes and free pages, keyed by PBKDF2-HMAC-SHA512 at 256,000 iterations with a per-database salt, integrity by HMAC-SHA512. Layer two is AES-256-GCM over stored values and embedding vectors, keyed by HKDF-SHA256 with a fresh 12-byte nonce per record. The system sqlite3 tool can no longer open the file, which is the point. Using strong primitives is necessary but not sufficient: 88% of Android apps that called cryptography at all made at least one misuse of the API.14 The parameters here are SQLCipher's audited defaults rather than hand-rolled.
The key is wiped from memory after use.
Held in a SecretString that zeroes on drop, derived into Zeroizing buffers, and pinned with mlock(2) so key pages resist being written to swap. The delete function refuses this account. Key generation refuses to overwrite an existing key.
Encrypting a database that already holds data
The operation where people lose everything. Built to survive a crash at any point.
Detect plaintext by header bytes, needing no key. Integrity check, abort if already damaged. Checkpoint the write-ahead log. Snapshot every row count. Export with the key bound as a query parameter, never interpolated. Confirm the header changed. Reopen keyed and confirm every count matches. Copy the original aside as a rollback artifact. Only then rename into place. The original is untouched until that last step. Five tests cover it, including one proving a passphrase containing quote characters cannot break out.
The data model
Six tables. No ORM, no migrations framework, one batch of DDL applied idempotently.
| Table | Holds |
|---|---|
graph_entities | typed entities, content, metadata, 384-dim embedding, supersession pointer |
graph_relations | typed, weighted edges between entities |
memory_nodes | keyed values, encrypted at the column layer |
memory_embeddings | vectors, encrypted at the column layer |
messages | conversation history by role |
sync_cursors | ingestion position per source |
Four indexes on entity type, entity name, and both relation endpoints. Foreign keys are enforced with PRAGMA foreign_keys = ON, including a self-reference from graph_entities.superseded_by. Deletion is append-and-supersede: a new row is written, the old row points at it, and readers filter on a null supersession pointer. Rows are never physically removed. A user_version gate reads the schema version after keying, because the header itself is encrypted, and refuses to open a database written by a newer build rather than corrupting it.
Precise about the second encryption layer: it covers the two memory columns, not everything.
memory_nodes.value and memory_embeddings.embedding carry application-layer AES-256-GCM. Entity content, entity metadata, entity embeddings and message bodies sit in plaintext inside the SQLCipher envelope, so they are protected at file level only. Claiming otherwise would be the easy error to make here.
What the design defends against, and what it does not
Defends: a lost or stolen laptop, cloud data-mining, credential theft from logs or device sync, OAuth interception, and injection through the query layer.
Mechanisms in order: whole-file SQLCipher with the key in the Keychain; no server to mine; no secret values logged; PKCE with state on an ephemeral loopback port; parameterized queries throughout, with devtools off in release.
Does not defend: another program already running as you, a compromised operating system, a tampered local model file, or instructions hidden inside content you ingest.
Two development environment variables can relax behaviour and are live in the shipped binary. API keys are not zeroized, so a core dump or swap file could hold one. The local model has no checksum. Prompt injection through ingested third-party content is a real surface: retrieval feeds entity content into the model context, and the gating design for it is written but not built. There is no full data-wipe path. All are tracked as numbered known issues rather than left implicit.
Dependencies and licence
Proprietary. Not open source, by an explicit decision.
No licence file, both crates marked unpublishable, the npm package private. The reasoning is recorded: closed source sets the monetisation model, which sets the repository visibility, which is why signing happens locally and free CI runs Linux-only. 705 crates in the core, 822 in the shell, 518 npm packages, every one pinned by a lockfile with integrity hashes. A 14-entry licence allowlist is enforced in CI, and anything outside it fails the build. Only crates.io is an allowed source; unknown registries and git sources are denied.
For engineers: how it actually runs
Concurrency. Twelve background workers, all detached, all self-supervising through their own retry loops.
Spawned through Tauri's runtime at setup. The SQLite handle is a single Arc<Mutex<Connection>> with a documented contract that it is only touched inside spawn_blocking. The secrets cache is a tokio RwLock<HashMap> because it is read-mostly. The embedder sits behind a Mutex<Option<..>> because the ONNX session is single-slot. Model loading holds a Semaphore(1), and the permit is dropped after the blocking join rather than before, so 3.5 GB is provably freed before the next acquire. The opening-story path re-checks its cursor after acquiring, so a boot retry and a live submit cannot both load the model for the same input.
Errors. anyhow throughout with context at every I/O boundary, flattened to strings at the IPC edge.
No custom error types and no thiserror, which is a deliberate simplification for a single-binary app. Degradation is explicit: no embedder falls back to keyword search, no triage key escalates to the council, no search key runs local-only, a locked database waits 5 seconds then errors, Touch ID unavailable degrades to a liveness check, and an unopenable brain database posts a notification and continues.
Progress crosses as events, not return values.
Nine event channels including council-chunk, command-chunk, ingestion-progress and live-search-start. The frontend contract is documented: attach the listener before invoking, or lose the first chunk to a race. 36 of 41 commands are async; blocking SQL always hops to a worker thread.
The statistics run in SQL, not Rust.
Ranking uses RANK() OVER plus a tie correction of (count over partition - 1) / 2, giving average ranks on both axes, because weekly meeting counts are small integers with heavy ties and min-rank alone is not Spearman. Rho is Pearson over those ranks, guarded so a constant axis yields null rather than dividing by zero. The critical-value table is 28 entries indexed by sample size, exact permutation for n=4 to 10 and 2-million-sample Monte Carlo with a fixed seed above that, regenerable by a script in the repo.
23 math functions had to be reimplemented.
The bundled SQLite is compiled without the math extension, so pow() failed at runtime and the correlation silently fell back to mock data. The fix registers 23 unary functions, 4 binary, pi, sign and a variadic log on every connection, flagged deterministic, preserving SQLite's null-in-null-out and NaN-to-null semantics.
Builds are stamped and the stamp is verified in the binary.
build.rs emits the short commit hash and an ISO-8601 build time, the latter computed by a hand-rolled civil-date conversion to avoid pulling a date library into build dependencies. The test suite runs a real build, extracts strings from the bundled binary, and greps for the current commit hash, which catches both a stale build and the "unknown" fallback. Release profile is link-time optimisation, one codegen unit, abort on panic, optimised for size.
Two algorithms worth naming.
The model output salvager recovers complete objects from truncated JSON in a single character pass tracking string state, escapes and bracket depth, recording every object that closes at depth one. A naive search for the last bracket gets this wrong when one appears inside a nested array or a quoted string, discarding every valid leading object along with the broken tail. The graph traversal enforces its entity bound inside the admission test rather than after the hop, so it truncates mid-hop instead of overshooting the limit.
The stack
| Layer | Technology |
|---|---|
| Core | Rust 2021, tokio |
| Desktop shell | Tauri 2.11.3 |
| Storage | SQLite with WAL, SQLCipher 4.5.3 |
| Encryption | AES-256-GCM, HKDF-SHA256, secrecy, zeroize |
| Local AI | ONNX Runtime with CoreML, candle |
| Interface | React 19, TypeScript 5.8 strict, Vite 6.4, Tailwind 3.4 |
| Edge | Cloudflare Workers, D1, KV, R2, Turnstile |
| Secrets | Infisical. No .env files exist |
| Verification | Playwright, gitleaks, cargo-deny, cargo-audit, osv-scanner, promptfoo |
05The intelligence
Questions escalate instead of costing the same
A short, low-stakes question takes the cheap path. Anything ambiguous goes to the full council.
Tier 0 is a free heuristic: under 12 words with none of 30 high-stakes keywords. Tier 1 is a small model classifying simple against complex, requiring an explicit fast verdict to stay cheap. Tier 2 is five model calls. When a provider key is missing the tier is skipped and the request escalates to the council, so quality never silently drops because a dependency is absent.
Four models argue, a fifth decides
One of them exists to attack the others' answers.
Agent A reasons analytically and runs first so output streams immediately. B synthesizes. C verifies adversarially. D audits conflicts between your local data and anything pulled from the web. B, C and D run concurrently. A chairman resolves them and must return structured JSON. Agent D's conflict findings carry double weight and appear verbatim.
It refuses to claim a pattern that is not there
Spearman's rank correlation, gated on a critical-value table for sample sizes 4 to 31 at one-sided alpha 0.05. Those values were derived by exact permutation enumeration for n=4 to 10 and 2-million-sample seeded Monte Carlo for n=11 to 31, rounded up in magnitude to stay conservative. A correlation must also clear an effect-size floor of 0.3. Samples of 3 or fewer never produce a claim. NaN fails closed. The weekly nudge needs 10 weeks of data.
When there is enough data and no pattern, it shows nothing.
A deliberate decision not to display an "all clear", because a reassurance the data cannot support is a false statement. Every user-facing string passes a test forbidding the words because, cause, diagnos, treat and cure. Correlation is never permitted to be phrased as causation.
Retrieval is bounded on purpose
50 recent messages, embedding search capped at 25 candidates, then a breadth-first graph expansion limited to 20 entities across 2 hops, enforced in the query layer. Embeddings are 384-dimension MiniLM. Similarity is an exact full-table scan rather than an approximate index: correct results, no index to corrupt, no extra dependency. Right for a personal dataset, wrong for millions of vectors.
The model behaviour is itself tested
Four evaluation cases through promptfoo across three providers, judged by a model at temperature 0: grounded factual accuracy, refusal to fabricate a sleep score it does not have, first-person voice, and refusal to print an API key.
06Proof it works
One command runs 23 checks
Regression guards, secret scanning across the working tree and full git history, compilation of both Rust crates, licence and advisory policy, the full test suite, TypeScript compilation, live database integrity, headless browser rendering in two engines, fresh-install key provisioning, a complete application build, and a verified restore from a real encrypted backup.
Two rules make it trustworthy.
A missing tool fails the check. A gate that disables itself when its tool is absent is not a gate.
A hang fails the check. The restore lane runs under a timeout and treats a timeout as red, where most suites record it as inconclusive.
The interface drift check
Every command the backend registers is compared against every command the frontend calls.
It fails loudly if either extractor returns zero results, so a broken pattern cannot produce a silent pass.
Why one check exists
A correlation feature failed inside the shipped app and the interface quietly showed mock data. Demos looked live while the feature was broken.
pow() is a SQLite math extension absent from the bundled build, so every "live" statistic had been computed by hand through the system tool. The fix registered the functions and made the suite run the correlation through the app's own database engine rather than a convenient substitute.
What the browser tests catch
22 tests across two engines. Zero console errors per screen. Body text over 40 characters, catching a blank render. Line-height at least 1.1 times font-size on every heading, catching clipped descenders. The font check validates itself, failing if neither font loaded rather than passing empty. Honesty assertions confirm real values render and missing data shows a placeholder.
07The machine that builds it
Hooks that refuse dangerous commands
Roughly 17 fire around the AI's actions and can block them before they run.
| Guard | Refuses |
|---|---|
| Resource | Heavy builds when memory is tight. Local model loads, always |
| Secrets | Nine command shapes that would print a secret value |
| Dangerous command | Recursive deletes outside temp, piping downloads into a shell, credential reads, force-push to main |
| Push | Any push to the main branch, in every argument ordering |
| Consent | Commands that would raise a system permission dialog unannounced |
The resource guard blocks on any of: more than 2 live sessions, under 5 GiB free disk, over 3 GiB swap, elevated memory pressure, or another build holding the machine-wide lock. Patterns are anchored to command position, so naming a blocked tool inside a commit message does not trip it.
Fail open or fail closed, chosen per layer
Reflex layers fail open. Gate layers fail closed.
A hook that cannot read a sensor lets the command through, because a broken hook must never break the shell. The build gate facing the same unreadable sensor refuses, because a gate should permit only what it can prove safe. The two share a lock file and have opposite failure modes by design.
It tests its own safety tooling
34 fixtures run through the guard pipeline with expected outcomes encoded in filenames. The build-guard tests include a positive control asserting a healthy machine is allowed to build, without which a guard that refuses everything would pass every test. The interactive-detection test drives a real pseudo-terminal, because piped input masks every branch; its header records that mutation testing caught this flaw in the test's own first version.
Memory that survives the session ending
An AI session forgets everything when it closes. This one writes to a database.
487 rows of architectural decisions and retrospectives. Nothing is deleted: the maximum row ID equals the row count, which proves it. Eleven memory layers exist, ranked so conflicts resolve identically every time. The tool's own automatic memory is switched off, because two memory systems drift apart and you lose track of which is true.
Code that merges itself, when it can prove it is safe
Changes merge without human review only when verification passes and the change falls outside four hold classes.
| Class | Routes to a human |
|---|---|
| Security | Vault, crypto, keychain, secrets, hooks, settings |
| Boot | Entry points, config, capabilities, entitlements |
| Infrastructure | Workflows, cloud code, lockfiles |
| Visual | Any interface change the render check did not verify |
Merge is the final branch, so an unanticipated file type cannot reach it without failing every hold check first. A visual change merges only when the render lane verified it in that same run. The cost guard fails closed. 40 assertions drive the real classifier, covering case-variant extensions, filenames with spaces, and precedence conflicts.
What was deliberately not built
Recorded with reasons, so no future session re-litigates a settled call.
| Not built | Because |
|---|---|
| Open source | Visibility sets CI economics and the monetisation model. Decided, not drifted into |
| A memory or agent-tooling layer | Commodity. Others own it |
| Social features | Serves a network rather than the single user, which the constitution forbids |
| A broad life-management platform | The most crowded category, and it walks into Apple and Microsoft |
| Autonomous posting and replies | Rejected on evidence: platforms penalise bot-pattern content, so a human gate is the higher-value posture |
| Compile checks in the pre-commit hook | A cold check exceeded the tool timeout and killed sessions before the integrity check ran. A gate that kills the session is worse than no gate |
| A build cache, locally | It cannot cache the link step, build scripts or proc-macros, which are the bulk of the build, and it disables incremental compilation |
| A Linux dev box | Compile checks are already free in CI, and the only heavy local step needs a Mac |
| A fix for a known false positive in the memory guard | A real fix needs shell-aware parsing of every argument. Documented so it is recognised rather than re-debugged |
The pattern worth noticing is that each entry names the reason and the tradeoff. Several explicitly anticipate a future session arguing the opposite and answer it in advance.
Claims are checked against source before they are published
21 numbered claims about what the product does, each with a verdict, a file-and-line pointer, and a date. Twelve true, nine unverified, none false.
Marketing copy must match this register before it ships. Some claims are flagged as launch blockers that cannot be published until the code is verified. It exists because shipping a claim the code does not support is the specific failure that destroys trust in a health product.
Failures are catalogued and only retired when proven fixed
19 documented failure modes, each retired only after a shipped fix plus 30 days without recurrence.
A passing compile proves the working tree, not the commit. Read the number the tool prints back: "1 file changed" after editing six is the defect announcing itself. Silent-on-empty equals lying-on-broken. Never verify that something did not happen by checking afterward.
Method and references
Eleven agents read disjoint parts of the source in parallel, each instructed to cite file and line and to mark anything unconfirmed.
Scopes: vault and cryptography; AI routing and the graph; desktop shell and interface; test suite, CI and merge gate; hooks and procedures; cloud infrastructure and recovery; content pipeline; memory and governance; plus external research. Counts were measured with git, wc and grep rather than quoted from documentation. Claims that could not be sourced were removed. Figures marked estimated show their inputs so they can be challenged.
Verified 2026-07-26 against commit 3643dde.
- 1 Huckvale K, et al. Unaddressed privacy risks in accredited health and wellness apps. BMC Medicine 2015;13:214. n=79
- 2 Tangari G, et al. Mobile health and privacy: cross sectional study. BMJ 2021;373:n1248. n=20,991
- 3 Grundy Q, et al. Data sharing practices of medicines related apps. BMJ 2019;364:l920. n=24
- 4 Huckvale K, Torous J, Larsen ME. Assessment of data sharing in depression and smoking cessation apps. JAMA Network Open 2019;2(4):e192542. n=36
- 5 Marshall JM, et al. Apps with maps—anxiety and depression mobile apps with evidence-based frameworks: systematic search of major app stores. JMIR Mental Health 2020;7(6):e16525. n=162
- 6 Larsen ME, et al. Using science to sell apps: evaluation of mental health app store quality claims. npj Digital Medicine 2019;2:18. n=73
- 7 Semigran HL, et al. Evaluation of symptom checkers for self diagnosis and triage. BMJ 2015;351:h3480
- 8 Doherty C, et al. Keeping pace with wearables: a living umbrella review of systematic reviews evaluating the accuracy of consumer wearable technologies in health measurement. Sports Medicine 2024;54(11):2907-2926. n=310 devices (249 validation studies, 430,465 participants)
- 9 Kochhar PS, et al. An empirical study of adoption of software testing in open source projects. 2013. n>20,000
- 10 SlashData. State of the Developer Nation, 29th edition, April 2025. 47.2M developers, bottom-up model
- 11 Stack Overflow Developer Survey 2024 (n=27,764 professional subset) and 2025 (n=49,000+)
- 12 Kaseya/Unitrends. State of Backup and Recovery Report 2025. n=3,000+. Vendor survey
- 13 Zetetic. SQLCipher, publisher description, accessed 2026-07-26
- 14 Egele M, et al. An empirical study of cryptographic misuse in Android applications. ACM CCS 2013. n=11,748