scalio-license
Shared license check for the Scalio apps (Nexus, Citadel, Foundry, Rosetta; Compass later). Offline only: Ed25519 signatures against public keys embedded in each app, no call home, no GitHub. Concept and decisions L1-L9: https://claude.ai/artifact/UGD8mKguzvivMMJbKW1qEx
Nothing in this package is secret. The private seeds stay in 1Password and in the Compass License Managers.
How it works
- Key:
<payload_b64>.<sig_b64>, Ed25519 over the payload bytes (same format as Compass issues). Every key carriesproduct_code(scalio-citadel, ...). An app accepts only its own code. - Own key per product, embedded in the app (
TrustedKey). No environment override. Without an embedded key nothing is enforced, so the code can ship before the key exists. - Staging keys: Compass dev/test sign with their own key, embedded with
plans=("nfr",). Such a key only issues base licenses of those plans and no add-ons, so a leaked staging seed never yields a sellable license. - Binding: self-hosted keys carry
installation= the installation ID the app shows on its license page (random, created on first start, stored indb.meta). SaaS keys carrydomains. A mismatch means Community plus an error. Compass lets a customer generate the key once; moving needs Scalio. - Purchase plus maintenance:
expis the end of maintenance. A build released afterexp+ 30 days makes the configuration read-only (423). Features and data stay. Trials (type: trial) end hard. - Limits only on create (402), existing data is never locked or deleted. Features off: 402.
- SaaS (
SAAS_MODE=true): the license page is read-only, Compass pushes the key throughPOST /api/provision/licensesigned with its control key K3 (PROVISION_PUBLIC_KEY).
Use in an app
from scalio_license import Addon, Edition, GateMiddleware, LicenseRuntime, Product, RequestGate, TrustedKey
from scalio_license.web import license_router, provision_license_router
PRODUCT = Product(
code="scalio-citadel", name="Scalio Citadel", lang="en",
trusted_keys=(), # TrustedKey("cit2026a", "<public key>") once Markus made the key
editions={"community": Edition("Community", frozenset(), {"tenants": 1, "admins": 1}),
"pro": Edition("Pro", frozenset({"self_healing"}), {"tenants": 25, "admins": 5}), ...},
limit_kinds=("tenants", "admins"), features=("self_healing", ...),
claim_map={"maxAdmins": "admins", "maxEmployees": "tenants"})
runtime = LicenseRuntime(PRODUCT, usage={"tenants": count_tenants, "admins": count_admins},
public_url=get_public_url)
app.include_router(license_router(runtime, lambda: db, require_admin), prefix="/api")
app.include_router(provision_license_router(runtime, lambda: db), prefix="/api")
app.add_middleware(GateMiddleware, gate=RequestGate(runtime, feature_rules=[...], config_writes=[...],
exempt=[r"^/api/license", r"^/api/provision", r"^/api/auth"]))
# startup: await runtime.refresh(db); asyncio.create_task(runtime.refresh_loop(db))
# on create: await runtime.assert_can_add(db, "tenants")
Env per app (prefix from the product code): <APP>_LICENSE_KEY, <APP>_LICENSE_ADDONS (only used while
nothing is stored in the database), APP_BUILD_DATE or BUILD_DATE (set in the image), APP_PUBLIC_URL, SAAS_MODE,
PROVISION_PUBLIC_KEY.
Vendor tool
tools/scalio_license_tool.py is not part of the package. It makes key pairs and signs Scalio's own
licenses (vendor, NFR) before a Compass License Manager exists.
python tools/scalio_license_tool.py genkey --out ~/citadel-seed.txt --kid cit2026a
python tools/scalio_license_tool.py base --seed-file ~/citadel-seed.txt --product scalio-citadel \
--plan nfr --customer "Scalio Dev" --domains dev.scaliocitadel.com --days 365
Development
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest && .venv/bin/ruff check .
tests/vector.json is a fixed key signed like Compass signs. Compass tests the same vector, so both stay in step.
Release
Bump version in pyproject.toml and __init__.py, add a CHANGELOG section, merge, then "Freigeben" in the
Scalio Dev cockpit (or Actions -> Publish -> Run workflow on main with the version, or push a tag without v
like 0.1.0). publish.yml tests, builds and publishes to PyPI with trusted publishing (no token); when started
from the cockpit it also creates the tag and GitHub release. Apps pin the exact version and upgrade in their own PRs.
Metadata
Release files for scalio-license 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| scalio_license-0.2.0.tar.gz | 23.1 kB | With provenance | Details for scalio_license-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| scalio_license-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for scalio_license-0.2.0-py3-none-any.whl |
Total release size: 42.9 kB
Release files / scalio_license-0.2.0.tar.gz
| Download URL | scalio_license-0.2.0.tar.gz |
|---|---|
| Size | 23.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
483e1af81673f64b217bcd38c985cbc0e99a78e51b0d2502bd53d74f4e08d50c
|
|
BLAKE2b-256 checksum How to use checksums |
24221bc516a16e5340ee587bc68c4a36b75eeb6d4ab1d35113fcefba40b821dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / scalio_license-0.2.0-py3-none-any.whl
| Download URL | scalio_license-0.2.0-py3-none-any.whl |
|---|---|
| Size | 19.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c7b807b91b55857233971cb741fa6666f891103c493b20257e435f3912ce2825
|
|
BLAKE2b-256 checksum How to use checksums |
e136b0e396e4548326d90ebbfd6412e51b8e900aab177cbd46072b45c63eea18
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logSecurity for scalio-license 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for scalio_license-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.