Skip to content

Latest commit

 

History

History
123 lines (101 loc) · 6.16 KB

File metadata and controls

123 lines (101 loc) · 6.16 KB

Releasing the Kivuli extension (GitHub-zip beta)

The beta channel is a zip attached to a GitHub release, loaded unpacked. That choice has sharp edges: unpacked installs never auto-update, and removing an install deletes the wallet vault, so both halves of this document matter: the maintainer procedure, and the update procedure users must follow.

Identity: the pinned extension ID

Every official build carries a key in its manifest (set in manifest.config.ts), so Chrome derives the same extension ID for every install, on every machine, regardless of folder path:

fcdigoihpflbghifhmpecihhfjkhabji

Without the key, Chrome hashes the install path, so two testers would get two IDs, and one tester moving the folder would get a "new" extension. Anything keyed to the ID (bug reports, dApp allowlists, a future Web Store migration) would fracture.

The key value is the public half of an RSA keypair. The private half is NOT in the repo and must never be committed (.gitignore blocks *.pem defensively). It lives at:

~/.kivuli/release-key.pem        # private key: back it up, never commit
~/.kivuli/release-key.pub.b64    # the base64 public key, as pasted into manifest.config.ts

The private key is not used by the zip flow at all: the manifest key alone pins the ID for unpacked installs. Keep it anyway: it is what lets a future .crx packaging or Chrome Web Store listing keep this same ID. Back it up like a secret. If it is ever lost, unpacked releases continue unaffected as long as manifest.config.ts keeps the same key string.

Note the ID is pinned, not authenticated: the key is public, so a matching ID proves consistency across installs, never that a build is official. Official builds come from GitHub releases only.

Maintainer: cutting a release

  1. Move the unreleased notes in CHANGELOG.md under the version being cut, and bump version in package.json (the manifest and the About screen both read it, nothing else to bump).
  2. npm test: must be green.
  3. npm run release: builds (typecheck + vite + finalize-dist), then packages release/kivuli-extension-v<version>.zip. The packager refuses a build whose manifest is missing the key, whose version disagrees with package.json, or where web_accessible_resources survived. Any of those would ship a broken channel, not just a broken build.
  4. Smoke the artifact itself, not dist/: unzip into a fresh folder, chrome://extensions → Developer mode → Load unpacked. Confirm the ID reads fcdigoihpflbghifhmpecihhfjkhabji, Settings → About shows the new version, and the service-worker console is clean. Remove this throwaway install when done.
  5. Commit, tag v<version>, and push the tag. The release workflow (.github/workflows/release.yml) takes it from there: it re-runs the tests, rebuilds and repackages, refuses a tag that disagrees with package.json, generates SHA-256 checksums, attests build provenance, and publishes the GitHub release with the zip attached. The published notes are the matching CHANGELOG.md entry plus the install and update procedure below, pasted in every time: users read release notes, not docs folders.
  6. Review the published release. If the workflow is unavailable, the manual fallback is the old procedure: create the release by hand with the zip, a SHA256SUMS.txt, the changelog entry, and the update instructions below. The release signing key plays no part in either path and stays off CI.

Users: installing

  1. Download kivuli-extension-v<version>.zip from the GitHub release.
  2. Unzip it into a folder you will keep (e.g. ~/kivuli-extension), not Downloads. Chrome loads the extension from this folder: if it is later deleted, moved, or cleaned up, the extension stops loading.
  3. chrome://extensions → enable Developer modeLoad unpacked → select the folder (the one containing manifest.json).
  4. Sanity check: the card shows Kivuli with ID fcdigoihpflbghifhmpecihhfjkhabji.
  5. Optional but recommended: verify the download before unzipping. Compare sha256sum kivuli-extension-v<version>.zip against the SHA256SUMS.txt attached to the release, and check GitHub's build provenance with gh attestation verify kivuli-extension-v<version>.zip --repo kivuliapp/extension.

Users: updating. Read this before touching anything

Unpacked installs never auto-update. No release, however critical, reaches you until you re-download. Watch the repo (GitHub → Watch → Custom → Releases) so security fixes are not missed.

To update:

  1. Download the new zip.
  2. Delete the contents of your existing extension folder, not the folder itself, and unzip the new version into that same folder.
  3. chrome://extensions → Kivuli card → Reload (circular arrow).
  4. Settings → About should now show the new version. If it shows the old one, the reload picked up stale files. Check you unzipped into the right folder.

Never update by loading a new folder, and never click Remove. Your wallet vault lives in the extension's browser storage, which survives overwrite-in-place + Reload but is deleted the moment the extension is removed. Loading the new version from a different folder either collides with the existing install (same pinned ID) or tempts you to remove the old one, and removing it wipes the vault.

If the wallet "disappears" after a bad update

The money is not gone. Everything (the meta-address, every per-site wallet, every receive address) derives from your 12 words. If an update goes wrong (vault wiped by a remove/re-add, popup won't open, wallet shows as fresh):

  1. Get a clean install working in the same folder (re-download the zip, overwrite, Reload, or if the extension was removed, Load unpacked again).
  2. On the welcome screen choose the restore path and enter your 12 words, then set a new passcode.
  3. Let the first scan finish: received payments are re-discovered from the chain via the seed-derived addresses.

This is also why the backup ceremony refuses to activate a wallet until the words are verified: on this channel, the phrase is not a nice-to-have. It is the recovery path for an update gone wrong.