Harassment, misconduct, and whistleblowing reports don't get made when people don't trust the channel. kilio lets anyone report without an account and without an email, seals every submission to your keys before it leaves their device, and still supports a two-way conversation — so you can ask follow-ups and give an outcome without ever learning who they are, unless they choose to tell you.
It is standalone and cross-platform — a single Rust binary plus a desktop app, on macOS, Linux, and Windows. No SaaS backend, no cloud account, no dependency on any hosted service. What you run is what you own — and what you run cannot read the claims it stores.
MIT OR Apache-2.0 · Rust · Tauri 2 · macOS · Linux · Windows · HPKE sealed-at-source · standalone · no cloud
Quick start · What it is · How it works · Screenshots · Privacy model · Architecture · Docs
kilio replaces the "email HR" / third-party ethics-hotline model — the one where the reporter has to trust a vendor's cloud, hand over their identity to begin, and hope nobody in the middle is reading along.
The difference from every incumbent: there is no central server that can read anything. An organization runs its own kilio instance — a laptop with a tunnel, a small VPS, a Raspberry Pi, anything that runs the binary. A reporter opens the public intake page, writes their claim, and their browser HPKE-seals it to the destination team's public key. The instance — and any tunnel or relay between them — only ever stores ciphertext. It is decrypted only inside a handler's app, with a key the server never holds.
kilio is completely standalone. It depends on no hosted service and no account — not even ours. It runs the same on macOS, Linux, and Windows. (Optional, off-by-default seams let it reach further when you want them — see Architecture — but nothing about the core needs them.)
The reporter's only identity is a 12-word receipt passphrase minted at submission. It derives a per-claim keypair, so they can return, read replies, and add details — including, if and when they decide, their contact info — without ever creating an account.
Status: 0.1.0 — early. The sealed-crypto core (
kilio-seal) and the sealed store + branch scoping (kilio-core) have landed and are tested, along with the full design (decisions.md). The server, CLI, web surfaces, and Tauri app are in progress — see the roadmap.
A reporter never authenticates. A handler always does. Between them runs a sealed, anonymous, two-way channel keyed only by a secret the reporter holds.
flowchart LR
reporter["Reporter<br/>(public PWA / TWA)"]
subgraph box["your box — kilio instance"]
direction LR
server["kilio-server<br/>(intake + handler API)"]
db[("SQLite<br/>ciphertext only")]
server <--> db
end
handler["Case handler<br/>(Tauri desktop app)"]
reporter -->|"HPKE-sealed submission<br/>+ PoW stamp"| server
server -->|"sealed reply"| reporter
handler <-->|"opens claims with<br/>the branch private key"| server
tunnel(["one-click tunnel<br/>(cloudflared / ngrok)"])
reporter -.public URL.- tunnel -.- server
- Seal at source. The reporter's device encrypts the claim to the branch's public key. The host stores ciphertext it cannot read.
- Receipt passphrase. 12 words are the reporter's only identity; they derive a per-claim keypair (memory-hard) for return visits and sealed replies. No email, no account, no recovery (by design).
- Anonymous two-way channel. Handlers reply sealed to the claim key; reporters prove control by signing with it. Nobody learns who they are.
- Go public with no infra. Expose the intake page through a tunnel from a laptop, or run behind a reverse proxy / Tor — your choice.
The reporter surface is a calm, public, anonymous intake page. The handler surface is the case-worker desktop app. kilio ships both light and dark — the shots below follow your GitHub theme.
|
|
|
|
|
|
Handler inbox — triage sealed reports across branches; the reporter is always anonymous.
Both surfaces are built mobile-first and ship light and dark. On a phone the handler's sidebar collapses to a drawer and the case view becomes a chat.
Reporter and handler surfaces on mobile, dark mode — anonymous submit, and a case handled on the go.
These four properties are non-negotiable (full detail in
docs/SECURITY.md and decisions.md §3):
| Property | What it means |
|---|---|
| Sealed at source | Claims are HPKE-sealed in the reporter's browser to the branch key. Host, tunnel, and relay see only ciphertext. |
| No mandatory identity | No name, email, or contact detail is ever required. The receipt passphrase is the only identity. |
| Anonymous two-way channel | Sealed replies both directions, bound to a secret only the reporter holds. |
| Metadata minimization | No IP/User-Agent logging on the intake path, size-bucketed ciphertext, an anonymous proof-of-work cold-contact gate instead of accounts, no third-party assets. |
Primitives are RFC 9180 HPKE (DHKEM-X25519 / HKDF-SHA256 / ChaCha20Poly1305)
via the audited hpke crate, Ed25519, Argon2id, and BLAKE3. No primitive is
hand-rolled; only their composition is ours.
Status: 0.1.0. Today you can build the workspace and run the sealed-crypto core's test suite. The runnable operator flow lands as the surfaces do.
- Rust stable (1.85+). Node 20+ and the Tauri prerequisites for the desktop app (as surfaces land).
git clone https://github.com/vul-os/kilio
cd kilio
cargo build --workspace
cargo test -p kilio-seal # the sealed-submission crypto spinekilio init # generate a branch keypair (sealed at rest)
kilio serve --port 8787 # intake + handler API, serves the embedded PWA
kilio tunnel start # expose the intake page publicly, no fixed infraOne Rust workspace, one shared web frontend, three ways to run it.
| Crate / app | Role |
|---|---|
kilio-seal |
Sealed-submission crypto: HPKE seal-to-branch, receipt→per-claim keys, sealed-sender envelope, PoW gate. Native and wasm32. ✅ |
kilio-core |
Domain model, SQLite sealed store, the seams, branch scoping. ✅ |
kilio-server |
axum: public intake API + handler API + embedded PWA + tunnel control. 🚧 |
kilio-cli |
kilio init / serve / tunnel / branch. 🚧 |
apps/desktop |
Tauri v2 handler app; opens claims locally with the branch key. 🚧 |
web/ |
React/JSX PWA/TWA — reporter + handler surfaces built (Sanctuary UI); kilio-seal WASM wiring next. 🚧 |
Three seams (thin interface, local default, adapter wired only at the composition root — the ofisi pattern):
- Delivery —
Local(default, standalone) ·Kotva(decentralized, content-blind rendezvous mailbox for cross-org forwarding). - Reachability —
LocalOnly·SubprocessTunnel(cloudflared/ngrok) ·VulosRelay(wede sovereign tunnel). - Identity / deploy mode —
standalone·os(behind a Vulos OS gateway, fail-closed boot gate).
Full contract: docs/ARCHITECTURE.md. Design rationale
and threat model: decisions.md.
- Getting started — build, test, and the operator flow.
- Architecture — crates, surfaces, seams, data flow.
- Security model — the privacy spine, threat model, crypto.
- Design decisions · Roadmap · Changelog
kilio is licensed MIT OR Apache-2.0 — at your option (see LICENSE-MIT and LICENSE-APACHE), matching every sibling in the vulos suite. Contributions welcome — see CONTRIBUTING.md. Found a vulnerability? See SECURITY.md.
kilio is free, standalone software — it runs on its own and needs no hosted service.
Part of the vulos family of self-hostable apps, but independent of it by design.