Skip to content
sane-appsPublic

About

Mac-native view-only Zcash books: import UFVK, classify notes, export scoped proof packs. Cannot spend.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

ZecBooks

ZecBooks · site: zecbooks.app · source: sane-apps/SaneBooks (historical repo path).

ZecBooks

Private books for shielded Zcash — Mac-native, local-first. Import a viewing key, classify income / change / expense, and share a scoped proof pack with your accountant. Cannot spend ZEC.

Download for Mac · MIT open source (LICENSE)

Welcome

ZecBooks welcome — import a viewing key

Ledger

Classified ZEC ledger

Proof pack

New proof pack date range

Share with disclosure

Share proof pack disclosure audit

Accountant Reader

ZecBooks Reader unlock

CipherPay gets you paid privately. ZBooks runs team treasury. ZecBooks is the Mac bookkeeping layer: private money, kept with honest books — change ≠ income, and an expiring .sanebooks pack — not a permanent UFVK.

The problem

Shielded Zcash already has viewing keys (ZIP 316). Merchants can take ZEC privately. What is missing is an accountant layer: classify change so it is not counted as income and hand a CPA a scoped artifact — not a permanent UFVK and not an unreviewed wallet dump. Fiat marks remain user/import supplied; ZecBooks does not currently claim a live price-source integration.

Community signal: Is anyone actually using viewing keys for business accounting? (Jun 2026).

The solution

Step What happens
1 Import a UFVK (uview…) for bookkeeper mode (or UIVK for receivables-only, with a permanent degraded-mode banner)
2 Sync compact history via lightwalletd (ZcashLightClientKit 2.7.0-rc.4; demo via SANEBOOKS_FORCE_MOCK=1)
3 Tag rows: Income / Expense / Change / Fee — change is excluded from income totals
4 Build an encrypted, Reader-expiring .sanebooks pack or intentionally export non-expiring plaintext CSV/PDF
5 Accountant opens Reader mode — read-only rows, no vault key, no chain sync

The Appearance settings include persisted Standard, Large, and Extra Large text sizes. This is app-managed because Apple documents that SwiftUI Dynamic Type does not change text size on macOS; the large layouts scroll instead of compressing or hiding primary controls.

Non-goals

  • Not a wallet — no seeds, no spending keys, no send UI
  • Not CipherPay — CipherPay is merchant checkout / IVK payment detect; ZecBooks starts after money arrives
  • Not ZBooks — ZBooks is team/DAO treasury + SIWZ + approved ZIP 321 payouts (web). ZecBooks is solo owner → CPA on a local Mac with expiring proof packs
  • Not tax software — we export accountant-ready rows; the CPA owns filing
  • Not “temporary UFVK access” — viewing keys are irrevocable; share packs, not raw keys

Security invariants

  1. Reject seed phrases and spending-key strings at import
  2. Prefer bookkeeper mode on UFVK; UIVK never claims complete books
  3. Proof packs carry fingerprint + classified rows only — never embed UFVK/UIVK
  4. Pack footer names lightwalletd endpoint + tip height + “assumes honest LWD”
  5. No iCloud / CloudKit for vault data; the imported key uses ThisDeviceOnly Keychain storage. Live sync also creates sensitive, owner-only Zcash SDK account data in backup-excluded Application Support storage.
  6. CSV/PDF are plainly labeled non-expiring plaintext; only .sanebooks is encrypted and Reader-expiring
  7. Pack format v2 uses PBKDF2-HMAC-SHA256 (600,000 iterations), ChaCha20-Poly1305, authenticated canonical headers, and encrypted private metadata

Ironwood honesty

NU6.3 / Ironwood activated on mainnet at height 3,428,143 (ZIP 258). New shielded receives land in Ironwood, not Orchard.

ZecBooks links ZcashLightClientKit 2.7.0-rc.4 (Ironwood receive/sync; tracking issue #1806 closed). Live path imports a UFVK as view-only and syncs against a configurable lightwalletd (default zec.rocks:443). Demo/offline still uses MockSyncFacade when SANEBOOKS_FORCE_MOCK=1 or the fixture demo key is used.

UIVK/receivables mode cannot import via the public SDK yet — that path stays degraded/honest.

Demo path (offline)

  1. Build and run (below)
  2. Import Viewing Key → Use Demo Key → Continue
  3. Wait for mock sync to catch up
  4. Open a row → classify → New Proof Pack → export .sanebooks / CSV
  5. Reader → unlock pack with passphrase

Build, test, and run

SaneApps Operator Overlay

Requirements: macOS 14+, Xcode 16+.

Use the project wrapper so the Mini, nonzero-test gate, framework repair, receipts, and process cleanup are all applied:

cd ~/SaneApps/apps/SaneBooks
xcodegen generate
./scripts/SaneMaster.rb verify --timeout 1800
./scripts/SaneMaster.rb verify --ui --timeout 1800
./scripts/SaneMaster.rb launch

Direct SwiftPM commands are focused diagnostics only, not release or E2E proof. Debug runs without the sandbox; the Release configuration enables App Sandbox, outbound networking, and user-selected files.

Public distribution is the notarized ZecBooks 0.1.1 Sparkle/direct zip:

Mini verify --ui was green on the current tree (122 tests including UI journeys).

Screenshots / visual audit

Historical Mini captures live under:

outputs/visual-audit-sanebooks/

They are useful references, not proof of the current source. Current clean app-only, minimum-size user-journey captures live under outputs/e2e/2026-08-04/final-green/cropped/; build/test receipts live under outputs/verify/ and are qualified in the current session handoff.

Institutions

Custody and exchange teams run the zecbooks command on Windows, Linux, or macOS. It is a library and a binary, not a second desktop app. It cannot spend.

Keep the spending key offline. Put an incoming viewing key, or a unified full viewing key, on the detection host. Pass --endpoint for that host's own lightwalletd. There is no hidden server. The ledger stays on the host. zecbooks pack writes an expiring .sanebooks proof pack. An accountant opens it with zecbooks open or with the Mac app. The pack does not contain the viewing key.

zecbooks check --key-file viewing.key
zecbooks sync --key-file viewing.key --endpoint https://lwd.example:9067 --out ledger.json
zecbooks classify --ledger ledger.json --id ROW --as change
zecbooks pack --ledger ledger.json --from 2025-01-01 --to 2025-12-31 --expire 2026-04-15 --passphrase-file pass.txt --out year.sanebooks
zecbooks open --pack year.sanebooks --passphrase-file pass.txt

A full viewing key marks notes on the change address as change, and those rows stay out of the income total. An incoming-only key cannot see that address, so you classify those notes yourself. A partial scan will not seal unless you pass --acknowledge-partial. A start after shielded activation is partial unless you pass --birthday for the account. Spends that cannot be tied to a note in this scan also mark the history partial. Prefer --key-file. --key is accepted and warned, because the shell history keeps it.

Build and test from this repo:

cargo test --manifest-path rust/Cargo.toml --locked

Container, from the rust directory: docker build -f Containerfile . Mount the key file and the ledger on /data. Do not copy them into the image.

GitHub Actions builds a checksummed binary for Windows, Linux, and macOS. Nothing in the tool phones home.

A viewing key reveals shielded history. Treat the key file like a bank-feed password.

Docs

Doc Purpose
docs/GRANT_PROPOSAL.md Coinholder-Directed Retroactive Grant application
docs/ZecBooks-0.1.1-PROVENANCE.md SHA-256 + notarization check for 0.1.1
docs/SUBMIT_PACKET.md FPF + forum paste packet
docs/COMPETITIVE_POSITIONING.md vs CipherPay, Zodl, ZGo, Koinly, ZBooks
docs/WALLET_VIEWING_KEY_GUIDE.md How to export a UFVK from common wallets
docs/LIVE_PROBE_FUNDING.md How to fund the live probe UA for a real ledger row
SECURITY.md / PRIVACY.md Threat model and data boundaries
AGENTS.md Agent / contributor project facts

License

MIT. Contact: hi@saneapps.com

About

Mac-native view-only Zcash books: import UFVK, classify notes, export scoped proof packs. Cannot spend.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages