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
sqlite3is 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:
| OS | State 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 binary | state.db (writable) | |
|---|---|---|
| Vendor public key | ✓ as a constant + pinned fingerprint | never |
| Private key | never (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.dbdeleted → protection intact via fallback marks- License issued for another machine → rejected
hwid_mismatch