# What is proven, what is not, and what we would want help with **Status: the honest inventory.** Written 2026-09-08. It exists so that nobody has to guess which parts of this project are load-bearing and which are hopeful. Where something is untested, it says so and says why. If any claim elsewhere in this repository contradicts this page, this page is the one that is right, and the other one is a bug. --- ## Who is building this, and with what One person, not a software engineer. My field is music. I have no computing background, I do not write Rust, and I could not have built this alone. **The code is written with AI assistance, and I have made the design decisions.** That division is the honest one, and it is worth stating plainly rather than leaving to be discovered. What it means in practice: - **The decisions I can defend** are the ones about shape. Why there is no operator. Why the record is scoped to About Me and stops hard before anything clinical. Why a membrane cannot be edited after a circle is made, and what that costs. Why acknowledgement is a record of reading rather than a permission. These are choices, they have reasons, and the reasons are in the commit messages and the comments, which are unusually long on purpose. - **The decisions I am taking on trust** are the ones about implementation. Whether the Rust is idiomatic. Whether the cryptography is used correctly in every path rather than only the ones with tests. Whether there is a class of bug here that somebody who has done this for ten years would spot in an hour. **The second list is exactly where outside review is worth most**, and it is the main thing this project would want from anyone reading it. There is a related point about the process. A large share of the real bugs found in this project were found by walking the interface as a user and noticing that something made no sense — not by tests, and not by reading code. Several are recorded in the commit history. That is offered as evidence that the walking is being done, not as a substitute for the review above. --- ## Proven ### The rules hold up against somebody trying to break them **101 tests, all passing on 23 September 2026**, run in CI on every push, in [`tests/tests/adversarial.rs`](../tests/tests/adversarial.rs), plus 3 unit tests on the ordering rule. They are written as attacks rather than as feature checks. Among them: - An uninvited agent cannot join a circle. - An invitation cannot be passed on to somebody it was not made for. - A member cannot forge an invitation. - A member cannot write the person's record, cannot hijack its update chain, and cannot delete it. - Nobody can acknowledge their own record, and an acknowledgement cannot be attached to something that is not a record. - A circle with no founder, with a malformed one, or naming a second person it cannot read, admits nobody — a broken configuration closes the door rather than opening it. - Nobody can create a circle in another person's name. - Two holders' circles are genuinely different networks. - With a second yes configured: half an invitation opens nothing; the holder cannot give the second agreement herself; a circle with no second yes is unaffected. - **A signal that claims to be from somebody else reaches no screen**, and one that names its real sender still does. - **Correcting yourself is the version that shows** — a corrected introduction, and a changed decision about a suggestion, both come back as the latest rather than as whichever arrived first. - **Being asked to agree is a question somebody answers.** Only the person an appointment names may answer it; an unanswered asking reads as neither a yes nor a no; and answering again replaces the answer without erasing it. - **A knock says nothing to the rest of the room.** Somebody else standing in the same waiting room sees that a knock happened and which key wrote it, and cannot read the name or the relationship. The holder can, and so can the person who wrote it. These run against a real conductor, not a mock. **What they prove is that the rules are enforced. What they cannot prove is that the rules are the right rules** — that is a question for a reviewer, not a test. And there is a second thing they cannot prove, which this week made plain. Every fault found by walking the demo — a button that did nothing, a screen that said nothing had happened when it had, a knock that had to be agreed to twice — passed every test in this file while it was happening. The rules were enforced correctly throughout. The tests are about the boundary; somebody sitting in front of it is about everything else. There is one honest limitation in how much of this can be tested at all. Everything is written through the app's own functions, and several of the link rules cannot be reached that way — the function that introduces you always links to your own introduction, so "you may only introduce yourself" has nothing to attack it with, and nothing deletes a link, so the rule about who may is unreachable too. Those rules are correct as read, and untested because there is no legitimate route to breaking them. Reaching them would mean shipping attack tools inside the app, which is a worse trade. **A note for anybody running these on Windows: you cannot.** The test crate pulls in a keystore that builds OpenSSL from source, which needs a full Perl toolchain that Git for Windows does not ship. CI runs them on Linux on every push, and that is where they are verified. It is why the CI badge at the top of the README matters more here than it would elsewhere. ### The whole journey works on one machine `the_whole_journey` walks the real sequence end to end. Beyond that, the interface has been walked repeatedly by hand with two and three separate conductors running side by side, each in its own window, on this machine. Invitations, joining, writing, suggestions, acknowledgement, leaving and rejoining all work. ### Two machines, and then no internet **14 September 2026, the first time Hearth ran anywhere but one computer.** Two Windows machines — a desktop PC and a laptop — each with the released 0.2.2 installer, on the same home wifi. **Online:** Margaret's circle was made on the PC. Dave, on the laptop, knocked at its door address, was let in, offered a suggestion, and the holder accepted it on the other machine. **Then with the internet taken away:** the broadband cable into the router was unplugged, leaving both machines on the local network and neither able to reach anything beyond it. "What matters most to me" was changed on the holder's PC, and the change appeared on Dave's laptop. A conventional hosted service does not do this: its devices talk to its server, and with the internet gone the people in the room stop sharing. Here they did not. (A hosted system *could* be built to sync locally as well — the claim is not that nothing else can, but that here it is the ordinary shape of the thing rather than an extra built around a central server.) **⚠️ But only while it was already running.** The same afternoon, both apps were restarted with the broadband still unplugged. Both opened, and they never found each other — left ten minutes, twice, with no error on either screen. Why, read in the Holochain 0.7.0 source rather than guessed: - **The list of where other devices are is kept in memory only.** Holochain builds its networking on kitsune2's default setup, which uses `MemPeerStoreFactory`. A restart forgets every peer, and the only way to learn them again is to ask the bootstrap server — which is on the internet. - **Saving that list would not be enough.** Each entry is signed to expire twenty minutes after it is made, and an expired one is refused. And a device's address is *reach me through this relay server*, a server on the internet; a direct path is only found once two devices are already talking. That is why the connection made before the cable came out kept working, and a fresh one after a restart could not be made. - **Stock Holochain 0.7 cannot look for devices on the local network.** The transport's own documentation says there is no discovery service. So the accurate claim for Hearth as released is: **it keeps sharing through an internet cut while it is running. After a restart with no internet, devices cannot find each other.** ### ✅ Restarting with no internet: solved in a field test, 19 September 2026 The same two Windows machines, each running **"Hearth LAN test"** — Hearth built with the Lightningrod Labs field-test Holochain, [holochain-0.7.0-mdns.2](https://github.com/lightningrodlabs/holochain/releases/tag/holochain-0.7.0-mdns.2), with its local-network discovery switched on ([download](https://github.com/topeuph-ai/hearth/releases/tag/lan-field-test-1), marked not for general use). - **The laptop joined by scanning the QR code** on the desktop's screen with its camera — the first use of the scanner, and nothing was typed. - Both apps were **quit fully, the broadband was unplugged, and both were started again.** They found each other in **about a minute**, and a change made on one arrived on the other. - **They found each other faster offline than online.** Not measured, and not explained from the source; the likely reason is that on the local network they connect directly, where online the first contact goes through the bootstrap and relay servers. - **Norton 360 asked about nothing** on the desktop during the test. It had flagged the installer itself as new and rarely seen, which is a reputation warning about any unsigned build, not a finding. Getting there took three attempts, and the first two tested nothing: the test app was not installed on one machine the first time, and the second time the test app itself could not start, because of a packaging fault now written up in [building-it.md](building-it.md). Recorded so the result is read as one clean run, not three. **What this does and does not change.** It shows the fix works on this hardware, for Hearth, in a real house. It does **not** change what Hearth ships: the field-test Holochain cannot talk to ordinary Holochain, and its authors say it is not for general use. Hearth moves onto local discovery when official Holochain has it — see [Finding each other without the internet](to-a-product.md#finding-each-other-without-the-internet). **A second fault, found in the same test and fixed.** Closing Hearth's window only hides it — it keeps running beside the clock so it can keep sharing — and opening it again started a second copy, which waited forever at "Starting lair keystore" because the first copy was still holding the keys. The desktop app now allows one copy per profile, and opening it again brings the window back. Checked by starting the built app twice: the second copy closed itself and nothing extra was left running. Not in a release yet. What this does **not** yet show, so nobody reads more into it: - **The two machines had already met online** before the internet went. Two devices meeting for the very first time with no internet at all is untried, even with the field-test build. - **Both were on one local network.** Two machines on different networks, with no internet between them, cannot reach each other and nothing claims they can. - **Two machines, not twenty.** Nothing here is evidence about scale. ### ✅ A change to the rules, survived — on two machines, 22 September 2026 **The thing the freeze exists to protect, done on purpose for the first time.** Until today the honest position was that Hearth could not be updated at all without destroying what people had: a patch release would ship new rules the conductor never installs, and a minor release would start a fresh conductor with a fresh keystore and a fresh agent key, leaving every circle on disk where nothing would ever look again. Both facts were read in the packaging source rather than assumed — see [`upgrades.md`](upgrades.md). With the data directory pinned, the new rules installed beside the old ones, and the agent key reused, **0.2.5 was installed over 0.2.4 on two Windows machines**: - **Every circle survived.** Nine cells before, nine after, listed on screen and each marked *"made with an older version"*. - **They open and read.** The record shows as it did, through the same screens. - **The person stayed the same person.** Asked of the conductor rather than inferred: both installed apps report the same agent key. ``` hearth.rules.2 | agent hCAkJbUeLrTY1ln9 | cells 1 | enabled kangaroo.happ | agent hCAkJbUeLrTY1ln9 | cells 9 | enabled ``` A new circle was then made under the new rules and joined from the other machine, which is also the first time **the locked record has run on two real machines**. **Done twice, on two separate apps.** The field-test build later the same evening carries the same packaging changes under its own app id (`uk.topeuph.hearthlan`), and installing it over the LAN build from 19 September did the same thing: the older circles listed, marked *"made with an older version"*, and the marking on the right ones. Two apps, two machines, one result. **What this does not show.** An old circle cannot yet be *carried across* to the new rules — it can only be opened and read where it is. That is step 3 of [`upgrades.md`](upgrades.md) and it is not built. And this was an upgrade within 0.2.x; the pinned directory means a later version number should behave the same, but nobody has done it. ### ⚠️ Joining took about ten minutes, and the media is the suspect Recorded here because it happened during the test above and it is not a small thing. The two machines **found each other quickly** — none of the ninety-second bootstrap delay in [`latency.md`](latency.md) — and the key handshake the encryption adds was **also quick**. What took about ten minutes was the joiner actually being in the circle. **The circle contained a photograph and a video.** A joining device receives and validates what is in the circle, and a two-minute 480p video is tens of megabytes arriving in three-megabyte pieces. That is the obvious suspect and it has not yet been confirmed from the logs. If it is right, it is an uncomfortable finding: media exists for people who cannot read a screen, so the feature built for the least able users is the one that makes joining slowest. The known lever is that a joiner need not store the whole circle — Holochain can run a cell at `target_arc_factor: 0`, reading without holding, which is also a privacy improvement. Not attempted. **The log was read the same evening, and the suspicion was half right.** From the laptop's own log: - **83 gossip rounds timed out**, one about every twenty seconds, from 18:40:33 to 18:56:30 — sixteen minutes of rounds starting and failing. - Every one of them names the peer as `https://dev-test-bootstrap2.holochain.org:443/…`, so the address went **through Holochain's public development relay** — for two machines on the same home wifi. - `ERROR integrate_dht_ops_consumer: database is locked` during a fifty-second stall: the workflow that files arriving data was also fighting for the database. So it is **not simply that the video is large. A large payload cannot finish inside a twenty-second gossip round over a relay**, so each attempt restarted rather than completing. Size and timeout together. That changes what to do about it, and the first thing is not about media at all: **find out why two machines on one network were talking through a relay.** See [`latency.md`](latency.md) for the three levers and the order to try them. ### ✅ With local discovery, the same media moved quickly — 22 September 2026 The same two machines, the same rules, the same photograph and video. The only difference: a build using the Lightningrod Labs field-test Holochain, with `mdnsBootstrap` and `irohTransport.enableLanDiscovery` switched on, so the machines can find each other on the wifi instead of being introduced through a relay on the internet. **The video reached the laptop very quickly**, against about ten minutes on the released build an hour earlier. **Two honest caveats.** The PC's wifi adapter switched itself off partway through, so the run began looking like a failure and recovered when the adapter came back — which is evidence of its own about recovering after a network interruption, but it means **nothing was timed with a stopwatch**. And it is one run, not a measurement. **What it supports.** The ten-minute join was not caused by media being large. It was caused by media being large *and* having to travel through a relay in twenty-second gossip rounds that never completed. Given a direct path on the local network, the same data moves at wifi speed. **What would make it conclusive:** the two builds back to back, same circle, same media, timed. Worth doing before the claim is repeated anywhere that matters. **What it means for the project.** Hearth already kept working through an internet outage without local discovery, as long as the devices were running. Local discovery extends that: devices that have restarted with no internet can find each other on the same network, and large files can move directly rather than through a relay somewhere else — which, from one untimed test, looks like the difference between photographs, sound and video being practical or not when everybody is in the same building, the ordinary case for a person and the people looking after them. Released Holochain 0.7.0 has no local discovery, so this remains a field-test build. See [`latency.md`](latency.md). ### It conforms to the standard it claims Checked field by field against the PRSB About Me JSON. See [`standard-and-gap.md`](standard-and-gap.md). --- ## Built, but not proven ### Two machines across the internet, in different places **Two machines on one home network now work, online and offline** — see [above](#two-machines-and-then-no-internet). What has not been tried is two machines in different buildings, on different networks, finding each other across the internet through the bootstrap and relay servers. Every piece that needs is in the build, and that is the next thing worth watching happen. ### Nobody outside the project has installed a release Releases are published and downloadable. Nobody but the author is known to have installed one. ### The test releases, 0.2.7 and 0.3.0, have not been tried together Added 23 September 2026, after an outside review suggested it. These two versions carry encryption, media, the upgrade, carrying a circle across, and passes. Each part has tests of its own; **nobody has yet run them together on real machines**, and that is where a design like this holds or falls apart. The matrix to work through, with released Holochain unless it says otherwise: | Test | Earlier (0.2.4 to 0.2.6) | 0.2.7 / 0.3.0 | | --- | --- | --- | | Two machines online | ✅ | to test | | Internet cut while running | ✅ | to test | | Fresh restart, no internet, same network | ✅ with the LAN build only | to test (LAN build) | | Two machines that have never met, no internet | not tried | to test (LAN build) | | Two machines on different networks | not tried | to test | | Two people editing while apart | not tried | to test | | A video, over the relay | slow (ten minutes) | to test | | A video, same room | quick with the LAN build | to test | | Removing somebody | ✅ | **to test with encryption** | | Letting somebody back in | ✅ | **to test with the keys** | | Upgrading over the previous version | ✅ 0.2.5 over 0.2.4 | ✅ 0.3.1 over earlier versions: circles made on older versions still there, photos and videos included (23 Sep) | | Carrying a circle across, with media, while encrypted | — | **not yet tried** | | Carrying across a circle somebody was removed from: they are not invited, and cannot read the new one | — | **not yet tried** (the app leaves them out; untested on machines) | | A successor taking over an encrypted circle: they can read it, move it, and the removed stay out | — | **not yet tried** | | A pass, read from another machine | — | ✅ 0.3.1, same home network; first try too early | | A call between two machines (0.3.5): the holder turns calls on, one member rings another, both see and hear | — | **not yet tried** — the call library connected two peers in one browser, set up as Hearth sets it up | | A call between two different networks (different houses) | — | **not yet tried**; expected to fail on some networks, since no call relay is run | The last rows matter most. "Local discovery" above means the Lightningrod Labs build of Holochain (`holochain-0.7.0-mdns.2`), not released Holochain: it is a Holochain feature Hearth makes use of, not a Hearth feature. ### Joining a circle can take about ninety seconds Measured here, understood, and written up in [`latency.md`](latency.md). Not fixed. It is a rendezvous cost rather than a bug, but it is a long time to sit in front of a screen wondering whether something has gone wrong. --- ## Not built ### The record is not encrypted — **in the released version** **Built and tested, and not in anybody's hands yet.** The released 0.2.4 stores the contents in the clear on every member's machine: entries are validated, signed and only reachable through the membrane, so a circle does not leak to the network at large, but anybody in a circle — and afterwards, if they keep their copy — has the plain text. That is fixed in 0.2.7 onwards (the latest release is 0.3.4), and as of 22 September 2026 it has run on two real machines. The record, suggestions, photographs, sound, video and acknowledgement roles are locked with a key every member holds, and **removing somebody starts a new key sealed to everybody but them**, so what the circle writes next cannot be read on their device by any software. Proven by the adversarial tests (102 by 24 September), including two on separate conductors, which is the only way to show that a key was never given. See [`encryption.md`](encryption.md). What it does not do, and cannot: the removed person keeps every key they were already given, so what they could read before, they still can. There is no way to delete a key from a keystore. For the About Me scope the exposure in the released version is smaller than it sounds — no medications, no diagnoses, nothing clinical, by design. It is still the reason nobody should put a real person's record into 0.2.4. ### Nothing is revocable in the ordinary sense Leaving takes the circle off your device. It does not reach anybody else's copy, and the interface says so rather than pretending otherwise. Changing who may enter means forming a new circle and everybody rejoining. This is honest, and it is a consequence of having no operator, but it is not what most people expect the word "remove" to mean. ### There is no way for a stranger to discover the record exists A paramedic who has never heard of this cannot find it. Paper solved that with a sticker on a fridge. See [`what-to-borrow.md`](what-to-borrow.md). Nothing is built, and a perfect record that is never read is the failure that matters most. ### The invitation is a wall of characters Long, awkward to send, and it carries the name of the person the circle is about in the clear. Assessed in [`DPIA.md`](DPIA.md). It is shaped that way because there is no server to hold accounts — the invitation has to carry the grant itself. That is the operator trade made concrete, and it needs work rather than a wish. ### Two of the six checks Holochain offers are not switched on **Closed in the migration batch (Hearth 0.2.5 onwards, test release 0.2.7).** Every kind of write now goes through the same rules wherever it lands, and the catch-all is gone — see item 1 in [migration-batch.md](migration-batch.md). What follows is kept as it was written, because it is the record of why. It still describes 0.2.4 and earlier, which is the recommended release until the batch has been tested. Found in an audit on 2026-09-09, and stated here rather than left to be discovered, because it is the sort of thing a reviewer finds in ten minutes. When somebody writes something in a circle, Holochain does not ask one machine whether it is allowed. It asks several, each looking at a different aspect of the same act. This zome answers four of those questions and lets two through unchecked — the one about the record as a filed document, and the one about the running list of what an agent has done. **No way to exploit it was found.** The two that *are* checked cover the contents and the links, and every list this app reads is reached by following a link, so a forged entry or a forged link is refused before anybody could see it. But the reason to write it down is that the same shape of gap has already happened here once: link creation was, at one point, entirely unchecked, and it was found by reading the code rather than by any test. It cannot be fixed now. The check lives in the frozen file, so changing it means every existing circle becomes unreachable. It is queued in [`to-a-product.md`](to-a-product.md) as the first thing to do whenever that file next moves. ### Nothing has been through a full security review No external review, no penetration testing of any kind. There has been one audit — the one above came out of it — but it was carried out by the same kind of process that wrote the code, which is exactly the limitation you would expect it to have. --- ## What we would want help with, in order 1. **Two machines in different places.** Two on one home network work, online and offline. Somebody in another building installing the release and joining a circle across the internet is the next largest answer it is possible to get. 2. **A read of the cryptography and the validation callbacks** by somebody who has written Holochain before, looking for the class of mistake that tests written by the author will never find. 3. **A view on encrypting entry contents** that does not quietly reintroduce a party holding a key on everybody's behalf. 4. **Whether the design is right at all** — the membrane model, the second yes, acknowledgement-as-record. These are defensible, but they are one person's answers and they have not yet been argued with by anybody who would know. --- ## What this project is not claiming - **Not a clinical record**, and not one that will become one by accident. The About Me boundary keeps clinical safety certification, clinician liability and the heaviest data protection questions out of scope. That boundary is load-bearing, not a limitation to be grown out of. - **Not production software.** Not deployed anywhere. Nobody's real record is in it. - **Not a claim that the encryption is secure.** It is an encryption design and implementation, tested by this project and not yet reviewed by anybody else. One real gap was found by an outside reader and fixed on 23 September 2026 (a device could fall back to a key the removed person still held). There may be others; that is what a review is for. - **Not a finished answer** to decentralised health data. It is one narrow, honest slice, built far enough to be argued with.