SGKEMBEDDED PERFORMANCEEpicTunerSDK · PrereleaseContact ↗
EpicTuner SDK/ Frozen .etplugin package contract v1

Download the complete Markdown manual ↓
One file with guides, API headers and examples for developers and coding agents.

Frozen .etplugin package contract v1

M0 froze naming, metadata, encoding, limits and test vectors. M5 implements native archive verification, per-user signed installation, rollback and entitlement enforcement. A structurally valid manifest or test signature does not authorize loading; a trusted publisher public key is required.

.etplugin is a ZIP archive with UTF-8 names, stored/deflated regular files only. Reject encryption, symlinks/hardlinks/special files, duplicate or case-colliding paths, directory traversal, absolute paths, backslashes, drive/stream separators, Windows device names and trailing spaces/dots. Directory entries are optional and carry no payload; directories are otherwise implicit. ZIP64 is unnecessary and rejected in v1. Limits: 128 MiB archive, 256 MiB total expanded, 64 MiB per file, 4096 payload files, 240 ASCII bytes per portable path, maximum 8 components, and 100:1 maximum per-file expansion ratio. Enforce bounds while streaming, not after unbounded allocation or extraction. Manifest/signature JSON are each <=64 KiB.

plugin.json
signature.json
payload/windows-x64/plugin.dll
payload/linux-x64/plugin.so
payload/linux-arm64/plugin.so
assets/...
licenses/...

package-manifest.schema.json requires stable plugin/publisher/key IDs, display name and description, strict three-component version, HTTPS help/support/home URLs, host minimum/inclusive and maximum/exclusive range, ABI range, required/optional feature lists, capabilities, per-target entries, panel/service declarations, settings schema, complete file inventory and dependency/license inventory. Product/ entitlement metadata is optional and separate from package authenticity. Each target has exactly one declared entry. Executable dependencies must be individually inventoried under their target payload directory. Every other payload is an asset or license; extra/unlisted payloads are rejected. Every file lists SHA-256, exact expanded byte length, role and platform. No self-referential inventory of plugin.json or signature.json is allowed. Dependency and panel namespaces must agree with declarations; runtime panel registrations must agree with the manifest.

Manifest schema version and ABI/service/wire versions are independent. Unknown manifest keys are rejected. Unknown optional features may be ignored; unknown required features or capabilities are not granted. Native libraries match the selected platform (including ABI architecture), not merely their filename suffix.

Signing bytes

The detached signature uses Ed25519 as specified by RFC 8032. Validate the complete manifest schema before canonicalization. The JSON subset forbids duplicate keys, invalid Unicode and floating-point numbers; numeric metadata uses safe-range integers. Canonical bytes follow RFC 8785, with no whitespace, sorted object keys, unchanged Unicode string values and UTF-8 encoding. All schema object keys are ASCII, making the integer-only subset simple to test without introducing a separate number-formatting implementation.

Sign these exact bytes (the prefix ends in one LF):

UTF8("EpicTunerPluginManifest/v1\n") || canonical_manifest_bytes

signature.json has schema=1, algorithm="Ed25519", publisher key ID, SHA-256 of the canonical manifest, and the detached 64-byte signature encoded as unpadded base64url (86 characters). Reject noncanonical encoding. The signature binds the full manifest and therefore every declared payload hash/length, target, capability and product. The issuer's private key never enters the SDK, host package, logs or activation responses. Test keys are separate from trusted publisher roots.

The native verifier uses OpenSSL Ed25519 and rechecks every payload hash before each installed worker start. Import publisher public keys explicitly in the Plugins window; its per-user plugin-trust.json has no built-in roots. A revoked: true key blocks both new installs and installed version starts. Rotate by importing a new key ID and signing an updated package; publisher ID must remain stable across updates. Test keys in the private repository are excluded from the SDK and normal app bundle. The runtime never treats a valid test-vector signature as an implicit trust grant.

The publisher tool is tools/package.py in the exported SDK. It reads a full v1 manifest, computes the inventory from a bounded payload tree, validates the schema, signs the domain-separated manifest, and creates .etplugin. It requires Python cryptography and jsonschema at publishing time; consumers need neither Python nor those packages. Keep the private PEM outside the SDK, package, source tree and support logs.

The manager stages a new version in a sibling directory, verifies it again, renames it into an immutable version path, drains the prior worker, then atomically saves the active-version registry. It preserves the prior version and a separate settings snapshot for rollback. A failed new worker start triggers rollback; manual rollback is also available. New capabilities appear in the review dialog before the install action. Uninstall has an explicit keep/remove settings choice. --safe-mode suppresses installed auto-start.