Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Chrome extension

An installable Chrome MV3 extension for using a SithBit account from the browser: wallet login, the onboarding wizard, aliases, balances, do-not-disturb schedules, delegated encryption-key management, and an in-popup mail reader — the same shared panes the Thunderbird, Outlook, and webmail clients carry, because all four hosts run the same shared core (webclients/shared/). Everything that must be signed is signed inside the extension by a WebAssembly module compiled from this workspace’s own crates; the server only relays already-signed transactions and never holds your key.

It reads mail two ways, exactly as webmail does. When an account-api is reachable it shows the full three-pane reader — folder rail, message list, message view, compose, and search — over the API’s /v1/mail surface. With the mail server down (or no account API configured at all), it falls back to a trustless on-chain inbox: your mailbox’s messages listed straight from Solana and read by unsealing their IPFS-stored bodies in wasm, no server involved. You can still also point any IMAP/ POP/SMTP mail client at the same account. Either way this same surface also runs in Chrome’s side panel, a persistent panel that stays open as you browse (the toolbar-icon click still opens the transient popup; an Open in side panel button promotes it). It is not a Gmail integration — it is a self-contained SithBit mail client, packaged as a browser extension.

What the operator must run

For the aliases, balances, and encryption-key panes, the account-api needs its [chain] section configured (a mail-grpc gateway plus a Solana RPC endpoint — see the configuration reference); without it those panes report the surface as unavailable while login and the settings panes keep working.

The three-pane mail reader rides the account API’s /v1/mail surface, so it appears whenever an account API is configured. The trustless on-chain inbox talks to no server at all — it needs only a Solana RPC endpoint and an IPFS gateway (both under Connection settings), so it keeps working with the mail server down, and it is the only reader shown when the account API url is left blank.

Installing from the store

Once the extension is published, install it from the Chrome Web Store: open _todo_store_listing_url_ (or search the store for _todo_store_listing_name_) and click Add to Chrome. Store installs update automatically.

Note: the extension is not yet published to the Chrome Web Store. The _todo_store_listing_name_ and _todo_store_listing_url_ placeholders resolve when the listing goes live; until then, install via Building and installing below.

For pre-release distribution the Web Store offers two non-public visibilities — Unlisted (installable by direct link, never surfaced in search) and Private (restricted to a trusted-tester group or a Google Workspace domain) — plus draft sharing with trusted testers, so a pre-GA listing can exist without public exposure. The load-unpacked path below remains the zero-store development route.

Building and installing

cd webclients/chrome
./build.sh          # wasm-pack build + stages shared/ + zips the package

build.sh writes two things: a staging/ directory (the unpacked extension) and sithbit-chrome.zip (the same tree, packaged). Install it either way:

  • Load unpacked (development). Open chrome://extensions, enable Developer mode, choose Load unpacked, and point it at webclients/chrome/staging.
  • Packaged. Distribute or side-load sithbit-chrome.zip.

An extension package cannot reference files outside its own root, so the shared core and the wasm module are copied into staging/ at build time — always load staging/, never the source tree. The manifest requests the storage and sidePanel permissions and host permissions for http://127.0.0.1 / http://localhost by default, with https://* as an optional grant for pointing it at a remote API.

What it does

Opening the popup routes to one of a few views from the session it probes (see the onboarding wizard):

  • Wallet manager — import more than one Solana keypair file (a JSON array of 64 numbers) into the same Chrome profile, each sealed under its own passphrase (PBKDF2 + AES-GCM), and unlock, switch between, lock, or forget them. Decrypted keys live only in memory and are gone when the browser exits, so each session re-prompts for the passphrases you want unlocked. One unlocked wallet is active at a time; every pane acts on it, and switching between already-unlocked wallets needs no passphrase.
  • Onboarding wizard — a brand-new profile (no wallet stored) or an unlocked wallet with no mailbox drops straight into the shared five-step wizard: create or import a wallet, claim an optional handle, set your default postage, and mint your mailbox on-chain — the mailbox and its alias ride one signed transaction built in wasm.
  • Dashboard panes — once unlocked and mailbox-registered: Balances (wallet SOL, on-chain message count, per-sender stamp lookup), Aliases (every alias pointing at your wallet; registration and transfer stay in the CLI), Domains (list a domain you hold for sale on the open marketplace, or buy a listed one by name and current authority; reassigning a domain’s authority is an operator action, not offered here), Reply bounties (settle reply bounties on-chain — claim one on a message you received and replied to, or refund one you placed that went unclaimed past its deadline), Pinning leases (escrow a refundable deposit asking operators to keep a message’s pinned body past the default retention — create a lease by the message’s CID and id, check a CID for your wallet’s lease, or close it anytime to reclaim the deposit; see pinning leases), Encryption key (publish, rotate, or close a delegated X25519 key; export the secret when it is shown — it appears once), Mailbox (claim your on-chain mailbox and set its registration config — an optional handle, the sending domain, the default postage unknown senders pay per stamp, and an on-chain-only (no IPFS) option; once registered it shows the message count and points per-sender price changes to Balances), Settings (the derived mail password for the active wallet and its IANA timezone), and Do not disturb (weekly or date-range retry windows). Close mailbox sits alongside them and is the one pane that does not act at once: closing runs a two-step, 7-day timelock, so the request only starts a clock — the mailbox stays open and keeps receiving mail, nothing is refunded, and a cancel is offered the whole time — and both rents come back only when you return after the wait and finish the close. The delay prices identity-cycling in time, since an instant refund made discarding a burned sending identity free.
  • Mail — the shared three-pane reader (folder rail, message list, message view, compose, and search) over the account API’s /v1/mail surface. This is the primary in-popup reader, shown whenever an account API is reachable; it is the same reader webmail and the Outlook add-in mount.
  • On-chain inbox — your mailbox’s messages listed newest-first straight from Solana, no mail server: open a row to read it in the Trustless viewer below. A KEPT pane in both modes, and — with the three-pane reader above — the whole of the in-popup mail experience when the mail server is down.
  • Trustless viewer — reads a single on-chain message with nothing but a Solana RPC endpoint, any IPFS gateway, and your unlocked wallet, with the SithBit mail server completely down: pick a message from the On-chain inbox (or enter a mailbox message id) and the extension resolves the message account for its sealed-body CID, fetches the sealed bytes from the gateway, and unseals them in wasm. A wallet-only read only works if the body was sealed to your wallet — a recipient who published a delegated key needs that key’s secret instead. Its header also carries a Reply on-chain action — see Trustless reply and compose below. Once a body has rendered, a Lease this message button beside Reply prefills the Pinning leases pane above with the open message’s CID and id — prefill only: you still review the deposit and submit, and entering a CID by hand works as before.
  • Open in side panel — promotes the whole popup into Chrome’s persistent side panel, which stays open while you browse instead of closing on blur like the toolbar popup. It is the same app either way.
  • Connection settings — where the popup points: the account API, the Solana RPC, the IPFS gateway, and — for trustless sending — the IPFS pin service. This popup never connects to the mail servers itself. They sit in a collapsed disclosure at the foot of every view, including first-run onboarding and the unlock gate — deliberately, and not merely for convenience: reaching them must never depend on being signed in, because signing in depends on the account API these settings configure. If the configured API is unreachable, the popup says so and continues, so you can correct the URL — or blank it to run trustlessly — from where you already are.

Trustless reply and compose

Reading is no longer the trustless surface’s whole story: the Trustless viewer’s header carries a Reply on-chain button, and the popup mounts the same floating on-chain compose card as trustless webmail — a Compose on-chain button opens it blank; Reply seeds it with the decrypted sender and the parent message’s account address. The card is always available (it rides the on-chain path, not the account API) and follows the webmail card’s lifecycle exactly: resolve the recipient and their published key on-chain, seal in the extension’s wasm module, pin the sealed bytes to your configured IPFS pin service, then sign and submit the SendMail transaction. The same seam ships in the Thunderbird extension and the Outlook add-in.

A reply sent this way is an on-chain send, not an SMTP compose: it never touches an outgoing mail server, and the operator’s SMTP/IMAP/spooler pipeline plays no part in delivery — the reply lands as an on-chain message account even while those servers are down. Chain reads, sealing, and pinning go straight to your configured endpoints; the transaction is signed in the extension’s wasm module like every other on-chain action here, and as always nothing the popup talks to can alter what you sign (see Security notes).

The card carries webmail’s three affordances, documented in full there rather than restated here:

  • The reply chip — the draft threads to the parent message with the same privacy-preserving linkage --reply-to makes (only its blake3 hash reaches the chain); Clear drops the link and keeps the draft. See Replying, and attaching a bounty.
  • Attach a reply bounty — an amount in SOL (blank = plain send) and a claim window in days escrow SOL on the message exactly like --bounty/--bounty-window.
  • Inline prepay — no frombox toward the recipient yet? The card holds the draft, quotes the postage (live per-stamp protocol fee included), and Prepay & send buys the stamps then re-sends the held draft once the purchase confirms — the same prepayment rule and behavior as webmail’s card. The Balances pane remains the standing place to buy stamps outside a compose.

Sending needs one endpoint reading does not: Connection settings gains an IPFS pin service URL (ipfsPinUrl, default http://127.0.0.1:8182 — an unauthenticated loopback sithbit-ipfsd) plus its optional bearer token (ipfsPinToken, default empty), where outbound sealed bodies are pinned. As with a remote API origin, saving a non-loopback pin URL prompts for that origin’s host permission on the same Save click — the extension ships with loopback-only host permissions. Operators offering that pin surface should read the pin lifecycle caveat: a client-made pin sits outside any mail server’s pin lifecycle.

Configuration

There is no hosted config: the endpoints live in chrome-store (backed by chrome.storage.local) under the Connection settings pane, each with a loopback dev default so a fresh install runs against a local stack with nothing to set —

  • apiUrl — the account API (default http://127.0.0.1:8180).
  • rpcUrl — the Solana JSON-RPC endpoint for trustless viewing (default a local surfpool at http://127.0.0.1:8899).
  • gatewayUrl — the IPFS gateway serving GET /ipfs/{cid} (default http://127.0.0.1:8183 — e.g. a sithbit-gateway).
  • ipfsPinUrl — the IPFS pin service that receives the sealed body on a trustless send (default http://127.0.0.1:8182 — an unauthenticated loopback sithbit-ipfsd).
  • ipfsPinToken — the optional bearer token for that pin service (default empty — the loopback default needs no auth).

Security notes

  • The wallet secret at rest is exactly as strong as your passphrase.
  • The session token authorizes account changes (password, timezone, DND) for up to 24 hours; on-chain actions additionally require the unlocked wallet, which never survives a browser exit.
  • The API relay cannot alter what you sign: transactions are built from the workspace’s own instruction encoders compiled to wasm, and a parity test pins them byte-for-byte to the CLI’s.