v4.6.0 - 2026-11-01
- HoloNET downloads the conductor for you (
HoloNETDNA.AutoDownloadConductor, on by default). When no conductor is installed, the Client downloads the officialholochainandhcfor the computer's OS and CPU (Windows x64, Linux x64/arm64, macOS Intel/Apple Silicon) from Holochain's stable releases, checks them against a pinned SHA-256 (scripts/update_conductor_hashes.pybuilds the table; releases newer than the table use the digest GitHub publishes) and caches them in%APPDATA%/NextGenSoftware/HoloNET/<version>/(HOLONET_CONDUCTOR_FOLDERoverrides it). New settings:AutoDownloadConductor,HolochainConductorVersion,AllowUnverifiedConductorDownload. The conductor now starts without PowerShell on Linux and macOS, so the plain Client works there, and in containers. Embedded packages stay for offline use. A CI job proves it on Ubuntu, macOS and Windows. Seedocs/conductor.md. - A conductor that already has the app installed no longer fails the first run. The conductor enables the app before its cells have started, so signing
credentials could answer
CellNotRunning; the admin client now asks again for a few seconds. HoloNETAPI also stops the conductor it started when the app exits (it used to outlive the app, and the next run attached to it). - Unity starter works.
Assets/packages.configlists the whole dependency closure (NuGetForUnity restores only what is listed), andtemplates/test_unity.pyrestores the packages, compiles and runs the demo in a real Unity 2022.3 editor. - 28 library packages (7 libraries x 4 variants) plus a template pack. Client, ORM, HyperNET, HDK, Manager, API and the Test Harness each come as
no conductor,
.Embedded(Holochain 0.7.1 and 0.7.0),.Embedded.Holochain071and.Embedded.Holochain070. Each variant depends on the matching Client variant, so conductors are never duplicated. The full list is in docs/packages.md, generated frompackages.json. dotnet newtemplates:NextGenSoftware.Holochain.HoloNET.Templatesaddsholonet-console,-worker,-webapi,-mvc,-razor,-blazor,-blazorwasm,-wpf,-winforms,-winui,-avalonia,-maui,-maui-blazor,-uno,-android,-iosand-unity.--HoloNET api|client|orm|hypernetpicks the library,--Conductorand--HolochainVersionpick the conductor. See docs/templates.md.- Fixed: the Client could not be installed from NuGet. It depended on a
Chaos.NaCl1.0.0 package that is not on nuget.org. The assembly is now inside the Client package. - HDK: no longer includes WEB5 STAR and HoloOASIS by default. STAR 2.0.6 pulls in OASIS provider packages that depend on the same missing
Chaos.NaCl, so a HDK with them could not be installed.-p:HdkIncludeStar=trueturns them back on once those packages are fixed. - API: targets .NET Standard 2.1 as well as .NET 10 (Unity). The default
oasis.happis now found next to the app, sodotnet runfrom the project folder works. - Embedded by default: on Windows, a Client with a bundled conductor now uses it by default (
HolochainConductorModewasUseSystemGlobal, which ignored it). The Manager picks the bundled conductor when there is one. - .NET 10: the API, and the Blazor and WinForms templates, are on .NET 10 (the Client, ORM, HyperNET and API keep .NET Standard 2.1 for Unity).
- One script keeps the list complete:
python scripts/holonet_packages.py check | pack | verify-packed | smoke | verify-nuget | set-version | docs. A public workflow checks the list on every push, and the publish workflows build everything from it. - Sandbox: sandbox.holonet.oasisomniverse.one (service in
sandbox/): try the API, Client, ORM and HyperNET from a browser. - Docs and learn sites: new Templates and Packages pages, and two tutorials (Up and running in 5 minutes, A template for every app).
v4.5.1 - 2026-10-31
HoloNET Client and HyperNET 4.5.0, API 4.5.1, HDK 4.5.0. ORM and Manager are unchanged.
- Examples.
examples/has six runnable, commented examples: - the Client;
- the ORM;
- every HoloNET API feature;
- HyperNET (three players);
- hApp generation, including a WEB5 STAR OAPP;
- a live web site on Holochain.
All six run against Holochain 0.7.0 and 0.7.1 in the release tests (scripts/run-live-tests.sh, PROJECTS=examples).
examples/start-conductor.sh and .ps1 start a conductor from HoloNET's bundled binaries.
- Documentation sites:
- docs.holonet.oasisomniverse.one has every guide and the full API reference;
- learn.holonet.oasisomniverse.one has six step-by-step tutorials.
Both are generated from the Markdown in this repo (scripts/build-sites.py).
- Client. The app client that InstallEnableSignAttachAndConnectToHappAsync creates now inherits the admin client's
logging settings. It always logged to the console and to file with the defaults, whatever you had set.
- HoloNET API. Configure(holoNETDNA) and UseConductor(adminUri, logToConsole) set the conductor and logging in one line.
- HyperNET. HyperNETSession.AgentPubKey is your own key, which other players need to message or ping you.
- Tests. The generated-hApp test now skips, saying why, when the generated sources are missing.
v4.5.0 - 2026-10-16
HoloNET API 4.5.0. Everything else is unchanged.
- Per-key storage. Each key is its own entry, so saving or loading one key costs the same however big the store is.
SaveAllDataAsyncwrites only what changed, and keys removed fromDataare deleted. A store saved by 4.4.2 or earlier (one entry) is copied over the first time 4.5 starts.HoloNETAPIDNA.StorageMode = "SingleEntry"keeps the old store. - Shared data.
SaveSharedDataAsync,LoadSharedDataAsync<T>,SaveSharedObjectAsync,LoadSharedObjectAsync<T>,LoadAllSharedDataAsync,ListSharedKeysAsyncandDeleteSharedDataAsyncwork on a namespace every agent in the app can read and write. - Change notifications.
SubscribeToChangesAsync(ns)plus theOnDataChangedevent (who changed what), sent as remote signals to the namespace's subscribers. - Broadcast.
SendSignalToAllAsync(message)reaches everyone using the API in the app. - Typed values.
LoadDataAsync<int>("score")andSaveDataAsync("score", 9001)cover numbers, bools, dates, Guids and enums, stored in the invariant culture. - Listing.
ListKeysAsync()andExistsAsync(key). - Sync versions of every common call (
SaveData,LoadData<T>,DeleteData,SaveObject,LoadObject<T>,SaveSharedData,SendSignalToAll,Exists,ListKeys, ...), for Unity scripts and console apps. - Tested live on Holochain 0.7.0 and 0.7.1, with a second agent for shared data, notifications and broadcasts.
v4.4.2 - 2026-10-16
HoloNET API 4.4.2. Everything else is unchanged.
- HoloNET API: one-line deletes.
DeleteDataAsync,DeleteObjectAsync,DeleteAllDataAsyncandDeleteAllObjectsAsyncare safe straight after a restart (the store is loaded first, so the deleted key can't be merged back in). The API also remembers the hApp it was initialised with (HoloNETAPIDNA), so one-line calls keep using it afterShutdownAsyncor a restart. Before, they silently switched back to the bundled OASIS hApp.
v4.4.1 - 2026-10-16
HoloNET API, Manager and HDK 4.4.1. Client, ORM and HyperNET stay at 4.4.0, unchanged.
- HDK is the full metapackage now: HoloNET Client, ORM and HyperNET, plus WEB5 STAR 2.0.6 and HoloOASIS 2.0.6.
STAR couldn't be installed from NuGet before, because IPFSOASIS 2.0.4 depended on
Ipfs.Http.Client>= 0.42.0, which was never published. OASIS 2.0.6 fixes that: IPFSOASIS now ships its IPFS client inside the package, and Contracts, ArweaveOASIS and STAR.DNA (never published at 2.0.4) are now published. OASIS 2.0.6 also builds HoloOASIS against HoloNET 4.4.0, so STAR's hApp generation has the classes it needs.-p:HdkIncludeStar=falsestill gives a HoloNET-only HDK. - API and Manager bundle the current OASIS hApp, with HyperNET. The previous bundled build predated it, so
HoloNETAPI.SendSignalAsync(and HyperNET) failed with the default hApp. A live test now installs both bundled hApps on 0.7.0 and 0.7.1 and joins a HyperNET zone, so a stale bundled hApp can't ship again. - Every GitHub release has its packages attached: each
.nupkgplus a.zipof its contents, including v4.2.0-v4.4.0, Libraries v2.0.4 and the OASIS hApp. The OASISpublish-holonet.ymljob's newrelease_taginput does this automatically.
v4.4.0 - 2026-10-16 (Holochain 0.7.0 and 0.7.1)
Every HoloNET package is now 4.4.0: Client, ORM, API, HyperNET, Manager and HDK, including all the Embedded variants.
hApp generation (WEB5 STAR + HoloNET ORM)
- WEB5 STAR now generates hApps that actually build on Holochain 0.7. Its old Rust templates were written for the pre-RSM
hdk 0.0.50 (
#[zome],hdk::commit_entry,ZomeApiResult), so nothing it generated could compile on current Holochain. - New STAR templates in
DNATemplates/RustDNATemplates/Holochain07, filled by HoloOASIS's template engine. For each zome, they produce an integrity zome and a coordinator zome with create, get, update, delete and get-all for every entry, plus anchored collections. They also writedna.yaml,happ.yaml,build.shand the matching HoloNET ORM C# models. - Choose the version with the HoloOASIS
HolochainVersionsetting (0.7.1by default, or0.7.0). - HoloNET ORM has its own code-based generator,
HolochainHappGenerator(plusFromStarDnaFolder), for apps that don't use STAR. - Tested end to end on both versions. A sample hApp is generated from the STAR templates and compiled with cargo. Its
generated C# models are compiled with Roslyn and drive the hApp on real 0.7.0 and 0.7.1 conductors: create, load,
update, change tracking, delete, and collection add, load, batch save and remove (
scripts/build-generated-happ.sh,LiveGeneratedHappTests).
HoloNET API
- Direct messages.
SendSignalAsync(message, toAgentPubKeys)and theOnSignalReceivedevent send and receive text messages as remote signals, peer to peer, with nothing stored.ReceiveSignal()now returns the last message received.SendSignal()andReceiveSignal()used to be placeholders;SendSignal()is now obsolete. - XML docs for every public member.
HoloNET Client
IHoloNETClientAdminnow exposesAddAgentInfoAsync(IEnumerable<string>). Before, only the obsolete pre-0.7 overload was on the interface.- More XML docs:
InstallEnableSignAndAttachHappEventArgs,HoloNETClientBaseand the admin events.
HoloNET Manager
- The Get Storage Info, Add Agent Info, Delete Clone Cell, Graft Records and Update Coordinators buttons work now; they used to say "Coming Soon".
- Dump State, Dump Full State, Dump Network Stats and Dump Network Metrics now show their results. Before, the results went to events nothing listened to.
HyperNET
- XML docs for every public member. STAR's
hypernet start [zone] | stop | status | configcommands now run onHyperNETService; they used to say "Coming Soon".
Documentation
- New
docs/folder: - guides: getting started, Client, ORM, API, HyperNET, Manager, and STAR hApp generation;
- a generated API reference for every public type and member of Client, ORM, API and HyperNET
(
scripts/generate-api-docs.sh). - The README's package list now covers the four Client/ORM variants, and the stale "Release Coming Soon" text is gone.
v4.3.0 - 2026-10-16 (HyperNET + HDK)
HoloNET HyperNET: P2P multiplayer networking, built out
HyperNET was a placeholder until now. It is now a working library, tested live with three players on Holochain 0.7.0 and 0.7.1:
- HyperNETSession: join, leave and change zones. Presence in a zone is a DHT link (the only thing stored); everything
else is a direct remote signal between players, with no server in the middle.
- Area of interest: game traffic goes to the players within AreaOfInterestRadius, at most MaxFullRatePeers (the nearest)
at full rate. The rest of the zone gets every FarUpdateEveryth position update. Moves smaller than MinimumMoveToSend aren't sent.
- Unreliable (fire and forget) and reliable messages (acknowledged, retried, de-duplicated, OnReliableMessageFailed),
typed messages via MessagePack, PingAsync latency, Stats.
- The zone list is re-read every PeerRefreshInterval (5 s) to catch missed join signals, and a heartbeat every
HeartbeatInterval (10 s) keeps idle players from hitting PeerTimeout.
- HyperNETService and HyperNETDNA: start, stop and status for a long-running process (what WEB5 STAR's hypernet commands drive).
- The OASIS hApp has the matching zome functions (hypernet_join, hypernet_leave, hypernet_peers, hypernet_send,
recv_remote_signal, plus an unrestricted grant for recv_remote_signal created in init) on main and on holochain-0.7.0-maintenance.
Two bugs found by the live tests are fixed there: recv_remote_signal took an ExternIO, which failed to decode every
real remote signal, and a multi-target send_remote_signal reached only one of several agents on the same conductor
(it now sends once per player).
HDK
NextGenSoftware.Holochain.HoloNET.HDKbecomes a real metapackage: HoloNET Client, ORM, HyperNET, WEB5 STAR and HoloOASIS (HoloNET Manager ships on its own as a desktop app). For now it carries Client, ORM and HyperNET: STAR and HoloOASIS are behind-p:HdkIncludeStar=trueuntil their NuGet packages install cleanly (STAR 2.0.3 needsIpfs.Http.Client>= 0.42.0, which isn't on NuGet, and HoloOASIS 2.0.4 pins the never-published HoloNET.Client 4.1.0).
Tests
- The live-test sandbox uses Holochain's in-memory network (offline; no public bootstrap or relay).
v4.2.0 - 2026-10-16 (Holochain 0.7.0 and 0.7.1)
Published to NuGet as 4.2.0 for every HoloNET package (Client, Client.Embedded, ORM, ORM.Embedded, HDK, HyperNET, Manager, and HoloNET API for the first time), with NextGenSoftware libraries 2.0.4. 4.1.0 was never published, so this release includes everything below, newest first.
Four Client / ORM packages
NextGenSoftware.Holochain.HoloNET.Client/.ORM: no conductor (connect to your own)..Embedded: bundles Holochain 0.7.1 and 0.7.0 (choose withHoloNETDNA.EmbeddedHolochainVersion, default 0.7.1)..Embedded.Holochain071/.Embedded.Holochain070: one version only (about half the size). Asking a single-version package for the other version uses the one it has and logs a warning;HoloNETClientBase.IsEmbeddedHolochainVersionBundledsays what a build carries. The conductors are now embedded directly (build propertyEmbeddedHolochain=both|0.7.1|0.7.0) instead of through Resources.resx.
HoloNET API overloads
- New overloads take the hApp as a
HoloNETAPIHapp(installed app id, .happ path, role). The old(hAppId, hAppPath, hAppRole, ...)string overloads are obsolete: with three or more leading strings C# could pick the zome/function overload instead (e.g.SaveAllObjectsAsync(appId, path, role)calledSaveAllObjectsAsync(zome, createFunction, updateFunction)).
HoloNET ORM, HoloNET API and HoloNET Manager working end to end on Holochain 0.7.0 and 0.7.1
All three are now tested against a real conductor of both versions with the OASIS hApp (live tests), plus a fake conductor / in-memory hApp for the error paths. 1,758 Client/ORM/API tests and 9 Manager tests pass on 0.7.0 and 0.7.1; line coverage: Client 93.1%, ORM 93.2%, API 93.9%, Manager logic 79% (the rest of the Manager is WPF window code). Before this pass none of them could save and reload data on 0.7.
HoloNET ORM (HoloNETEntryBase, HoloNETAuditEntryBase, HoloNETCollection, HoloNETObservableCollection)
- Entries: updates,
Load()andDelete()used the EntryHash where Holochain needs the ActionHash, so every update failed; loading a hash with no record reported success; thestatefield andIsChangedmade saved entries look changed;PreviousVersionActionHashwas the source-chain previous action;OrginalEntrywas always null. - Audit entries: a new
Idon every save, only the first modification recorded, culture-dependent dates,NullReferenceExceptionwhen a tracking flag was off, delete wipedDeletedDate, no audit trail on 0.7. - Collections: add/remove sent only the anchor (not which entry), the batch couldn't tell adds/removes/updates
apart, loads never mapped records onto
T, reloads duplicated entries, change detection broke after the first match. The zome contract is now defined (seeHoloNETCollectionCore); the OASIS hApp has matchingget/add/remove/batch_update_avatar_collectionfunctions (coordinator only, DNA hash unchanged). - Events were only wired when the ORM object connected the client itself, so a shared client's
OnErrorwas never forwarded and the observable collection never tracked changes. Constructors now all takeIHoloNETClientAppBase.
HoloNET API
Rebuilt on the 0.7 OASIS hApp with the same public methods: one store entry (StoreId) holding Data and Objects as JSON;
created then updated by action hash; the installed app is reused (it used to uninstall it, losing the data, on every
start); errors reported (OnError, LastError, Message); loaded objects convert to T; ShutdownAsync; bundled
oasis.happ rebuilt for 0.7. Note: overloads like SaveAllObjectsAsync(hAppId, hAppPath, hAppRole) and
SaveAllObjectsAsync(zome, createFn, updateFn) take the same string types, so the hApp versions need a fourth argument.
HoloNET Manager
- Demo models used zome functions that no longer exist and sent no
id/username; every loaded record opened its own conductor connection; the demo hApp path was relative (the conductor couldn't find it). - App interface connections had no authentication token, which Holochain 0.6+ requires, so no app connection worked.
- Work queued from WebSocket events with
Dispatcher.CurrentDispatchernever ran; shutdown re-subscribed handlers; closing connections modified the list being iterated; recycling reconnected another app's client; status updates to a closed popup threw; creating a client from the interface-attached event deadlocked; grant/attach error events were treated as success (it connected twice on 0.7.0); the shared entry's hash was saved as an entry hash and couldn't be loaded; reboot waited for clients that were already closed and could run twice. Bundledoasis.happrebuilt for 0.7. - Results: Manager tests 9/9 on both versions (boot, the HoloNET Entry/Collection demos incl. re-enable/reconnect/ reinstall, the shared install → grant → attach → connect → use flow with the entry form, reboot, admin queries).
- New test project
NextGenSoftware.Holochain.HoloNET.Manager.Testsdrives the Manager headless: boot, the HoloNET Entry and Collection demos, and the install → grant → attach → connect → use flow.
HoloNET Client fixes found on the way
- Sync methods called from inside a HoloNET event deadlocked (since they were made to wait for the conductor):
inside a conductor callback they now send and report through the matching
On...CallBackevent, as they used to. IHoloNETClientAdmindefaulted installs to Unrestricted grants while the class used Assigned; code holding the interface got grants Holochain 0.7 rejects (BadCapGrant). A test now checks every interface default.uninstallhAppIfAlreadyInstalled: falsetried to install again; it now reuses the installed app.ShutdownHoloNETAsyncon an already disconnected client never completed.WaitTillReadyForZomeCallsAsynchung forever when the agent key/DNA hash were unknown and retrieval was off.- Request ids weren't atomic: two requests sent at once from different threads (an app call while a HoloNET event sends another) could get the same id, and a reply was matched to the wrong call.
- NextGenSoftware.WebSocket: the receive loop ran on the caller's UI thread, so in a desktop app any blocking call froze it.
- NextGenSoftware.Logging: every log line scanned the whole log folder, so with a few hundred files HoloNET calls timed
out; the folder also grew without limit. The current file is now remembered and only
MaxLogFiles(default 50) kept.
Tests and tools
scripts/run-live-tests.sh <version>now runs the Client/ORM/API project and the Manager project (PROJECTS=clientormanagerfor one;HAPP_OVERRIDEto try another hApp).scripts/build-test-happs.sh <version>builds the OASIS test hApps (0.7.0 from the hApp'sholochain-0.7.0-maintenancebranch: theholochain-0.7.0tag plus the collection functions).
Full Holochain 0.7 coverage pass: 1,647 tests, 95% line coverage, ~40 bugs fixed
Every public request method, response type and connection path now has tests, against a real conductor on both
Holochain 0.7.0 and 0.7.1 and against a fake conductor (FakeConductor in the test project) that produces exact 0.7
wire shapes, errors, malformed replies and dropped connections. Results: 1,637 tests pass on each version, plus 10
conductor auto-start tests; HoloNET.Client line coverage 95.1%, branch 85.4%. What isn't covered is listed at the end.
Bundled conductors
- The Embedded package now carries Holochain 0.7.1 (default) and 0.7.0; choose with
HoloNETDNA.EmbeddedHolochainVersion. Each is extracted to%APPDATA%\NextGenSoftware\HoloNET\<version>\.
Holochain 0.7 API (completed)
- New: admin
dump_conductor_state; app-interfaceagent_info,dump_network_metrics,dump_network_stats,enable_app; paging fordump_state(SourceChainCursor) anddump_full_state(DhtOpsCursor,limit). - 0.7.1: direct-signal sender (
SignalCallBackEventArgs.FromAgentPubKey,IsDirectSignal); system signals raised on the newOnSystemSignalCallBack(they were dropped). hc sandbox callno longer exists in 0.7:RetrieveAgentPubKeyAndDnaHashFromSandboxnow useshc client call.
Decoders that never matched the 0.7 wire format
peer_meta_info (always empty), DNA definitions (zome dependencies / wasm hash never read), the typed full state dump
(never deserialised), AppInfo.AppStatus (always None on 0.7), clone cells in app_info (decode failed),
countersigning session state ("no session" was an error), scalar zome results ((), bool, numbers, strings were
"unknown responses"), HoloHash strings of lengths other than 39 bytes.
Calls that hung forever (now fail with a message)
get_dna_definition errors; malformed app_installed / app_info / zome replies; a dropped connection, a call made
while disconnected, or a send that failed; a reply of an unexpected type (e.g. one renamed in a future Holochain);
RetrieveAgentPubKeyAndDnaHashFromConductor on an app_info error; the conductor ↔ sandbox fallback looping when both
failed; app clients with a token connecting in callback mode; a custom logger that throws.
Conductor start / stop
UseExternalignoredFullPathToExternalHolochainConductorBinary;hcdev-tool mode used the wrong port flag; "only one conductor" never detected a running one;DisconnectAsyncreturned before auto-shutdown finished.- Shutting down "all" conductors killed every
rustcprocess on the machine (your own builds); "current only" killed every holochain/hc process. Both now stop only what they should, and the hidden PowerShell host too. - Failed config creation still launched an empty PowerShell host; the config port rewrite could hit
report: none. - Start waits for the admin port instead of a fixed delay (faster, and no more timeouts under load).
Behaviour and API fixes
- Task continuations no longer run on the WebSocket receive thread (
RunContinuationsAsynchronously): the live suite went from ~35 s to ~20 s, and reused request ids (cached zome results) no longer race. - Sync wrappers:
GetAppInforeturned aTask; severaldynamicoverloads (CallZomeFunction, clone cells,MapEntryDataObject) returned aTaskor threw; some returned placeholders;.Result/.Wait()replaced. SyncInstallEnableSignAttachAndConnectToHappdefaulted toUnrestrictedgrants while async usedAssigned(now bothAssigned); added the missing syncInstallEnableSignAndAttachHapp. - Entry mapping:
float, nullable and enum properties, and non-English number formats;Record.DateTimeis UTC (it applied a fixed −5 h offset). - A null request id crashed
CallZomeFunctionoverloads; the voidInstallAppwithout an agent key did nothing; a zome string parameter that merely decoded as base64 (e.g. a username) was sent as bytes. - Clients unsubscribe from
AppDomain.UnhandledExceptiononDispose(they leaked); faulty log providers / loggers can't break calls (also fixed in NextGenSoftware.Logging and NextGenSoftware.WebSocket).
Breaking: GetAppInfo() (sync) returns AppInfoCallBackEventArgs instead of a Task; ClonedCell.clone_id is a
string; DumpFullStateAsync's cursor is a DhtOpsCursor (the int overload is kept and ignores the value); the
AppBundle install overloads are obsolete (an AppBundle can't be packed for 0.7).
Not covered (and why)
About 200 lines are catch blocks around code that can no longer throw (after the fixes above) and are kept as
defensive handlers; the rest are the ShowHolochainConductorWindow branches (would open a visible window during tests),
generated resource code, and fallbacks made unreachable by the fixes. Removing them would reach 100% but make HoloNET
less robust, so they stay.
Running the tests
scripts/run-live-tests.sh 0.7.1 (or 0.7.0) starts a fresh sandbox and runs everything with coverage; conductor
auto-start tests need HOLONET_LIVE_AUTOSTART=1 (and HOLONET_LIVE_EMBEDDED=1 with -p:Embedded=true). See
INTEGRATION_TESTING.md. scripts/classify_uncovered.py lists what isn't covered.
Holochain 0.7.0 and 0.7.1 both supported; direct signals
HoloNET now works against both Holochain 0.7.0 and 0.7.1 conductors. The full live suite (96 tests) passes on each, on fresh sandboxes.
- Capability grants: 0.7.1 changed the
grant_zome_call_capabilitypayload ({tag, constraint, grant: {functions}}instead of 0.7.0's{tag, access, functions}) with no compatibility shim, so each version rejects the other's shape. HoloNET sends the 0.7.1 shape, retries once with the 0.7.0 shape on a "Failed to deserialize request" error, and remembers which one the conductor accepts. Nothing changes for callers. - Grant listings (
ListCapabilityGrantsAsync) decode both versions. ReadAccessInfo,Functionsand the newCapabilityType("zome_call"or"direct_signal") rather than the rawaccess/functionsfields. - New (0.7.1+):
GrantDirectSignalCapabilityAsyncon the admin and app clients lets other agents send direct signals to a cell. On 0.7.0 it returns an error (the request doesn't exist there). - New:
SendDirectSignalAsync(dnaHash, agents, signal, capSecret)on the app client.capSecretis only sent when set, so it works on 0.7.0 too. On 0.7.1 a recipient only receives the signal if it granted direct-signal access; it arrives on the recipient'sOnSignalCallBack. - The generic
okresponse is now routed by request id (send_direct_signalvsprovide_memproofs).
hApps must be rebuilt for 0.7.1. 0.7.1 changed the CapGrant type, so an integrity zome built against hdk 0.7.0 /
hdi 0.8.0 fails validation on a 0.7.1 conductor ("callback has invalid parameters"). Rebuild with hdk 0.7.1 /
hdi 0.8.1. The OASIS hApp main branch now targets 0.7.1; the tag holochain-0.7.0 is the last 0.7.0 build.
Synchronous methods now return the result (behaviour change)
Breaking for anyone relying on the old behaviour. HoloNET's synchronous methods (the ones without Async, e.g.
ListApps(), AttachAppInterface(), Connect(), Disconnect(), 66 in all) used to send the request and return an
empty placeholder straight away ("please wait for the ... event"); the real result only arrived through events. They now
wait for the conductor and return its result, which is what a synchronous .NET method is expected to do.
- Events (
OnAppsListedCallBacketc.) are still raised, so event-based code keeps working; it just no longer gets an early return. - They run on the thread pool and are awaited with
GetAwaiter().GetResult(), so calling them from a UI or Unity main thread doesn't deadlock (a live test calls them on xunit's synchronisation context). - Prefer the
Asyncmethods where you can. For fire-and-forget, call theAsyncmethod withConductorResponseCallBackMode.UseCallBackEvents.
The previous line of each wrapper is kept commented out next to the new one.
Coverage push: four more 0.7.0 bugs, shared-state fixes
New live tests (LiveConductorCoverageTests) for paths no test reached exposed real bugs. 93 tests; all pass
live against a 0.7.0 conductor on a fresh sandbox. HoloNET.Client coverage with the conductor: 54.9% lines,
49.6% branches (it was 46.3% / 39.9%; offline-only it is 5.2%).
Fixes
app_infowas rejected ("Failed to deserialize request"): 0.7.0AppRequest::AppInfois a unit variant, but HoloNET sent the old{ installed_app_id }object. It now sends no value.app_inforesponses crashed decoding: a completedTaskCompletionSourcewas completed again and threw. All 51SetResultcalls are nowTrySetResult, so duplicate or late responses can't crash response handling (and leave callers waiting).list_app_interfacescrashed decoding: 0.7.0 returnsAppInterfaceInfo { port, allowed_origins, installed_app_id }, not bare ports, and an empty list threw inSubstring. NewAppInterfacesListedCallBackEventArgs.AppInterfaces;WebSocketPortsstill filled.- The synchronous
CallZomeFunctionalways returned null (regression from the earlier deadlock fix): every overload passedUseCallBackEvents, and C# bound the caller's mode argument to adynamicparameter. All sync overloads now go through one helper that honours the mode (default: wait) and runs on the thread pool, so a UI/Unity thread still can't deadlock. - All clients shared one HoloNETDNA:
HoloNETClientBase.HoloNETDNAread and wrote the staticHoloNETDNAManager.HoloNETDNA, so creating any client replaced every other client's DNA (admin URI, InstalledAppId, DnaHash, AgentPubKey). Each client now keeps its own; a client given none still uses the shared, file-loaded default.SaveDNAsaves the client's DNA. -
Shared signing credentials weren't thread-safe: concurrent clients threw in
Dictionary.TryInsert. Now aConcurrentDictionary. -
AddAgentInfoAsyncnever completed: its result handler checked the agent-info-returned request map (copy-paste), so the waiting call was never resolved. New overload takes the encoded strings thatGetAgentInfoAsyncreturns (AgentInfos); the oldAgentInfo[]overload is obsolete. - New
AddAdminInterfacesAsync(add_admin_interfaces): the decoder existed but there was no request method. ListCapabilityGrantsAsyncalways returned no grants: a Holochain 0.7.0 conductor bug (capability_grant_infoskips every grant wheninclude_revokedis false, not just revoked ones). HoloNET now always asks for all grants and drops revoked ones itself whenincludeRevokedis false. Already reported upstream (holochain/holochain#5950) and fixed in Holochain 0.7.1 (#5958); the workaround is correct on both.
Tests
- Live tests now report as skipped without a conductor (they used to pass silently).
coverlet.collectoradded:dotnet test --collect "XPlat Code Coverage".- Live test classes run one at a time (shared sandbox; concurrent installs hit conductor DB errors).
RegisterDnais checked to fail cleanly on 0.7.0 (no such admin request; already obsolete).
Remaining app/admin APIs verified live
Live tests now cover every API area against a real 0.7.0 conductor: clone cells (create, disable, enable, delete), deferred membrane proofs (provide → enable), WASM host functions, op timings on both interfaces, DNA definitions, capability grants, both state dumps, token issue/revoke, and installing from bytes. 85 tests, 14 of them live.
Fixes
- Signals were never delivered: the dispatcher routed on the inner type (which is
app,app_directorsystemin 0.7.0, neversignal), and the decoder expected the pre-0.4{"App": [cell, data]}shape with agent and DNA hash swapped. Signals now route on the outerWireMessagetype, skip request-id matching, and decode{"type", "value": {cell_id, zome_name, signal}}(newSignalValue). - Tuple-variant requests sent
{field: value}objects where the conductor wants the bare value: countersigning (Box<CellId>),revoke_app_authentication_token(token as an int array),get_compatible_cells(DnaHash).get_dna_definitiontakes aCellIdin 0.7.0; the DNA-hash overload now looks up a matching cell, and aCellIdoverload was added. dump_full_statewas routed to thedump_statedecoder and hung; it's now decoded properly, andDumpedStateJSONis always set (the typedDumpedStateis best-effort).- Decoder errors no longer hang calls:
HandleError(args, …)threw (the default when nothing subscribes toOnError) before decoders raised their result. It now reports the error on the result. list_wasm_host_functionsdidn't unwrap the response envelope.DumpOpTimingsAsyncwas missing fromIHoloNETClientAppBase.- Install from bytes: new
InstallAppFromBytesAsync(AppBundleSource::Bytes). - Embedded binaries: the hc-tool path wrote the conductor binary out as
hc.exeinto the wrong variable, and extracted binaries were never refreshed after an upgrade (only written when missing). NowResources.hcis used, and stale copies are re-extracted. - Large responses hung:
DataHelper.ConvertBinaryDataToString(NextGenSoftware-Libraries), called on every response, was O(n²); a full-state dump never finished. Fixed in that repo (842296f). - Feature-gated APIs: countersigning (
unstable-countersigning) andGetCompatibleCells(unstable-migration) don't exist in the standard 0.7.0 conductor. They're now documented on the methods, and they return a clean error instead of hanging. - CS0162 (unreachable
break) fixed; the libraries repo's CS4014/CS0162 warnings fixed.
App flow verified live against Holochain 0.7.0
HoloNET has now run the full flow against a real 0.7.0 conductor and the 0.7.0 OASIS hApp
(C:\Source\OASIS-Holochain-hApp\workdir\oasis.happ, hdk 0.7.0): install → enable → grant
zome-call capability → attach app interface → issue token → authenticate → zome call.
Fixes
- App authentication:
InstallEnableSignAttachAndConnectToHappnow issues an app authentication token and gives it to the app agent. Without one, the conductor closes the app socket on the first request. - Response payloads: about 17 decoders deserialized the whole
{"type", "value"}envelope as the payload, so their results were empty. Affected: auth token, clone cells, countersigning, peer meta info, op timings, capability grants, compatible cells, state dumps, storage info and others. NewDeserializeResponseValue/DeserializeResponseValueAsJsonhelpers unwrapvalue. - Dispatch hang: the dispatcher deserialized every payload as
dynamicjust to readtype. Payloads keyed by hashes (e.g.network_metrics_dumped) throw underMessagePackSecurity.UntrustedData, so the response was never routed and the call hung. Dispatch now reads onlytype. - Conductor errors: the message was read from
"data"(it's"value"), so it was always lost. The base handler also threw before the per-request error event fired, which could hang the caller. It now logs, and callers getIsErrorwith the conductor's message. - Auth token encoding:
AppAuthenticationTokenis a RustVec<u8>, which goes on the wire as an integer array both when issued and when used to authenticate. Fixed withByteArrayAsIntArrayFormatter. - Agent info: the request takes
dna_hashes(cell_idwas ignored), and the response is a list of encoded strings. NewAgentInfos;AgentInfois[Obsolete]. dump_network_metricssends{dna_hash, include_dht_summary}. Stats and metrics are exposed as JSON.install_appsendssource/roles_settings.attach_app_interfacesends the requiredallowed_origins(default"*").RegisterDna/GraftRecordsare[Obsolete]; 0.7.0 has no such admin requests.- Zome results with real records:
nullentry fields (Option::None) threw aNullReferenceException, and decode errors calledHandleErrorbefore the result event fired, so the zome call hung. Now null-safe and non-fatal; live test decodes real 0.7.0 avatarRecords down to entry fields. - Sync wrappers: the 73
XxxAsync(...).Resultwrappers now run viaTask.Run, so they no longer deadlock on a UISynchronizationContext. Unawaited calls (CS4014) go throughFireAndForget, which logs failures. - Other bundled binaries: the
holochain.execopies inTemplates.MAUIandUnoApp.Mobilewere 0.1.5 and are now the verified 0.7.0 build. - 80 tests, including 11 live tests (
HOLONET_LIVE_ADMIN_URI, plusHOLONET_LIVE_HAPP_PATHfor the app flow).
Wire-format corrections (verified against holochain-0.7.0 source)
Breaking changes
DnaManifestnow matches 0.7.0DnaManifestV0(deny_unknown_fields):manifest_versiondefaults to"0";network_seed,propertiesand the flatzomeslist are removed (setintegrity.network_seed/integrity.properties, and put zomes inintegrity.zomes/coordinator.zomes). Code that set the removed members no longer compiles.ZomeManifest:bundledandurlremoved;pathis the only location field.IntegrityManifest.zomes/CoordinatorManifest.zomesareZomeManifest[].IntegrityZomeManifestandCoordinatorZomeManifest(added earlier in 4.1.0 without verification) are[Obsolete]. They are not Holochain types.DesensitizedZomeCallCapGrant.functionsis nowDictionary<string, object>.ListAppsRequest.status_filteris now astring. UseAppStatusFilter.ToWireValue().
Fixes
- Request/response envelope (affected every call):
AdminRequest/AppRequestand their responses are{"type": ..., "value": ...}in Holochain 0.6.1 and 0.7.0. HoloNET sent and read"data", the pre-0.4 key, so the conductor returnederrorfor every call. Confirmed against a live 0.7.0 conductor (Live_OldDataContentKey_IsRejectedByConductor). - Response routing: added
zome_called,storage_infoandop_timings_dumped. Before this, the DumpOpTimings callbacks never fired.generate_agent_pub_keyis no longer tagged as a capability grant. AppStatusFilterwas sent as an integer index, which the conductor reads as a variant index (Runningfiltered byAwaitingMemproofs). It is now sent as"enabled","disabled","awaiting_memproofs","awaiting_restore"or"unrecoverable".Running/Stopped/Pausedare[Obsolete].EnableAppresponse: 0.6.1/0.7.0 returnAppEnabled(AppInfo). HoloNET decoded the old{app, errors}shape, which left the enabled app'sAppInfo(and so itsCellId) null.HoloNETDNAManager.LoadDNAalways returnednull(it deserialized into an interface and swallowed the exception). Also fixed:throw ex;→throw;, and theStreamWriteris now disposed.- Bundled conductor:
Resources/holochain.exeandhc.exeare now the official holochain-0.7.0 Windows builds. Their SHA-256 hashes match the GitHub release digests. - Capability grants:
CapAccessandGrantedFunctionsare serialized as{"type": ..., "value": ...}, as the conductor expects. HoloNET previously sent{"Assigned": ...}/{"All": null}. 0.6.1 used the same tagging, so this bug predates the 0.7.0 upgrade. NewCapAccessbuilder;CapGrantAccessUnrestricted/Transferable/Assignedare[Obsolete]. - Clone cells:
CloneCellIdis sent as{"type": "clone_id" | "dna_hash", "value": ...}. The enum has no CellId variant. Existing overloads still accept a clone-id string, a DNA hash, or a CellId (its DNA hash is used) viaCloneCellId.Normalize. CellInfodecoding: the conductor sends{"type": "provisioned" | "cloned" | "stem", "value": {...}}, butCellInfoexpected{"provisioned": {...}}, so every cell decoded empty.CellInfoTypecame backNone, noCellIdwas captured, andInstallEnableSignAndAttachHappaborted with "CellType Is Not Provisioned". Fixed withCellInfoFormatter.- Tests now assert the exact wire JSON for these types. 76 tests in total, including
LiveConductorTeststhat run against a real conductor whenHOLONET_LIVE_ADMIN_URIis set.
See AUDIT.md for the full audit, the evidence for each finding, and what remains open.
Post-upgrade polish (v4.1.0 follow-on)
Further hardening and completeness work on top of the 0.7.0 upgrade:
DesensitizedZomeCallCapGrantandCapAccessInfotyped (Data/Admin/Responses/):CapGrantInfo.cap_grantis nowDesensitizedZomeCallCapGrant(typed) instead ofdynamic.CapAccessInfocarriesaccess_type(string) and optionalassignees(AgentPubKey[]). Verified againstholochain_zome_types0.7.0.- DNA manifest restructured (
Data/Admin/Requests/Objects/). Correction: this was written without checking the Rust source, and parts were wrong (origin_time/quantum_time,IntegrityZomeManifest/CoordinatorZomeManifest, string coordinator dependencies). The verified 0.7.0 shape is in "Wire-format corrections" above; the invented types are[Obsolete]. EnableCloneCellRequest.clone_cell_iddoc comment updated with wire-format note (matches Disable/Delete treatment from the main 0.7.0 pass)..gitattributesadded:* text=auto, CRLF for.cs/.csproj/.sln/.md, LF for JSON/YAML — silences persistent CRLF warnings on commit.- Test count: 55 — covers
DumpOpTimingsRequest(with/without cursor),IntegrityZomeManifest,CoordinatorZomeManifest(verifies string deps),DnaManifestintegrity+coordinator round-trip,CapAccessInfo(Unrestricted, Assigned),DesensitizedZomeCallCapGrant,OpTimingsDump×3; all green. - TestHarness
v4.1.0— Summary/Description updated to Holochain 0.7.0; conductor paths configurable viaHOLONET_*env vars noted in release notes. - Sibling packages (ORM, HDK, HyperNET, Manager) bumped to v4.1.0 with updated NuGet
Summary/Description referencing Holochain 0.7.0 and a
v4.1.0PackageReleaseNotesentry.
Holochain 0.7.0 Wire Protocol Upgrade
Upgrades HoloNET's wire protocol from Holochain 0.6.1 to 0.7.0, verified against the real Rust
source in the holochain repo at tag holochain-0.7.0
(holochain_conductor_api, holochain_types, holochain_zome_types).
Key changes:
- tx5/WebRTC transport removed:
signal_urlandwebrtc_configfields removed fromNetworkConfig/Kitsune2Config(Data/Config/Kitsune2Config.cs). iroh (QUIC) is now the sole network backend.Kitsune2ConfigretainsBootstrapUrl,RelayUrl,TargetArcFactor, andAdvancedJson. DnaStorageInfofields removed (Data/Admin/Responses/Objects/DnaStorageInfo.cs):authored_data_size,authored_data_size_on_disk,cache_data_size, andcache_data_size_on_diskwere removed from the conductor wire shape in 0.7.0. Onlydht_data_size,dht_data_size_on_disk, andused_byremain.AppStatusFilter.AwaitingMemproofsadded (Enums/AppStatusFilter.cs,Enums/AppInfoStatusEnum.cs,Data/App/Responses/AppInfo.cs): new app status introduced in 0.7.0 for apps that have been installed but are waiting for membrane proof submission.DnaDefalias (Data/Admin/Responses/DnaDef.cs): the Holochain JS client renamedDnaDefinition→DnaDefin 0.7.0. ADnaDefsubclass is provided for forward compatibility while keeping the existingDnaDefinitionname.DumpOpTimings— new paginated API (new in 0.7.0): wired in both the admin and app interfaces:- New request type
DumpOpTimingsRequest(Data/Admin/Requests/DumpOpTimingsRequest.cs) withdna_hash, optionalcursor(OpTimingsCursor), and optionallimit. - New response types
OpTimingsDump,OpTimingDump,OpTimingsCursor(Data/Admin/Responses/OpTimingsDump.cs). HoloNETRequestType.AdminDumpOpTimings/AppDumpOpTimingsandHoloNETResponseType.AdminOpTimingsDumped/AppOpTimingsDumpedadded.AdminOpTimingsDumpedCallBackEventArgs/AppOpTimingsDumpedCallBackEventArgsadded (EventArgs/EventArgsAdmin.cs).DumpOpTimingsAsync/DumpOpTimingswired inHoloNETClientAdmin(admin interface: conductor fndump_op_timings) andHoloNETClientAppBase(app interface).
v4.0.0 - 2026-10-11 (Holochain 0.6)
Holochain 0.6.1 Wire Protocol Upgrade
Earlier "version bump" work only updated version strings/comments without changing the actual
wire protocol, leaving HoloNET's real on-the-wire shapes at roughly Holochain 0.2.x-0.3.x while
docs claimed 0.5.6. This upgrade re-verifies and re-implements the wire protocol against the real
Holochain 0.6.1 Rust source (holochain_conductor_api, holochain_types, holochain_zome_types
at tag holochain-0.6.1 on GitHub) so HoloNET's serialization actually matches a 0.6.1 conductor.
Key changes:
- Zome call signing payload (
Data/App/Requests/ZomeCall.cs,ZomeCallSigned.cs): replaced the old flattenedcell_id_dna_hash/cell_id_agent_pub_keybyte arrays with a properCellIdtuple type (Data/App/Requests/CellId.cs) matchingholochain_zome_types::cell::CellId(DnaHash, AgentPubKey). AddedData/App/Requests/ZomeCallParamsSigned.csmirroring the real 0.6.1 wire shape sent over the app websocket interface (holochain_conductor_api::app_interface::ZomeCallParamsSigned { bytes, signature }), used byHoloNETClientAppBasewhen constructingcall_zomerequests. - New Admin/App message types added to
Enums/HoloNETRequestType.cs/HoloNETResponseType.cswith corresponding request/response classes underData/Admin/Requests,Data/Admin/Responses,Data/App/Requests,Data/App/Responses: RevokeZomeCallCapability, ListCapabilityGrants, PeerMetaInfo, IssueAppAuthenticationToken, RevokeAppAuthenticationToken, GetCompatibleCells, CreateCloneCell/EnableCloneCell/ DisableCloneCell, countersigning, ListWasmHostFunctions, ProvideMemproofs. - Typed DumpNetworkStats/DumpFullState responses:
DumpNetworkStatsResponse(with nested transport stats) andFullStateDumpedResponse/IFullStateDumpedResponsegive typed, deserialized access to conductordump_network_stats/dump_statedata, while the legacy raw-JSON string fields (NetworkStatsDumpJSON,DumpedStateJSON) are kept as an escape hatch for callers depending on the old shape. NetworkConfig(Data/Config/NetworkConfig.cs) added and wired intoHoloNETDNAto carryRequestTimeoutS, matching the move ofrequest_timeout_sfromConductorConfigdirectly toConductorConfig.network(NetworkConfig) in Holochain 0.6.1.CallZomeOptions(Data/App/Requests/CallZomeOptions.cs) added as an optional trailing parameter onCallZomeFunctionAsync, allowing a per-call timeout override that falls back toHoloNETDNA.NetworkConfig.RequestTimeoutS. Existing overloads remain unchanged/backward compatible.- Removed dead scaffolding:
InitializeIntegratedKeystoreAsync/InitializeCachingLayerAsync/InitializeWASMOptimizationAsyncand theirTask.Delay-only helper methods (the "Holochain 0.5.6+ Enhanced Features" block inHoloNETClientBase.cs), plus the unusedKeystoreConfig/CacheConfig/WASMConfigclasses and the correspondingHoloNETDNA/IHoloNETDNAproperties. None of this mapped to any real Holochain wire protocol or conductor config; it was pure unused stub code with no callers outside itself.Kitsune2ConfigandQUICConfigwere removed for the same reason. - TestHarness / doc-comment cleanup: updated hardcoded
holochain-0.1.5conductor/happ paths inNextGenSoftware.Holochain.HoloNET.Client.TestHarness/HoloNETTestHarness.csto0.6.1, and fixeddocs.rs/holochain_types/0.2.1doc-comment links (inInstallAppRequest.cs,CoordinatorSource.cs) to point atdocs.rs/holochain_types/0.6.1, which is the matching crate version for theholochain-0.6.1release.
Not verified
- No authoritative Rust struct could be found for a
CallZomeOptions-equivalent wire type inholochain_zome_types/holochain_conductor_api/holochain_typesat tagholochain-0.6.1;CallZomeOptionshere is a HoloNET-only client-side convenience type (see its doc comment), not a verified mirror of a Rust struct.