Security & privacy
Honest scope: what Sheaf protects, and what it cannot.
Sheaf is designed to reduce unnecessary public linkage between treasury operations and individual payouts, subject to the capabilities and limitations of the underlying payment infrastructure. This page summarises the full threat model kept in the repository at docs/security/privacy-threat-model.md.
Who can see what
| Observer | Visible to them |
|---|---|
| Block explorers, indexers, analytics firms | All on-chain data: sender, receiver, amount, token, time, calldata. |
| Validators, sequencers, RPC providers | The same, plus the submitting IP and mempool timing. |
| Route provider (Relay) and its solvers | Every quote, deposit and fill. Its public request feed lists user → recipient pairs without authentication (verified). |
| Wallet providers | The treasury address, every signed transaction, the dapp origin. |
| Sheaf hosting operators | Everything in the database, including names, references and the original CSV. |
| Your finance administrators and approvers | Everything in your organisation, by design. Viewers see redacted addresses. |
What is implemented and tested
- Roles (Owner, Finance admin, Approver, Viewer) enforced on the server in every API route.
- Organisation isolation: every query is scoped by the session’s organisation, never by a client-supplied id.
- Viewers receive redacted addresses from the API, not only in the UI.
- Four-eyes approval: the last editor of the recipient set cannot approve it (configurable).
- Approvals bind to a hash of the recipient set and are invalidated by any change.
- Append-only audit events for every state change, download and export, enforced by the data layer and by database triggers.
- Contractor names, internal references and CSV originals are encrypted at rest (AES-256-GCM).
- Rate-limited sign-in and sign-up; the server refuses to start in production with placeholder secrets.
- Idempotency keys and a duplicate-send guard: a payment is never re-sent while its last attempt is pending or unknown.
- Optional bounded spacing between submissions (0–30 min), off by default, timestamps kept internally.
What is not implemented
- Externally anchored audit storage (the audit table is append-only inside the database, not written to a separate ledger).
- Per-organisation encryption keys in a KMS; one server-side key encrypts every organisation.
- Mixing, shielded pools, zero-knowledge transfers or any privacy protocol.
- Address validation for non-EVM networks.
- Hardware-key or SSO authentication; sessions are cookie-based with scrypt password hashing.
On-chain reality
Same chain, same token (default)
The route provider returns a plain token transfer from the treasury to the recipient. On-chain this is identical to paying directly: no privacy benefit. Sheaf labels these routes “Direct transfer” on the review screen.
Cross-chain or cross-token
The treasury deposits with the provider on the origin chain; a provider solver pays the recipient on the destination chain. The recipient’s incoming transaction does not name the treasury, but amounts, timing and the provider’s public request listing still correlate the two. This is obfuscation against casual inspection, not unlinkability.
Words we do not use
Anonymous. Untraceable. Unlinkable. Invisible. Private transactions. If you see any of these in Sheaf, it is a bug.
Known limitations in the docs