Packaging & compiled apps

py-rizmi works unchanged in packaged apps. Here's what matters.

PyInstaller

pyinstaller --onefile main.py
# plain import works; no hidden-import needed for py_rizmi core
  • sqlite3 is stdlib — no extra data files to declare.
  • Compiling with a native-code compiler keeps your embedded public key and fingerprint constants in machine code; patching them means rebuilding the binary — a far higher bar than editing an archive.

The one rule that makes it work

Never derive state paths from __file__. Onefile packagers extract to temp dirs wiped at exit (PyInstaller's __file__ points inside _MEIPASS). py-rizmi already handles this: writable state always resolves to the platformdirs user-data location:

OSState DB location
Linux~/.local/share/<AppName>/state.db
macOS~/Library/Application Support/<AppName>/state.db
Windows%LOCALAPPDATA%\<AppName>\state.db

What lives where

Compiled into the binarystate.db (writable)
Vendor public key✓ as a constant + pinned fingerprintnever
Private keynever (your issuing machine only)never
Licenses / trial keys / clock marks—HMAC-verified rows + fallback file

Release checklist

  • rizmi doctor run -a MyApp -P pub.pem --fingerprint <hex> passes on a clean VM
  • First run starts a trial; second run continues it (not restarted)
  • System clock rolled back → blocked with clock_tampering
  • state.db deleted → protection intact via fallback marks
  • License issued for another machine → rejected hwid_mismatch