> For the complete documentation index, see [llms.txt](https://docs.telys.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.telys.ai/security/trust-anchors.md).

# Trust anchors

The three cryptographic checks Telys runs before activating the native runtime — a signed release manifest, per-artifact SHA-256 hashes, and a strict offline license.

Telys will not run an engine it cannot prove is genuine. Before the native runtime activates, the SDK checks three independent anchors — a **signed release manifest**, **per-artifact hashes**, and an **offline license** — and every one must pass. Each answers a different question, and the chain is ordered: nothing downstream is trusted until the anchor above it is. All three run locally against keys embedded in the wheel; none touches the network.

## Where the anchors live

A verified install lands under `$TELYS_HOME/runtime/<platform>/` (for example `runtime/macos-arm64/`). Each anchor consumes these files:

| File                                         | Consumed by                                                                           |
| -------------------------------------------- | ------------------------------------------------------------------------------------- |
| `telys_manifest.json`                        | Anchor 1 — the release manifest (format version, platform, expected artifact hashes). |
| `telys_manifest.sig`                         | Anchor 1 — RS256 / PKCS#1 v1.5 signature over the manifest bytes.                     |
| `libty_runtime.<ext>`, `libame_kernel.<ext>` | Anchor 2 — the native libraries whose SHA-256 is checked.                             |
| `license.jwt`                                | Anchor 3 — the offline license token.                                                 |

The public keys the SDK trusts ship **inside the wheel**, so verification needs no key server:

* `release_public_key()` → `telys/_keys/telys_release_pub.pem` (verifies the manifest)
* `license_public_key()` → `telys/_keys/telys_license_pub.pem` (verifies the license)

Both require the `cryptography` package, a hard SDK dependency.

## Anchor 1 — the signed release manifest

The manifest carries the format version and platform, plus the expected SHA-256 of every artifact (`{format_version, platform, artifacts: [{name, sha256, size_bytes}]}`). Its signature is checked over the **exact bytes** of `telys_manifest.json`:

```python
from telys.verify import verify_manifest, release_public_key

# RS256 / PKCS#1 v1.5 + SHA-256 over the exact manifest bytes.
# Defaults to the embedded release public key.
manifest = verify_manifest(manifest_bytes, signature)   # -> trusted manifest dict
```

`verify_manifest(manifest_bytes, signature, pubkey=None)` verifies the RSA signature and returns the manifest dict only if it is intact. The signature covers the raw bytes, so re-serializing or editing a single character invalidates it. Once it passes, the artifact names and hashes inside the manifest are trusted — which is what makes Anchor 2 meaningful.

{% hint style="info" %}
The manifest is the root of the chain: the hashes Anchor 2 checks live **inside** this signed manifest. An unsigned or forged manifest would carry worthless hashes, so its signature is verified first.
{% endhint %}

## Anchor 2 — per-artifact SHA-256

For each artifact in the trusted manifest, the SDK recomputes the file's SHA-256 and compares it to the promised value **in constant time**:

```python
from telys.verify import verify_artifact, sha256_file

# Recomputes SHA-256 of the file and compares to the expected hash
# (from the verified manifest) in constant time. Raises on mismatch.
verify_artifact("libty_runtime.dylib", expected_sha256)

# The underlying primitive, if you want the digest itself:
digest = sha256_file("libty_runtime.dylib")   # hex SHA-256 string
```

A swapped, patched, or truncated `libty_runtime` or `libame_kernel` produces a different digest and is rejected. Constant-time comparison prevents probing a mismatch byte-by-byte through timing.

## Anchor 3 — the offline license

The last anchor proves this machine is entitled to run Telys. It is strict and entirely offline:

```python
import datetime
from telys.verify import verify_license

now = int(datetime.datetime.now(datetime.timezone.utc).timestamp())  # verify_license wants a Unix int
claims = verify_license(license_jwt, now=now)   # strict, offline, RS256
print(claims["products"]["telys"])              # tier + features
```

`verify_license(token, pubkey=None, *, now, issuer=None, audience=None, product="telys")` validates `license.jwt` against the embedded license public key and:

* **pins the algorithm to RS256** and rejects any token with a `crit` header;
* checks `iss` (default `https://license.algenta.ai`) and `aud` (default `telys-runtime`, `algenta-runtime`);
* requires `ver == 2` (the `SUPPORTED_LICENSE_VER`);
* checks `exp` against `now` plus a grace window;
* reads the `products.telys` entitlement (tier + features).

The defaults are constants in `telys.verify`:

| Constant                    | Default                            |
| --------------------------- | ---------------------------------- |
| `DEFAULT_LICENSE_ISSUER`    | `https://license.algenta.ai`       |
| `DEFAULT_LICENSE_AUDIENCES` | `telys-runtime`, `algenta-runtime` |
| `SUPPORTED_LICENSE_VER`     | `2`                                |
| `PRODUCT`                   | `telys`                            |

The offline check with a grace window on `exp` means a short outage or travel does not lock you out of a provisioned install. See [**Offline licenses & verification**](/licensing/offline-licenses.md).

## Fail-closed, native-only

The three anchors compose into one rule: an install that does not verify does not run. A verified install is **native-only** — `load_runtime()` loads the signed native runtime and never downgrades a verified install to unverified code; if the runtime cannot import, it raises `RuntimeNotInstalled`. Importing the package activates only a verified install's `pysite/`, and is a silent no-op otherwise.

{% hint style="warning" %}
You can override the anchors via environment — `TELYS_RELEASE_PUBKEY` / `TELYS_RELEASE_PUBKEY_FILE`, `TELYS_LICENSE_PUBKEY` / `TELYS_LICENSE_PUBKEY_FILE`, `TELYS_LICENSE_ISSUER`, and `TELYS_LICENSE_AUDIENCE` — to point at keys of your own, for example a staging release key. In production, leave the embedded PEMs and default constants in place; overriding them means trusting keys you supply.
{% endhint %}

## Next steps

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Verify the runtime signature</strong></td><td>Run the three-anchor chain yourself, step by step.</td><td><a href="/security/runtime-signature-verification.md">Verify the runtime</a></td></tr><tr><td><strong>Security overview</strong></td><td>The whole posture and the threat model.</td><td><a href="/security/overview.md">Overview</a></td></tr><tr><td><strong>The signed runtime &#x26; trust model</strong></td><td>How the anchors fit into loading the engine.</td><td><a href="/understand-telys/signed-runtime-trust.md">Signed runtime &amp; trust</a></td></tr><tr><td><strong>Signature verification failures</strong></td><td>What to do when an anchor does not pass.</td><td><a href="/troubleshooting/signature-verification.md">Signature verification</a></td></tr></tbody></table>

Next: run the chain in [**Verify the runtime signature**](/security/runtime-signature-verification.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.telys.ai/security/trust-anchors.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
