Protected Component Delivery and Verification
Every file in pyvorin-native 1.0.9 ships in the wheel and is SHA256 hash-checked at import. The Ed25519 manifest and cache signatures are not yet active in the shipped build — here is exactly what is and is not verified today.
Published Aug 14, 2026
The pyvorin-native wheel ships as one self-contained artefact: 5,098 files listed in its manifest, almost all of them Cython-compiled shared objects for a specific CPython and platform, plus the plain-Python glue between them. Nothing is downloaded afterwards. There is no protected-component downloader anywhere in the package, no delivery URL in any installed binary, and no second stage that fetches "premium" modules on demand. What you install is what runs, and the package verifies itself before it lets anything execute.
This page describes that verification honestly — including the part that is not finished. The shipped 1.0.9 build enforces its SHA256 integrity table and its licence-lease signature, but two Ed25519 signature checks described in the build documentation (the manifest signature and the entitlement-cache signature) are inactive because their verification keys ship empty. We describe both halves, because a verification story you have to exaggerate is not a verification story.
What ships, and how
The manifest enumerates 5,098 files, each with its hash. The bulk of the package is .so extensions compiled for cpython-312 on linux x86_64, with some plain .py files alongside. The package metadata declares the MIT licence, and the runtime dependencies are pydantic, llvmlite, numpy, msgpack and pynacl — the last of which does the Ed25519 signature work for licence leases.
Provenance is anchored at build time, not at install time. The manifest records a build watermark — an identifier baked through the compiled modules and the generated hash table alike, so the integrity data cannot be swapped in from a different build without the mismatch showing. Verification confirmed the watermark in _integrity_data.py matches the one in the manifest; the installed files were additionally checked against the wheel's own hashes. What the manifest cannot tell you — because its signature field is empty — is that this manifest is the one the build produced. Hold that thought; it is the subject of the next sections.
The delivery model matters for security as much as for convenience. Because every compiled module arrives inside the one wheel, the supply-chain surface is a single artefact installed by your normal package manager, over your normal TLS, from your normal index. There is no secondary download channel to secure, no per-component fetch to intercept, and no runtime decision about which server to trust. The server platform does expose artefact-download endpoints for signed compiled components, but those serve other clients — the native package never calls them, and a full URL sweep of every installed binary confirms the only hosts present in the code are api.pyvorin.com, app.pyvorin.com and localhost.
The integrity check that runs: SHA256 against a baked-in table
Every process that imports pyvorin runs pyvorin._integrity.verify() once, from pyvorin.licensing.core, before any gated work happens. The check SHA256-hashes every compiled .so in the package against EXPECTED_HASHES — a table baked into a generated file, _integrity_data.py, which carries the same build watermark and generation timestamp as the rest of the 1.0.9 build. The whole pass takes about five milliseconds.
A mismatch does not produce a warning you can scroll past. It raises a RuntimeError naming tampering, and the import fails closed. The only bypass is PYVORIN_DEV_MODE=1, an escape hatch intended for working on the source tree; if you find it set in a production environment, that finding is the incident. This check is the package's answer to corrupted installs and to casual tampering: any .so modified after installation — by disk corruption, a clumsy "optimisation", or a low-effort attacker — is caught at the next process start, before it executes.
Understand the threat model precisely, because it has an edge. The hash table is itself a plain-text file inside site-packages, so the check detects modification of the binaries by anyone who did not also think to update the table. Against accidental corruption and unsophisticated tampering it is complete. Against an attacker with write access to the install tree who edits both a .so and its listed hash, it is not — that gap is exactly what the manifest signature was designed to close, which brings us to the honest half of this page.
The signatures that do not run yet
The build system's signing layer defines three Ed25519 verification keys, embedded at build time:
| Key | Purpose | Status in shipped 1.0.9 |
|---|---|---|
MANIFEST_PUBLIC_KEY | Verify the Ed25519 signature over MANIFEST.json, which would anchor the whole hash table | Empty — verification skipped |
CACHE_VERIFY_KEY | Verify the signature on the entitlement cache | Empty — verification skipped |
LEASE_VERIFY_KEY | Verify server-signed licence leases | Set and enforced |
In the installed 1.0.9 build, MANIFEST.json carries empty signature and public_key fields, and the generated _signing_keys.py has empty strings for both the manifest and cache keys. The verification code returns early when no key is embedded, so both Ed25519 paths are skipped in production. You can confirm this on any installed copy in seconds:
python -c "import pyvorin._signing_keys as k; print(repr(k.MANIFEST_PUBLIC_KEY), repr(k.CACHE_VERIFY_KEY))"
Two empty strings. That is the whole story, and it is checkable by the reader, which is precisely why we are comfortable printing it.
The practical consequences, stated without inflation. What is verified today: every compiled module against the hash table at every process start, and every licence lease against the embedded Ed25519 key, with the signing secret existing only on the entitlement server so leases cannot be forged locally. What is not verified today: that the manifest and the hash table themselves are the ones the build produced. A defender with write access to site-packages who modifies both a .so and its hash entry would pass the import check — until the lease layer, telemetry or a server revalidation surfaces something inconsistent, none of which is guaranteed or timely. If your threat model includes a sophisticated actor who can write to your Python environment, the honest position in August 2026 is that pyvorin-native's self-verification alone does not cover that actor, and you should protect the install tree with the same file-integrity monitoring you would apply to any security-sensitive deployment.
Why ship it this way at all? Because the engineering order was defensible: the checks that protect revenue and correctness (hashes, leases) were built first, and the manifest signature that hardens the table itself was scaffolded but not yet wired to a key-distribution mechanism. Publishing the gap is not an act of contrition; it is the point. A customer who discovers this from a blog post will reasonably ask what else we did not mention. The same customer reading it here, with the reproducing one-liner, can price the gap into their own controls and verify the fix when a future build ships real keys.
The licence file: the strongest protected component
Ironically, the most fiercely protected object in the package is not code at all — it is ~/.pyvorin/license.json. The file sits at mode 0600 and carries three independent layers: an HMAC-SHA256 over its contents using a build-time secret; binding to the device fingerprint derived from hostname, user and machine ID; and the server's Ed25519-signed lease, verified with the one key that is embedded. The signed lease's tier and feature claims override anything in the local JSON, so editing the file edits nothing that matters. Around it sit a monotonic anti-rollback watermark with five minutes of clock tolerance, an 800-day cap on lease validity, and entitlement-hours accounting with a backup file and anti-replay nonce. Tampering with the package is one threat; tampering with the licence is the one the implementation visibly cares most about, because it is the one its business model cannot shrug off.
The verification inventory
Pulling the page together, here is every protection active in the shipped 1.0.9 build, when it runs, and what it defends against:
| Check | When | Cost | Defends against |
|---|---|---|---|
SHA256 of every .so vs _integrity_data.py | Every process, at import | ~5 ms | Corruption; tampering that misses the hash table |
HMAC-SHA256 over license.json | Licence reads | Negligible | Casual edits to the licence file |
Ed25519 lease signature (LEASE_VERIFY_KEY) | Licence validation | Negligible | Forged or edited entitlements — the signed claims override local edits |
| Anti-rollback watermark, 800-day lease cap, hours counter with nonce | Licence validation | Negligible | Lease replay, lease extension, entitlement rewinding |
| Manifest Ed25519 signature | — | — | Inactive in 1.0.9 (key ships empty) |
| Entitlement-cache Ed25519 signature | — | — | Inactive in 1.0.9 (key ships empty) |
The pattern in the table is deliberate and worth naming: the protections that guard correctness and entitlement revenue are active, enforced and runtime-verified; the protection that would guard the supply chain against a sophisticated on-host actor is scaffolded but not yet keyed. Knowing which row of that table a given threat lands in is the entire point of publishing it.
What to do with this information
If you are evaluating Pyvorin for a security review, three concrete recommendations, in order of effort. First, pin and hash the wheel itself at install time — the supply-chain guarantee for a single-artifact package is strongest at the artefact boundary, and your package manager or an SBOM tool can do this today. Second, monitor the install tree with your existing file-integrity tooling; the package's own check already covers the "someone changed a .so" case, and monitoring the table alongside it closes the gap described above. Third, when a future release ships a non-empty MANIFEST_PUBLIC_KEY, re-run the one-liner from this page and update this assessment — the moment the keys are real, the manifest path upgrades from documentation to control without any code you own changing.
Where to go next
- How local compilation works — the local compile path and the complete outbound network surface.
- Activation and entitlement — the lease, the gate, and offline grace in detail.
- Compiler pipeline overview — what the verified binaries actually do with your code.
- CLI reference — the tooling surface you are protecting.
Last reviewed 3 August 2026 against pyvorin-native 1.0.9 installed at /root/pvfinal: 5,098 manifest files, _integrity_data.py 194 lines with matching build watermark, _signing_keys.py read directly from the installed package. Key statuses quoted above are from that file, not from documentation.