From b32e5b39d13469aea38165740d5f45869310a34d Mon Sep 17 00:00:00 2001 From: Ravenyjh Date: Wed, 14 Oct 2026 21:24:38 +0800 Subject: [PATCH] docs(router): explain why tee_verified is absent on Private models Requests to Private (TeeML) models are sealed by the 0G gateway before they reach the Router, so the Router never sets tee_verified on them, even with verify_tee: true. The page read this as "verification was not requested", which led a heavy user to report it as a bug. The check actually runs in the gateway: a failed signature blocks a non-streaming response, and ends a stream with an error event. Document that, the X-0G-E2EE / X-Provider / ZG-Res-Key headers, and the limit of independent verification for sealed responses (the provider signs hashes of the encrypted exchange). Also stop claiming every provider runs in a TEE, and fix the privacy page's Auditing bullet that pointed Private-model users at verify_tee. Co-Authored-By: Claude Opus 5.5 --- .../router/features/verifiable-execution.md | 25 +++++++++++++++++-- .../compute-network/router/privacy.md | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/docs/developer-hub/building-on-0g/compute-network/router/features/verifiable-execution.md b/docs/developer-hub/building-on-0g/compute-network/router/features/verifiable-execution.md index eba1abb6..139d1fde 100644 --- a/docs/developer-hub/building-on-0g/compute-network/router/features/verifiable-execution.md +++ b/docs/developer-hub/building-on-0g/compute-network/router/features/verifiable-execution.md @@ -11,7 +11,9 @@ import TabItem from '@theme/TabItem'; # Verifiable Execution -Every 0G Compute provider runs inside a **Trusted Execution Environment (TEE)** and cryptographically signs its responses. The Router can verify that signature synchronously on your behalf and report the result back in the response metadata. +Providers on the `verified` and `private` [trust tiers](../routing#trust-modes) run inside a **Trusted Execution Environment (TEE)** and cryptographically sign their responses. The Router can verify that signature synchronously on your behalf and report the result back in the response metadata. + +For **Private models** (TeeML, such as `glm-5.3`), the request is encrypted before it reaches the Router, so the Router cannot check the signature and the check happens one step earlier. See [Private models](#private-models). ## Opt in with `verify_tee` @@ -65,7 +67,26 @@ When `verify_tee` is set, the Router adds a `tee_verified` field to the response | --- | --- | | `true` | The provider's TEE signature was validated successfully | | `false` | A signature was present but did not verify — treat the response as untrusted | -| `null` / absent | Verification was not requested for this response | +| absent | No verdict from the Router: verification was not requested, the response came from a Private model (see [Private models](#private-models)), or the provider is on the `standard` tier and signs nothing | + +## Private models + +Requests to Private models (TeeML providers, such as `glm-5.3`) on `router-api.0g.ai` are encrypted to the provider's enclave by the 0G gateway in front of the Router. The Router forwards ciphertext it cannot read, so it does not set `tee_verified` on these responses, **even with `verify_tee: true`**. This is expected, not a failed check. + +The signature check runs in the gateway instead, on every request, whether or not you set `verify_tee`. The gateway runs inside a TEE and checks each response's signature against the TEE signer the provider registered on-chain: + +- **Non-streaming:** a response whose signature does not verify is never delivered; you get an error instead. +- **Streaming:** the signature covers the whole response, so it can only be checked after the last chunk has been sent. If it fails, the stream ends with an error event (for chat completions, in place of `data: [DONE]`). Treat a streamed answer as verified only once the stream has finished normally. + +These response headers tell you what happened: + +| Header | Meaning | +| --- | --- | +| `X-0G-E2EE: sealed` | The request was encrypted to the provider's enclave and the response decrypted from it. `none` means the request went through unencrypted. | +| `X-Provider` | The provider the request was encrypted to. | +| `ZG-Res-Key` | The handle to fetch this response's signature from the provider (step 2 under [Without the SDK](#without-the-sdk)). | + +You can fetch the signature with `ZG-Res-Key` and confirm it recovers to the provider's on-chain TEE signer (steps 1 to 3 below). Step 4 does not apply: for a Private model the provider signs hashes of the *encrypted* request and response, which only the gateway sees. ## When to use it diff --git a/docs/developer-hub/building-on-0g/compute-network/router/privacy.md b/docs/developer-hub/building-on-0g/compute-network/router/privacy.md index 5739cbf6..80819e0c 100644 --- a/docs/developer-hub/building-on-0g/compute-network/router/privacy.md +++ b/docs/developer-hub/building-on-0g/compute-network/router/privacy.md @@ -101,5 +101,5 @@ The catalog changes as providers join the network; per-provider tiers are shown ## Auditing - Account usage endpoints break down consumption by trust tier, so you can report exactly which share of traffic ran sealed, per day and per model. -- Add `verify_tee: true` to any request to have the Router verify the provider's TEE signature synchronously; see [Verifiable Execution](./features/verifiable-execution.md). +- Responses from Private models are signature-checked by the 0G gateway before they reach you, and carry `X-0G-E2EE: sealed`. The Router's `tee_verified` field is not set on them, even with `verify_tee: true`; see [Verifiable Execution: Private models](./features/verifiable-execution.md#private-models). - Provider attestations can be independently verified with [dstack-verifier](https://github.com/Dstack-TEE/dstack), and the verification mechanics are documented under [verification modes](../inference.md#verification-modes).