Pacto is a Tauri v2 desktop application that combines a SvelteKit/Svelte static SPA frontend with a Rust backend crate. The two halves communicate through Tauri’s typed invoke/event bridge. The Rust backend owns all cryptographic operations — Nostr key handling, MLS group state, EVM signing — while the frontend manages UI rendering, Svelte stores, and read-plane EVM queries via viem. Outbound traffic flows to two distinct external networks: Nostr relays for messaging and EVM/Aztec RPCs for on-chain governance.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/covenant-gov/pacto-app/llms.txt
Use this file to discover all available pages before exploring further.
System overview
Layer responsibilities
| Layer | Role | Key files |
|---|---|---|
| Frontend | UI, state, user flows | src/routes/+page.svelte, src/stores/, src/components/, src/lib/ |
| Tauri bridge | Typed frontend ⇄ backend RPC and events | src-tauri/src/lib.rs (invoke_handler + AppHandle::emit) |
| Rust backend | Crypto, Nostr/MLS relay logic, EVM signing, SQLite, media | src-tauri/src/lib.rs, src-tauri/src/{nostr,mls,chat,message,rumor,db,account_manager,evm}/ |
| Network | Nostr relays for messaging; RPCs for chain reads and sends | TRUSTED_RELAYS, ALCHEMY_RPC_KEY, user RPC prefs |
Data flows
1. Messaging flow
Nostr events travel in two parallel paths depending on the conversation type. Direct messages use NIP-59 Gift Wraps (kind 1059) and inner rumor kinds such as 14 (text), 15 (file), 7 (reaction), and 30078 (typing). MLS group messages travel as kind 444 on the wire, while MLS welcome invites arrive wrapped inside a Gift Wrap as kind 443. Both paths ultimately land in the same unifiedChat / Message model in SQLite.
2. EVM wallet flow
Key derivation, reads, and writes are split across layers intentionally. The same BIP-39 seed derives both Nostr keys and EVM addresses. Reads such as balances, contract observation, and receipt polling happen in the frontend via viem. Writes — WalletBar sends, treasury deployments, and governance transactions — happen in Rust using Alloy. Signer purpose also matters:squad keys can act on treasury and governance, while advanced keys are restricted to the Advanced panel.
3. Storage flow
Each Nostr account is fully isolated under its own npub directory. The app SQLite database (vector.db) holds chat metadata, events, profiles, and squad infrastructure pointers. The MLS engine database (vector-mls.db) is owned by the MDK engine and stores cryptographic group state. Frontend per-account state is scoped via localStorage keys built with persistenceKey(prefix).
Key directories
| Directory | Purpose |
|---|---|
src/ | Svelte frontend source |
src/routes/ | Single-page static SPA shell |
src/stores/ | Svelte writable/derived stores |
src/lib/ | Typed Tauri wrappers, domain logic, helpers |
src/components/ | Svelte UI components grouped by domain |
src-tauri/src/ | Rust backend crate |
src-tauri/src/evm/ | Wallet, key derivation, RPC, contract bindings, governance |
src-tauri/src/evm/contracts/ | alloy::sol! bindings for pacto-gov, sponsor, Safe, ERC-20, Hats |
static/ | Static assets (twemoji SVGs, etc.) |
docs/ | Authoritative tracked architecture and operational docs |
.cursor/rules/ | Editor-enforced project policies |
.github/workflows/ | Cross-platform release CI |
Security and trust model
Pacto requires no KYC; all identity is cryptographic, expressed as an npub/nsec keypair. The EVM private key is decrypted in Rust only for approved signing operations and is never exposed to the frontend. Message content and secrets are stored encrypted at rest in SQLite; profile data and indexing metadata remain plaintext so they can be searched and indexed efficiently. A PIN-derivedENCRYPTION_KEY (Argon2) is used to encrypt the events.content column — if the key is missing or wrong, the UI displays [Decryption failed] rather than failing silently. There is no independent third-party security audit yet; see docs/audits/README.md.
Cross-cutting conventions
- Greenfield: No public alpha has shipped yet. Prefer clean, minimal paths over legacy-compatibility shims.
- Brief inline comments: Source comments should explain behavior, not architecture. Point to
docs/for structural explanations. - No tracker IDs, spec section markers, or checklist breadcrumbs in source files.
- Public protocol addresses belong in the tracked JSON file
src/lib/evm/pacto-protocol-addresses.json, not.env.
Explore further
Nostr Transport
How Pacto uses kinds 1059, 443, and 444 for DMs and MLS group messaging.
MLS Engine
MDK engine integration, storage layers, threading model, and eviction handling.
Storage
Per-npub SQLite isolation, schema, message encryption, and logout behavior.
Direct Messages
DM architecture, Gift Wrap flow, and NIP-59 rumor kinds.