Developer guide · Zikaron

Releasing

A release has to be checkable byte for byte by anyone: its checksums, its signature, and the match between the source archive and the tag. These are the steps a maintainer follows.

Version numbers

Three parts, major.minor.patch. Every version’s changes go into the change log: what was added, changed and fixed, changes to file formats and command-line output, and what users have to do when upgrading. Ledger mirrors, the command line’s ledger folders and record kits are read by a new version as usual; local encrypted files, the machine folder and data folders are read in the version’s own form, and when that form changes, the change log, the release notes and the manual’s “Upgrading from an earlier version” say how data comes across by hand. The law’s version is written in its spec name and is independent of the software version.

Before a release

  • Every test passes on main: continuous integration builds and tests release builds on macOS, Linux and Windows, the macOS and Linux cells also building the way a release does and checking that the binaries carry neutral path names alone; each platform’s packages are then installed and opened once on a real machine.
  • Both digests of the law recompute to their values.
  • The cores show zero divergences against the frozen cores, and every chain-facing recording replays identically.
  • The contract’s code hash recomputes correctly.
  • The Chinese and English manuals match the interface sentence for sentence.
  • The six first-launch steps are walked through on a clean machine.
  • Install over the previous version on a machine with data; the machine folder and data folders are used as they are, and the ledger check answers “OK”.
  • A ledger mirror exported by 0.1.2 is brought across by the manual’s “Upgrading from an earlier version”, and the ledger check answers “OK”.
  • A whole-machine backup exported on one system is restored once on each of the others.

Build

Release files are built from the tagged commit, each system with its own tool:

git tag v0.1.5
macOS
packaging/macos/build.sh --identity Kaptonia
The script first builds zikaron-pack, which gives the compiler flags for the path mappings (zikaron-pack rustflags), then builds the app and the command line with --locked and checks with zikaron-pack no-paths that the binaries carry neutral path names alone, stopping before packaging if anything is left; it then puts the window program zikaron-desk, the command line zikaron and the third-party licences into ZIKARON.app, signs and verifies each one, then makes dist/ZIKARON-<version>-macos-<arch>.dmg (with a link to Applications) and a .pkg (the app into /Applications, the command line into /usr/local/bin), and writes SHA256SUMS-macos-<arch>.txt. Extended attributes are stripped, and the owners, dates and partition names in the dmg and the owners and dates in the pkg are made neutral.
Linux
packaging/linux/build.sh
Builds on Linux itself, with the same path mappings and path check as on macOS; on another host, use cross-build.sh, targeting glibc 2.31. build.sh makes the .deb with dpkg-deb, and cross-build.sh writes it with packaging/linux/make_deb.py; the AppImage is the pinned AppImage runtime followed by an image made with mksquashfs, these two alone. The runtime is pinned by its bytes (type2-runtime 8f39b89 for x86_64), and a downloaded one that differs stops the build, when the pinned file is handed to the script as APPIMAGE_RUNTIME; aarch64 still awaits a pinned runtime and gets the .deb alone. The third-party licences go in /usr/share/doc/zikaron-desk/, and the binaries’ .comment section is emptied.
Windows
cargo run --release --locked -p zikaron-pack -- windows --out dist
Built on Windows with MSVC, it lays out the folder dist/ZIKARON-<version>-windows-x86_64/, which is then zipped for the release page.

Binaries are stripped of symbols; the paths of the home directory, the Cargo and rustup directories, the source and the build directory are mapped away at compile time, by one table in zikaron-pack shared by all three systems, and every date in a package comes from SOURCE_DATE_EPOCH (the commit time by default), so the product is independent of the build machine.

Checksums and Zikaron record

  1. Compute the SHA-256 of every release file (each platform’s packages and the source archive) and gather them into one release list, SHA256SUMS.txt; the three platforms’ third-party licences are published separately. The release page carries ten files: six packages, the release list and three licence lists.
  2. Before publishing, record ten records in the project’s Zikaron ledger and anchor them on chain together: the six packages, the two programs in the Windows package, the release list, and the commit; the transaction, block, recorder address and each fingerprint are on the Checksums page.
  3. The release page, the website’s download page and the list agree in all three places; the download page’s “Zikaron record” column carries each file’s anchoring transaction.

How users check them is under Checksums.

System signing

The app and the dmg are signed with the project’s own certificate, whose common name is Kaptonia; the project issues this certificate itself, the release is outside Apple’s notarization, and the project publishes it directly. Every version is signed with the same certificate and the same identifier, com.kaptonia.zikaron.app, so the system recognizes each version as the same app. The pkg is checked by its SHA-256. The Windows zip and the two Linux packages are unsigned and checked by their SHA-256.

Files downloaded in a browser carry a quarantine flag, and macOS refuses to open them; on recent macOS, “Open Anyway” works only some of the time. The way the download page and the release notes give is: check the file with shasum -a 256 first, then remove the quarantine flag in Terminal with xattr. On Windows, the first start takes “More info”, then “Run anyway”; on Windows 11 with Smart App Control on, turn it off first. Users who want to confirm where a file came from can check its signer, certificate fingerprint, checksum and Zikaron record; see Checksums.

Release notes

For every version, state what was added, changed and fixed; changes to file formats and command-line output; what users have to do when upgrading; and known limitations. CHANGELOG.md and CHANGELOG.en.md in the repository record each version, and the release notes link to them and to that version’s manual.

Contract and networks

The app carries a table of four known deployments (Ethereum mainnet, Sepolia testnet, Arbitrum One, OP Mainnet), each with a chain ID, registry contract address, start block and two preset nodes. Before adding a row:

  1. Read the code from the chain and check its code hash.
  2. Confirm that the start block comes before the first anchor on that contract.
  3. Choose two preset nodes from different sources, both with TLS, both answering the right chain ID, each measured to hold the complete logs since the start block, matching entry for entry, and refusing too wide a query range in words; nodes that serve only a recent window, charge, or rate-limit are left out.

Once a row is released, its chain ID, registry contract and start block stay as they are, and old ledgers go on being verified by them. A preset node whose logs become incomplete can be replaced: a data folder copies a row’s nodes when it is made, so a replaced pair reaches data folders made afterwards, and an existing data folder’s nodes are the user’s to change.

The website

With every version the website updates the file names, sizes, checksums and Zikaron records on its download page. The pages are generated by a script in the repository, and the output is committed with it.

After a release

  • Download a copy from the release page, then check, install and open it by the users’ own steps.
  • Confirm that the drop zone on the download page answers “Matches the release list” for every file.
  • When a release file turns out to be wrong, publish a new patch version; published files and checksums stay as they are.