Konclave: A group vault on Zcash | FROST

Hi everyone,

I’m Daniel Gorgonha, co-founder of DeegaLabs, a software engineering studio in Florianópolis, Brazil, with 10+ years of software development behind me. I got into privacy through practice. In a local circle on privacy and community safety, I built Safe City, an app for anonymous neighborhood alerts here in Florianópolis, with the code public precisely so anyone can audit that there is no tracking. That project pulled me deeper into cryptography and privacy tech.

Last year I attended the Ipê Village conference, two days at the hotel in Jurerê. This year I came back as a volunteer and on the architecture track, presented a valocracy project, and spent nearly the whole month at the workshops. At the Privacy House, during the Raycash workshop on building onchain apps with privacy, I met @michae2xl, the first Zcash ambassador in Brazil and one of the sponsors of the event. I was also there for the session by pacu, Zcash’s developer relations engineer, on contributing effectively to the Zcash ecosystem. That talk, honestly, shaped how I approached this project: instead of building something and then showing up asking for support, start by understanding where the ecosystem actually needs hands.

Since then I’ve been getting closer to the ZcashBrazil community, and along the way I built privacy-focused projects like a shielded BTC collateral protocol on Starknet and Cronos Shield, 2nd place among 191 projects at the Cronos x402 PayTech Hackathon. Konclave was born at the ZecHub Hackathon 3.0, where I competed, and I’ve been working on it full time for the last 2 months. I’m here because I believe the right way to be part of this community is to create real value and to listen, and that’s what I intend to do.

So here it is, and I’d genuinely value your feedback.

What we built

Konclave is a GUI for FROST threshold vaults on Zcash: a group treasury where spend authority is split t-of-n across members by real DKG, the key is never reconstituted (at creation or at signing), and every transaction is shielded. Propose, approve to quorum, sign, broadcast, account. In plain language, no CLI.

We built it because the Foundation’s FROST tooling is excellent but, as ZF itself has noted, wallet integration is the missing piece. “Easy multi-sig tools for shielded addresses” is also a named ZCG funding priority, which is what pointed us here.

We learned a great deal from Zkool, by @hanh, which already does shielded FROST and solved real problems before we did. We are not claiming the first FROST on Zcash. What we did differently was take the whole ceremony into the browser, with nothing to install, and wrap it in a treasury flow: proposal, approval, signing, and a book.

What is proven (verifiable, not claimed)

12 mainnet transactions, each a real FROST ceremony with the key never reconstituted. Quorums proven: 2-of-2, 2-of-3 and 3-of-4.

Each one is a first: the first time a capability was proven on the live network. It is not a log of every send; the vaults have made more transactions than that, and the ones that only repeat something already listed are deliberately left out. A row there is a claim you can check, not evidence of volume.

Among them:

  • an application-driven quorum payment
  • a private payroll: one shielded transaction, N outputs, each payslip in an encrypted memo
  • a send from a vault born of real DKG
  • the full Orchard to Ironwood cycle under NU6.3, including the first Ironwood-pool spend
  • a browser-signed broadcast, two tabs over a blind relay (3022420a…)
  • a ceremony across separate physical machines, over the internet: two people in two places, each browser holding only its own share (aec83baf…, block 3,460,285)
  • a 3-of-4 vault operated by someone other than me (b496fc3c…)
  • and a private payroll on the web path, post-Ironwood: 2 beneficiaries in a single V6 transaction (7c4c1dd5…)

248 orchestrator tests and 189 UI tests, CI on every push, open source (Apache-2.0/MIT).

You do not have to trust any of this: node scripts/verify-proof.mjs reads docs/PROOF.md and checks every txid against public explorers. The script reads the same document the proof page does, precisely so the two cannot drift apart.

Site: konclave.xyz · Code: GitHub - deegalabs/konclave: The vault that decides together. A local-first, browser-native collective Zcash treasury using FROST threshold signatures. Private on the outside, transparent on the inside. · GitHub

No cryptography was reimplemented. In the browser we run the Foundation’s own crates compiled to WebAssembly (frost-rerandomized and reddsa), plus librustzcash. On the local path we use frostd, frost-client and zcash-sign directly.

Honest limits

The chain does not prove where the signers were, for the same structural reason it does not prove the signature was a threshold one: an aggregated FROST signature is indistinguishable from a single-signer one. The cross-machine ceremony rests on the two operators and the ceremony trail, not on the block.

The hosted helper is view-only, not blind. It holds the vault’s UFVK in order to build and broadcast the transaction, so it sees the movements and the memos. It never receives, derives or stores a share, and the relay that carries the ceremony is a blind mailbox. But the distinction matters and we would rather say it.

Quorum policy and proposal expiry are application-enforced, not consensus-enforced, and we say so in the docs.

Some of the proof txids came from trusted-dealer vaults; the DKG-vault sends and the browser broadcasts came from keys born by real DKG.

The desktop app exists and is signed, but has not been validated on each platform. The macOS build is not notarized and Gatekeeper refuses it, so we have disabled the downloads on the site until that is fixed. The vault runs entirely in the browser meanwhile.

This is beta and under active hardening: the last few weeks have been as much about auditing what already existed as about building, and what we find becomes a public issue before it becomes a release. It is self-custodied software: each member’s key share stays on their own device, and we hold no one’s funds.

Who it’s for

Treasurers who shouldn’t be a single point of failure; cooperatives and community funds that decide together; and NGOs, journalists and activist orgs for whom a transparent multisig is a liability, because it doxes donors, salaries and structure to anyone watching the chain.

What’s next

We’re onboarding a few pilot groups now, and I intend to submit a proposal to ZCG in the next round: evolving Konclave from a proven prototype into a maintained product (cross-device ceremonies, hardening, and real-org onboarding). Before that, I’d rather listen: what would make this genuinely useful to this community? What are we missing?

Thanks for reading. This stands on the Zcash Foundation’s FROST tooling, and we learned a great deal from Zkool along the way.

Credit where it is due: the @zcashfoundation team, and @hanh for Zkool.

Daniel Gorgonha · DeegaLabs

9 Likes

I met Daniel in the south in Brazil while I was at ipecity (a pop-up city / a network state) in April, at an event where Josh also spoke virtually. It was a funny coincidence that he had previously won a hackathon with a project named “Shield,” so he already scored some points with me there lol.

But in all seriousness, he and his wife, both developers, have a great attitude and have remained interested in Zcash ever since. The merit is entirely his. I supported the project with product direction and testing, and I clearly have skin in the game, and I’ll be using the system for Zcash Brazil. Congratulations on the project.

1 Like

Thank you, @michael2xl. Coming from you, that means a great deal, and so does the mentorship behind it.

I opened this thread asking what would make Konclave genuinely useful to this community. The honest answer turned out to be what you did: put it in front of a real group and real money. The Zcash Brazil treasury now running as a 3-of-4 FROST vault on Ironwood, for payroll and proposals, is the first time Konclave has operated a real collective treasury instead of a demo, and that has shaped what I build and how I test it far more than any feature list could.

I want to name the partnership plainly. Having a first group that is patient with the rough edges and clear about what a treasurer actually needs is the reason it keeps getting better, and more robust under the hood. I will keep sharing here what changes and what is still open, honestly.

Grateful to be building on the Zcash Foundation’s FROST tooling, and grateful to have Zcash Brazil as the first hands on it. Thank you for the trust and the partnership.

2 Likes

Konclave update: 27 August to 7 September

Eleven days since this thread opened. 112 pull requests merged, four new mainnet transactions in the proof file, and v0.3.0 tagged. Most of the work went to one question: what does an outsider learn about a vault, and what can they do to it. Below is what changed, by area, with what is still open at the end.

Privacy: the vault id stopped being a key

A vault id used to be enough to read a vault’s books through the hosted helper. Every seated member now holds a per-vault random secret S, minted at the DKG and sealed to members over the encrypted channel, persisted sealed at rest like the share.

  • Private reads (balance, transactions, ceremonies, proposals, ledger, members) require HKDF(S, "read") in a header, never the URL. A leaked id answers 401.
  • The signing room is derived from S rather than the group key, so an id-only outsider can neither compute it nor observe it.
  • A vault export is one opaque blob: metadata, share, S and beneficiaries all under the passphrase. A leaked backup reveals nothing, not even the vault id.
  • The viewing key was still going to the browser in plaintext. It decrypts every payslip the vault has sent, and TLS covers the wire but not the endpoint, where an extension with host permissions or a TLS-terminating proxy reads it. It now goes out sealed to the vault’s registered devices, and the helper refuses to serve it unsealed.

The relay learned less, and can be lied to less

The coordination relay is a mailbox. It is now blind to what a vault pays and to whom: each device derives a persistent comms key from its share, registers it, and the helper hybrid-seals the signing request to the seated devices. The ceremony no longer re-broadcasts the transaction.

Seating in the signing room is authenticated, so an outsider can no longer take a seat or forge room messages, and a sign response that does not verify is rejected instead of killing the send. Both were proven against the live relay rather than in a test.

Governance writes are authenticated

A vote or a member rename from anyone who could reach the helper used to be accepted. A write is now signed by an Ed25519 key derived from the seat’s FROST share, and refused otherwise. It turns on per vault, at the first device that unlocks, so vaults created before it keep working.

Recovery: a backup that rebuilds the vault, not just the seat

The export omitted the viewing key, so a member restoring from their own encrypted backup held real spend authority over money they could not detect. It now carries the viewing key and the wallet birthday, without which a rebuilt wallet scans from the current height, finds nothing, and cannot be rescanned.

open-export.mjs opens a backup with Node’s own crypto: no Konclave, no packages, no network. It reports whether the backup is complete rather than printing what is in it.

Availability

On 27 August the helper served one request at a time, so a five minute send made the whole service indistinguishable from dead, health check included, and it took a vault down. Both the helper and the relay now run a worker pool with a bounded body read. The incident has a postmortem in the repo.

The app

  • A reload asks for the passphrase on the screen you are on, instead of sending you back to the vault list to pick the vault you were already inside.
  • A passkey can open the books, enrolled per device. Sending money still asks for the passphrase.
  • The passphrase can be rotated. It was the one credential with no way to change it.
  • PBKDF2 went from 210,000 iterations to 600,000. The old count is the OWASP figure for SHA-512 and we use SHA-256. Existing vaults keep opening at their own count, which travels with the ciphertext.
  • Text and control edges now meet WCAG AA in both themes, checked by a test that recomputes the ratios from the design tokens rather than trusting an audit’s arithmetic.

Proven on mainnet

The 12 transactions listed when this thread opened are 16, each verifiable with the checker in the repo. The four added in this period each prove something the earlier ones did not:

  • A send whose closing signature was made on an Android phone in a mobile browser, its share sealed on that phone, through the installed PWA.
  • A send that survived a live bogus-response injection: an outsider holding only the public vault id posted a structurally valid but cryptographically bogus signature response into a running ceremony, and the send completed.
  • A send with the relay blind to the payment, attested by the captured room trace rather than by the block, since the block shows an ordinary shielded transaction.
  • A send watched from outside throughout: every private read answered 401 and the public endpoint stayed byte identical before, during and after. A vault mid-payment was indistinguishable from an idle one.

Quorums proven: 2-of-2, 2-of-3, 3-of-4. The helper is still view-only rather than fully blind, which is the limitation named when this thread opened and it has not moved.

Still open

The member list and the remaining private reads still reach the browser in plaintext; sealing covers the viewing key only. A vault created before the read gate cannot fetch its own viewing key, so the export fix does not reach it and its backups still restore the seat and not the vault. Passkey enrolment says nothing when the authenticator has no PRF, because every failure in that path is silent by design. The desktop build has never been validated on real per-platform hardware.

Where I’d like help

  • Migrating an unprotected vault. The read gate lands per vault, and protecting an existing one means re-creating it and moving the funds with a signed send. There is no automatic migration and I do not think there should be, because an automatic one would have to mint the secret somewhere the members are not. If you have taken a threshold setup through a key rotation, I want to know what you did with the old one.
  • The passkey is per device on purpose, and I would like to be wrong. WebAuthn PRF guarantees nothing about its output surviving a passkey sync, and Apple’s own forums have it failing concretely: an iCloud-synced credential returning a different PRF result on the second device ( Security Verification and /822523), and Safari’s cross-device QR flow not supporting the extension at all (/774112). If anyone has measured PRF stability across a synced credential on current OS versions, that changes the design rather than the wording.

These updates will be weekly from here. If you try it, tell me what breaks. It runs on mainnet with real ZEC, and every claim above is a txid or a test you can run.

Repo: GitHub - deegalabs/konclave: The vault that decides together. A local-first, browser-native collective Zcash treasury using FROST threshold signatures. Private on the outside, transparent on the inside. · GitHub · App: https://www.konclave.xyz