graincrawl treats Granola auth and encrypted local state as user-owned data.
The default path is private API sync using the desktop session file when it is
already present, plus plaintext cache fallback when Granola still writes one.
allow_private_api = trueallow_desktop_cache = trueallow_encrypted_json = falseallow_opfs = falsekeychain_prompt_mode = "explicit"persist_helper_keys = false
That means graincrawl doctor, status, notes, and export must not prompt
macOS Keychain. A Keychain prompt is allowed only after the user explicitly
enables encrypted sources and invokes an explicit unlock command.
Encrypted JSON support runs only inside the authorized public command path.
After configuration and explicit-unlock checks, graincrawl snapshots the
requested encrypted files into memory, reads the Granola Safe Storage
Keychain item through /usr/bin/security, unwraps the DEK, and decrypts only
the requested JSON. Keychain access has a 30-second timeout. The DEK, Keychain
secret, and decrypted Granola JSON are never written to disk. There is no
hidden helper command that can bypass the public authorization checks. OPFS
remains unsupported.
allow_encrypted_json = true permits the feature, but never invokes it by
itself. The operator must also run graincrawl unlock encrypted-json or pass
--unlock encrypted-json to sync.
- Do not log tokens, refresh tokens, decrypted keys, cookies, or raw encrypted payloads.
- Do not read or mutate live Granola files in tests.
- Snapshot encrypted files into memory before Keychain access; never write decrypted Granola JSON to disk.
- Use temp config, cache, and database paths for tests.
- Prefer
graincrawl secrets --jsonbefore debugging unlock issues. - Prefer
graincrawl unlock --jsonbefore enabling encrypted sources.