> 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

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 (versions + 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 lists the release version and the expected SHA-256 of every artifact. 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 versions 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="/pages/as3JvHboA5RxokqNHpAw">/pages/as3JvHboA5RxokqNHpAw</a></td></tr><tr><td><strong>Security overview</strong></td><td>The whole posture and the threat model.</td><td><a href="/pages/jLlQKGv5GwnJU5gn4Frl">/pages/jLlQKGv5GwnJU5gn4Frl</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="/pages/VmHkD0an28Ww8yTFnwpS">/pages/VmHkD0an28Ww8yTFnwpS</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="/pages/0eykLEyLKnupmpNlVgH9">/pages/0eykLEyLKnupmpNlVgH9</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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
