Skip to main content

halieum

A minimal, dependency-free license guard for personal Python projects.

import halieum
halieum.init("your-license-id")

import halieum does nothing on its own — no network, no file I/O, no output, no monkey-patching. It cannot affect the surrounding code. All logic runs inside init().

When the license for id is confirmed invalid (a validly-signed license whose expiry has passed, or one that was tampered with / forged), halieum enforces from the project root. When the license server is merely unreachable, it never deletes anything: it falls back to a local cache, and on a first-ever run with no cache it simply exits the host program.

halieum is a deterrent for the author's own projects. Anyone who can edit the source can delete the two lines above; treat it as a speed bump, not a vault.


How it works

init(id)
  -> GET  <PAGES_BASE>/licenses/<id>.json           (GitHub Pages)
  -> verify RSA (PKCS#1 v1.5 + SHA-256) with the embedded PUBLIC key
  -> compare exp against the local UTC clock
       valid & current        -> cache to temp dir, return silently
       expired / tampered     -> ENFORCE (delete) then exit
  -> if the network failed:
       cache present & valid   -> return silently
       cache present & expired -> ENFORCE (delete) then exit
       no cache (first run)    -> exit host program (never delete)

The signature is asymmetric on purpose: the public key ships inside the package (safe to be public on PyPI — it can only verify), while the private key stays in a GitHub Actions secret and signs each license.


Install

pip install halieum

Runtime requires the standard library only and targets Python 3.6+.


init() API

halieum.init(
    id,                 # REQUIRED. License identifier issued by the Action.
    dry_run=False,      # Only determine validity; never delete, never exit.
    debug=False,        # Log to sys.stderr (never print). Default: silent.
    mode="recursive",   # "recursive" | "source" | "self" | "file"
    target=None,        # Dir/file to enforce on. Default: project root.
    root=None,          # Override project-root auto-detection.
    extensions=None,    # Custom extension filter (implies source filtering).
    timeout=None,       # Network timeout in seconds (default 5.0).
    exit_after=True,    # After a destructive enforcement, exit the process.
)

Modes

mode effect
recursive (default) Delete every file under target (default: project root), then remove emptied directories. .git/.hg/.svn are preserved.
source Like recursive, but only files whose extension is in extensions (default: common source extensions).
self Delete only the single file that called init().
file Delete only the single resolved target file.

Project root is the entry-script directory (__main__.__file__, else sys.argv[0]), falling back to the current working directory. So calling init() from a sub-module still resolves to the project root — never the sub-module folder and never the installed package folder.

Examples

# Check only, change nothing, print diagnostics:
halieum.init("my-id", dry_run=True, debug=True)

# On failure, delete only the ./src tree:
halieum.init("my-id", target="src")

# On failure, delete only source files, keep data/assets:
halieum.init("my-id", mode="source")

# On failure, delete only the file that calls init():
halieum.init("my-id", mode="self")

Output never uses print (which a host app can hijack); diagnostics go straight to sys.stderr and are silent unless debug=True.


Setting up your own license server (one time)

The signing key, the issuing Action and the Pages distribution all live in this repository.

1. Generate the RSA keypair

pip install pycryptodome
python tools/gen_keys.py

This rewrites src/halieum/_keys.py with your public key and prints the private key (PEM) to stdout.

2. Store the private key as a secret

Repo → Settings → Secrets and variables → Actions → New repository secret:

  • Name: HALIEUM_SIGNING_KEY
  • Value: the PEM private key printed above

Until a real public key is generated, _keys.py ships a placeholder (n = 0) and halieum stays inert (it reports "unconfigured" and never enforces).

3. Enable GitHub Pages

Repo → Settings → Pages → Source: GitHub Actions.

Set your Pages base URL in src/halieum/_config.py:

DEFAULT_BASE = "https://<your-username>.github.io/<repo>/"

Licenses are then served at <DEFAULT_BASE>licenses/<id>.json.

4. Issue a license

Repo → Actions → Issue License → Run workflow, and provide:

  • id — the license identifier (the same string passed to init()).
  • datetime — expiry, ISO-8601 UTC, e.g. 2026-12-31T23:59:59Z.

The workflow signs the license, writes licenses/<id>.json, commits it back as the source of truth, and deploys all licenses to Pages. Re-running with the same id updates its datetime and re-signs.


Safety guarantees

halieum is deliberately biased toward not deleting:

  • A network failure alone never deletes. It uses the cache, or (first run) exits the host program.
  • Deletion happens only for a provably invalid license: a correctly signed license past its expiry, or one whose signature/id does not verify.
  • The enforcement target is screened against a deny-list of filesystem roots, critical OS directories, the running interpreter, site-packages and halieum's own package directory. A target outside the project root is refused.
  • .git/.hg/.svn are preserved; each file removal is individually guarded (locked files on Windows are skipped, not fatal).
  • Any internal halieum error results in a no-op, never a deletion.
  • dry_run=True disables every destructive action and every exit.
  • import halieum is inert; nothing runs until init() is called, and the same id is only ever processed once per process.

Development

pip install -e ".[dev]"      # editable install + pytest/build/twine
pytest -q                    # run the suite (stdlib only; no crypto needed)
python -m build              # sdist + wheel
twine check dist/*

The test-suite signs with a throwaway RSA key embedded in tests/conftest.py using pure Python, so it needs no third-party crypto. CI (.github/workflows/ci.yml) runs the matrix across Python 3.8–3.14 on Ubuntu and Windows.

Publishing to PyPI

python -m build
twine upload dist/*

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

halieum-0.1.1.tar.gz (23.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

halieum-0.1.1-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

Details for the file halieum-0.1.1.tar.gz.

File metadata

  • Download URL: halieum-0.1.1.tar.gz
  • Upload date:
  • Size: 23.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for halieum-0.1.1.tar.gz
Algorithm Hash digest
SHA256 0e7ee549b29a13d3c81615905e7d3f24e1e5e629e14c220b4da1d29fb4a65ca1
MD5 90bddd66853f410d0a3ab6178f92398a
BLAKE2b-256 aa8b22a2f73b9b152a4ad0c9924862e0d05d54e8ba6e429620a939ddf360545f

See more details on using hashes here.

Provenance

The following attestation bundles were made for halieum-0.1.1.tar.gz:

Publisher: python-publish.yml on Randark-JMT/halieum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file halieum-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: halieum-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 18.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for halieum-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 27fba8aa9fbc8b00e682097fd9d66d41665130d0134926c6112804632b16e610
MD5 c1c57f4d6439b5e43750e6c4fe749943
BLAKE2b-256 7449e6e6b39ffc494e1bec615c37389ab04c7cc57cca59d26487f90cc2787f93

See more details on using hashes here.

Provenance

The following attestation bundles were made for halieum-0.1.1-py3-none-any.whl:

Publisher: python-publish.yml on Randark-JMT/halieum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page