Releases: kaditham-technologies/saavi
Release list
Saavi v0.3.4
- One-click updates. When the banner announces a new release, Saavi now
downloads the update package itself and verifies its signature against a
public key baked into the running binary (Tauri updater, minisign — a
separate key from the GPG release signing key) before offering a single
Install & restart button. Nothing installs without that click; a
package that fails verification is discarded and the browser flow
returns. - One-click updates for .deb installs too. The Tauri updater cannot
drive dpkg, so Saavi walks the manual chain itself: it verifies
SHA256SUMS.ascagainst the release key pinned in the app, checks the
downloaded.debagainst its signed checksum, and installs on your
click through polkit's system authentication (pkexec dpkg -i), then
relaunches. - The update check runs on every launch. It was capped at once per
calendar day, so "restart to see if there's an update" silently did
nothing for the rest of the day. It is still a single GET of our own
static manifest — nothing else changes: no third party, no identifiers,
nothing downloaded or installed.
Install
These builds are GPG-signed (see below) but not yet code-signed with
Apple or Microsoft certificates, so each OS will warn on first launch.
- macOS (
.dmg, universal): drag Saavi to Applications. The build is
not yet notarized, so on first open macOS says it "could not verify that
Saavi is free of malware" and offers only Done / Move to Bin. Click
Done, then System Settings → Privacy & Security, scroll to "Saavi was
blocked", click Open Anyway. Or, in Terminal:
xattr -d com.apple.quarantine /Applications/Saavi.app. Either way,
verify the.sigfirst — that is the check this dialog stands in for. - Windows (
.msior-setup.exe): SmartScreen will show "Windows
protected your PC" — click More info → Run anyway. The installer
fetches Microsoft's WebView2 runtime if it is missing (Windows 10/11 ship it). - Linux:
sudo apt install ./saavi_*_amd64.deb, or
chmod +x saavi_*.AppImage && ./saavi_*.AppImage.
Your keys live in the app's own store (passphrase-locked) — nothing is
uploaded anywhere. Backups are plain text files you save yourself.
Verify this release
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Verifying Saavi v0.3.4
1. Download the asset you want, its detached signature (.sig), and
saavi_pubkey.gpg from this release.
2. Import the key:
gpg --import saavi_pubkey.gpg
3. Check the fingerprint:
gpg --fingerprint "Saavi release signing"
It must read, exactly:
DCF5 773B 84E9 AABA 785F D5A8 4D2A ECE6 8A95 3F46
Compare it against https://kaditham.ie/saavi/ — published outside
GitHub, so a compromised repository cannot swap the key and the
binaries together. If it differs, stop and write to
security@kaditham.me (see SECURITY.md in the repository).
4. Verify the asset:
gpg --verify <asset>.sig <asset>
Expect: Good signature from "Saavi release signing
<webmaster@kaditham.me>". A "key is not certified" warning is
normal here; step 3 is what establishes the trust.
This message is clearsigned by the same release key: save it to a
file and run gpg --verify on it to check it has not been altered.
-----BEGIN PGP SIGNATURE-----
iHUEARYKAB0WIQTc9Xc7hOmqunhf1ahNKuzmipU/RgUCao7mGwAKCRBNKuzmipU/
RttxAQDafxXmt9vipY/uhFAYQQK/uyE2bNG3IwS9ETWBzZY9YgEAz6r1LDYZ8uLG
N20kXuCmXps0yk4LzACfcaLVYmgsWwk=
=hT67
-----END PGP SIGNATURE-----
Saavi v0.3.3
- Header polish: the top-left mark is now the Saavi key tile (the launcher
icon, inlined SVG) instead of the Tamil "சா" letters, and the tagline
reads "Friendly desktop OpenPGP" — here and everywhere else it appeared
(README, package metadata, the installer's short description).
Install
These builds are GPG-signed (see below) but not yet code-signed with
Apple or Microsoft certificates, so each OS will warn on first launch.
- macOS (
.dmg, universal): drag Saavi to Applications. The build is
not yet notarized, so on first open macOS says it "could not verify that
Saavi is free of malware" and offers only Done / Move to Bin. Click
Done, then System Settings → Privacy & Security, scroll to "Saavi was
blocked", click Open Anyway. Or, in Terminal:
xattr -d com.apple.quarantine /Applications/Saavi.app. Either way,
verify the.sigfirst — that is the check this dialog stands in for. - Windows (
.msior-setup.exe): SmartScreen will show "Windows
protected your PC" — click More info → Run anyway. The installer
fetches Microsoft's WebView2 runtime if it is missing (Windows 10/11 ship it). - Linux:
sudo apt install ./saavi_*_amd64.deb, or
chmod +x saavi_*.AppImage && ./saavi_*.AppImage.
Your keys live in the app's own store (passphrase-locked) — nothing is
uploaded anywhere. Backups are plain text files you save yourself.
Verify this release
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Verifying Saavi v0.3.3
1. Download the asset you want, its detached signature (.sig), and
saavi_pubkey.gpg from this release.
2. Import the key:
gpg --import saavi_pubkey.gpg
3. Check the fingerprint:
gpg --fingerprint "Saavi release signing"
It must read, exactly:
DCF5 773B 84E9 AABA 785F D5A8 4D2A ECE6 8A95 3F46
Compare it against https://kaditham.ie/saavi/ — published outside
GitHub, so a compromised repository cannot swap the key and the
binaries together. If it differs, stop and write to
security@kaditham.me (see SECURITY.md in the repository).
4. Verify the asset:
gpg --verify <asset>.sig <asset>
Expect: Good signature from "Saavi release signing
<webmaster@kaditham.me>". A "key is not certified" warning is
normal here; step 3 is what establishes the trust.
This message is clearsigned by the same release key: save it to a
file and run gpg --verify on it to check it has not been altered.
-----BEGIN PGP SIGNATURE-----
iHUEARYKAB0WIQTc9Xc7hOmqunhf1ahNKuzmipU/RgUCao7YDgAKCRBNKuzmipU/
RqABAQDghseZ11zphaR1HxZHuhnZzHIDOenXXEk7A5Ar4L9sYQD+OT9FBIBDXQp3
NEV2pOYlRGFWyxWUaYwOg0oVvjzDhQc=
=nAWL
-----END PGP SIGNATURE-----
Saavi v0.3.2
- The running version is visible. A quiet
vX.Y.Zsits in the status
bar next to the update control — "what version am I on?" no longer needs
the package manager. - Publish your key to keys.openpgp.org. A new action in key details
uploads the public key (own keys only — Saavi store, or system keys with
their secret half here). The key is findable by fingerprint immediately;
the keyserver mails each address a verification link, and by-email search
works once it is clicked. - Revocation certificates. Key details can now save the signed "this key
is no longer valid" note — generated up front with new Saavi-store keys
(and stored alongside them), derived on demand for imported or older keys
(unlock required), and produced by gpg itself for system keys. Keep it
separate from backups; import + publish it if a key is ever lost or
compromised. GnuPG-interop tested.
Install
These builds are GPG-signed (see below) but not yet code-signed with
Apple or Microsoft certificates, so each OS will warn on first launch.
- macOS (
.dmg, universal): drag Saavi to Applications. The build is
not yet notarized, so on first open macOS says it "could not verify that
Saavi is free of malware" and offers only Done / Move to Bin. Click
Done, then System Settings → Privacy & Security, scroll to "Saavi was
blocked", click Open Anyway. Or, in Terminal:
xattr -d com.apple.quarantine /Applications/Saavi.app. Either way,
verify the.sigfirst — that is the check this dialog stands in for. - Windows (
.msior-setup.exe): SmartScreen will show "Windows
protected your PC" — click More info → Run anyway. The installer
fetches Microsoft's WebView2 runtime if it is missing (Windows 10/11 ship it). - Linux:
sudo apt install ./saavi_*_amd64.deb, or
chmod +x saavi_*.AppImage && ./saavi_*.AppImage.
Your keys live in the app's own store (passphrase-locked) — nothing is
uploaded anywhere. Backups are plain text files you save yourself.
Verify this release
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Verifying Saavi v0.3.2
1. Download the asset you want, its detached signature (.sig), and
saavi_pubkey.gpg from this release.
2. Import the key:
gpg --import saavi_pubkey.gpg
3. Check the fingerprint:
gpg --fingerprint "Saavi release signing"
It must read, exactly:
DCF5 773B 84E9 AABA 785F D5A8 4D2A ECE6 8A95 3F46
Compare it against https://kaditham.ie/saavi/ — published outside
GitHub, so a compromised repository cannot swap the key and the
binaries together. If it differs, stop and write to
security@kaditham.me (see SECURITY.md in the repository).
4. Verify the asset:
gpg --verify <asset>.sig <asset>
Expect: Good signature from "Saavi release signing
<webmaster@kaditham.me>". A "key is not certified" warning is
normal here; step 3 is what establishes the trust.
This message is clearsigned by the same release key: save it to a
file and run gpg --verify on it to check it has not been altered.
-----BEGIN PGP SIGNATURE-----
iHUEARYKAB0WIQTc9Xc7hOmqunhf1ahNKuzmipU/RgUCao7UQgAKCRBNKuzmipU/
Rs2RAP9B1CJTxmIcmIKUkK50xlHJAqsSHcYnY1eTRO48VOSHGgD+I4IoTrhYmGN+
ZuUMSfiahtu5NAdkGOHjgr64QWWRqww=
=WxRr
-----END PGP SIGNATURE-----
Saavi v0.3.1
- Key details on a single click. Clicking a key row now opens the details
dialog directly, in both the Saavi store and System GnuPG views — it used to
need a double-click or the toolbar's Details button, so a plain click looked
like it did nothing.
Install
These builds are GPG-signed (see below) but not yet code-signed with
Apple or Microsoft certificates, so each OS will warn on first launch.
- macOS (
.dmg, universal): drag Saavi to Applications. The build is
not yet notarized, so on first open macOS says it "could not verify that
Saavi is free of malware" and offers only Done / Move to Bin. Click
Done, then System Settings → Privacy & Security, scroll to "Saavi was
blocked", click Open Anyway. Or, in Terminal:
xattr -d com.apple.quarantine /Applications/Saavi.app. Either way,
verify the.sigfirst — that is the check this dialog stands in for. - Windows (
.msior-setup.exe): SmartScreen will show "Windows
protected your PC" — click More info → Run anyway. The installer
fetches Microsoft's WebView2 runtime if it is missing (Windows 10/11 ship it). - Linux:
sudo apt install ./saavi_*_amd64.deb, or
chmod +x saavi_*.AppImage && ./saavi_*.AppImage.
Your keys live in the app's own store (passphrase-locked) — nothing is
uploaded anywhere. Backups are plain text files you save yourself.
Verify this release
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Verifying Saavi v0.3.1
1. Download the asset you want, its detached signature (.sig), and
saavi_pubkey.gpg from this release.
2. Import the key:
gpg --import saavi_pubkey.gpg
3. Check the fingerprint:
gpg --fingerprint "Saavi release signing"
It must read, exactly:
DCF5 773B 84E9 AABA 785F D5A8 4D2A ECE6 8A95 3F46
Compare it against https://kaditham.ie/saavi/ — published outside
GitHub, so a compromised repository cannot swap the key and the
binaries together. If it differs, stop and write to
security@kaditham.me (see SECURITY.md in the repository).
4. Verify the asset:
gpg --verify <asset>.sig <asset>
Expect: Good signature from "Saavi release signing
<webmaster@kaditham.me>". A "key is not certified" warning is
normal here; step 3 is what establishes the trust.
This message is clearsigned by the same release key: save it to a
file and run gpg --verify on it to check it has not been altered.
-----BEGIN PGP SIGNATURE-----
iHUEARYKAB0WIQTc9Xc7hOmqunhf1ahNKuzmipU/RgUCao7EugAKCRBNKuzmipU/
RurIAP9YoVSuth6WzMncXNFmrsX5rSm3fyzX+RASbwtmMoMtewD+O2LH3jx1yr0r
b4QJ2bg2FmR1Fgxt+sfivQAhkJgndAA=
=2AQ0
-----END PGP SIGNATURE-----
Saavi v0.3.0
Security (external audit + review response)
-
Signature verdicts on every unseal, both keyrings.
decryptTextand
decryptBytesnow classify EVERY signature (good / bad / expired / revoked
/ unknown-key / unsigned) against candidate keys and return a worst-first
summary — a bad signature can never hide behind a good one. The Saavi-store
unseal shows the same Unsigned / Signed-by / trusted verdicts the system
GnuPG path always did; an unknown signer is looked up by key ID on
keys.openpgp.org (as an untrusted candidate — it can name a signer, never
vouch for one). (audit M1) -
"Your key" is a fingerprint comparison, never a UID substring. The
Verify and unseal trust badges compare the signer's fingerprint against
this device's keys; a stranger's key whose user ID embeds your address can
no longer render as "trusted key". (audit M2) -
Corrupt store records are quarantined, not silently dropped. A ring
that fails to parse is parked under a quarantine key and surfaced as a loud
alert in the key table, instead of the key simply vanishing. (audit M3) -
Imported keys are re-locked with our S2K. A cleartext or weak-S2K
export is re-encrypted under the current passphrase on import. (audit I3) -
System-keyring trust changes now confirm natively.
gpg_import,
gpg_set_ownertrust,gpg_recv_keyandgpg_delete_publicshow a native
OK/Cancel dialog naming the fingerprint before touching~/.gnupg, so a
webview alone cannot poison the keyring every other tool reads. (audit L1) -
Keychain keys unlock lazily. Remembered keys are no longer unlocked on
every key-list refresh (which undid Lock and the idle timer); the table
shows "remembered" from a keychain probe, and a key is decrypted only when
actually used. A hidden window now also auto-locks. (audit L2, L9) -
Decryption belt:
DECRYPTION_FAILEDalongsideDECRYPTION_OKAYnow
counts as failure.human()prefers an error/failure line over gpg's
trailing "not certified" warning. Locked-key detection is structural (key
IDs) with the error-string match only as a fallback. (audit L4, L8, hardening) -
Encrypt-to-self in the sealer so the sender keeps a readable record of
what they sent. (audit L6) -
WKD/VKS hardening: the domain is validated before URL construction, and
the size cap is enforced WHILE streaming (a chunked response with no
Content-Length can no longer defeat it). The update manifest read is
capped the same way. (audit L7, 04) -
MIME layer for PGP/MIME letters (
src/mime.ts): builds and parses the
inner MIME entity that gets encrypted — text + HTML alternatives,
attachments, and the real Subject as a protected header
(protected-headers="v1", the Thunderbird/LAMPS convention) so the
visible subject can stay "...". Base64 leaf parts throughout; the parser
also reads foreign mail (quoted-printable, RFC 2047/2231 filenames,
LF-only input).buildEncryptedMessageassembles the complete outer
RFC 5322 + RFC 3156multipart/encryptedmessage around an armored
ciphertext — the exact wire bytes (webmail imports and submits them; a
desktop export can write them as .eml). -
GnuPG interop tests (
tests/interop.test.ts, skipped when nogpgon
PATH): real GnuPG decrypts our sealed MIME letters and reports GOODSIG on
our signatures; we decrypt GnuPG's ciphertext. Documented finding: OpenPGP
text-mode literals canonicalise line endings, so nothing may depend on
CRLF surviving decryption — the MIME parser is line-ending-agnostic. -
Sealer: the To field accepts addresses separated by commas, semicolons,
spaces or new lines (before, anything but a comma made one unusable
address). When no key is found the message now says why, per address:
the domain publishes none over WKD and keys.openpgp.org has none —
or the domain could not be reached at all.
Install
These builds are GPG-signed (see below) but not yet code-signed with
Apple or Microsoft certificates, so each OS will warn on first launch.
- macOS (
.dmg, universal): drag Saavi to Applications. The build is
not yet notarized, so on first open macOS says it "could not verify that
Saavi is free of malware" and offers only Done / Move to Bin. Click
Done, then System Settings → Privacy & Security, scroll to "Saavi was
blocked", click Open Anyway. Or, in Terminal:
xattr -d com.apple.quarantine /Applications/Saavi.app. Either way,
verify the.sigfirst — that is the check this dialog stands in for. - Windows (
.msior-setup.exe): SmartScreen will show "Windows
protected your PC" — click More info → Run anyway. The installer
fetches Microsoft's WebView2 runtime if it is missing (Windows 10/11 ship it). - Linux:
sudo apt install ./saavi_*_amd64.deb, or
chmod +x saavi_*.AppImage && ./saavi_*.AppImage.
Your keys live in the app's own store (passphrase-locked) — nothing is
uploaded anywhere. Backups are plain text files you save yourself.
Verify this release
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Verifying Saavi v0.3.0
1. Download the asset you want, its detached signature (.sig), and
saavi_pubkey.gpg from this release.
2. Import the key:
gpg --import saavi_pubkey.gpg
3. Check the fingerprint:
gpg --fingerprint "Saavi release signing"
It must read, exactly:
DCF5 773B 84E9 AABA 785F D5A8 4D2A ECE6 8A95 3F46
Compare it against https://kaditham.ie/saavi/ — published outside
GitHub, so a compromised repository cannot swap the key and the
binaries together. If it differs, stop and write to
security@kaditham.me (see SECURITY.md in the repository).
4. Verify the asset:
gpg --verify <asset>.sig <asset>
Expect: Good signature from "Saavi release signing
<webmaster@kaditham.me>". A "key is not certified" warning is
normal here; step 3 is what establishes the trust.
This message is clearsigned by the same release key: save it to a
file and run gpg --verify on it to check it has not been altered.
-----BEGIN PGP SIGNATURE-----
iHUEARYKAB0WIQTc9Xc7hOmqunhf1ahNKuzmipU/RgUCao7ARgAKCRBNKuzmipU/
RgTWAP0S68RW4+0h3yHne92WH6XjVp2il3ys3p8jDVvgBoWrVQD9E6y3SUR54XSG
kD3Y3KukCGQJAVi0v8pf3bvA6QVhRgo=
=aWaN
-----END PGP SIGNATURE-----