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.0.tar.gz (22.9 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.0-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: halieum-0.1.0.tar.gz
  • Upload date:
  • Size: 22.9 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.0.tar.gz
Algorithm Hash digest
SHA256 c3aae907fe5c7ce416346105a5e43ee2d9976bbef220b9bf0b5fa1eb41e6d010
MD5 4fb35d35469cdfe26fd5f44639419db6
BLAKE2b-256 e1b6d29a41ed8c519eabc3e102d76b45af1fabdb2ed9670443c9c2c07bf5df93

See more details on using hashes here.

Provenance

The following attestation bundles were made for halieum-0.1.0.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.0-py3-none-any.whl.

File metadata

  • Download URL: halieum-0.1.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7da8bf3d40449fd4ea459220c44a04044e961826790275c3c96afc740376b888
MD5 b040ddc896e4302907ca45f0a44483f8
BLAKE2b-256 4627f5d6829046f38ac998e42488db4fa0be148644139047e0a7859332400e94

See more details on using hashes here.

Provenance

The following attestation bundles were made for halieum-0.1.0-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

0.1.1

2 files

This release

0.1.0 This release

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