> For the complete documentation index, see [llms.txt](https://docs.trezalabs.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trezalabs.com/getting-started/concepts.md).

# Concepts

The core of Treza is the **pipeline**: a graph of nodes that turns inputs into generated media. Everything else, from the visual editor to the published API, is built around it. Start with the concepts below, then move on to the advanced and enterprise building blocks further down the page.

***

### Pipelines

#### What they are

A pipeline is a directed graph of nodes that you build on the visual canvas. Data flows along the edges from one node to the next: an input becomes a prompt, a prompt becomes a video, a video gets a caption. A pipeline has a **draft** you edit and, once you publish, a versioned **published** snapshot that serves API traffic.

#### Core ideas

* **Draft vs. published.** You edit the draft freely. Publishing takes a snapshot and assigns it a version number. API calls always run the published snapshot, never your in-progress draft.
* **Contract.** Treza derives an input/output contract from your input and output nodes. The input keys you send to the API, and the output keys you get back, come from this contract.
* **Ownership.** Pipelines and API keys are scoped to your account. A key can only invoke pipelines owned by the same account.

#### Typical flow

1. Start from a prompt or a template on the canvas.
2. Wire nodes together and run the pipeline to test it.
3. Publish to get a versioned endpoint.
4. Call the endpoint from your product, scripts, or an agent.

***

### Nodes

#### What they are

Nodes are the building blocks on the canvas. Each node does one job and passes its output to the next. You add them from the palette and connect them by dragging edges.

#### Common node types

* **Input** - the entry point that accepts a value from the editor or an API call.
* **Model / generation** - video, image, language, audio, or embedding models. Pick a model per node.
* **Prompt / transform** - reshape text between steps, for example refining a brief into a shot prompt.
* **Guardrail** - redaction, PII, and conditional-routing nodes that handle sensitive data before it reaches a model or an external system.
* **Output** - the value returned by the pipeline. Output nodes define the response contract.

***

### Models

#### What they are

Every generation node runs a model. Treza reaches models through an OpenAI-compatible backend spanning providers like Together, OpenRouter, Fireworks, and DeepSeek, so you are never tied to one vendor.

#### Core ideas

* **One model per node**, changeable at any time with no rewrites.
* **Any model id.** Pick from the catalog or type any Hugging Face or OpenRouter model id straight into the node.
* **Bring your own keys.** Provider keys are stored encrypted and used server-side.

See the [Models](/pipelines/models.md) page for the catalog and the [Secrets](#secrets) concept for provider keys.

***

### Runs & versions

#### What they are

A **run** is a single execution of a pipeline, whether triggered from the editor or over the API. Every run is recorded with per-node timing, token counts, cost, and status.

#### Core ideas

* **Run history.** Inspect any run node by node to see exactly how a prompt became an output. Filter by trigger (editor vs. API).
* **Versioning.** Each publish creates a new version. You can roll back to an earlier version at any time.
* **Export.** Export run history for SOC 2, HIPAA, or an internal audit.

***

### Published endpoints & API keys

#### What they are

Publishing a pipeline exposes it as a versioned HTTP endpoint under `https://trezalabs.com/api/pipelines/<id>`. You authenticate with a Treza API key (`treza_live_...`), created on the **API keys** page and sent as a bearer token.

#### Two ways to call it

* **Typed** - `POST /api/pipelines/<id>/invoke` with `{ "inputs": { ... } }` returns a `runId`; poll `GET .../invoke?runId=...` for JSON keyed by the output contract.
* **OpenAI-compatible** - `POST /api/pipelines/<id>/chat/completions`, a drop-in for any OpenAI SDK, streaming included.

See the [Pipeline API](/api/pipeline-api.md) reference for full request and response shapes.

***

### Guardrails

#### What they are

Guardrail nodes handle sensitive data inside a pipeline. The redaction and PII nodes strip personal data before it reaches a model or an external system; conditional-routing nodes branch the graph based on the data.

The same redaction engine is also available as a standalone OpenAI-compatible gateway. See the [AI Gateway](/ai-gateway/ai-control-plane.md) for details.

***

### Secrets

#### What they are

The secrets manager stores provider API keys and other credentials your nodes need. Values are envelope-encrypted with KMS at rest, never returned by any API, and injected server-side at run time, so your pipeline can call a provider without your application handling the key.

***

### Billing & credits

#### What it is

Treza is **prepaid credits**, with no subscription and no recurring charge. You buy a credit pack once (starting at $10), and credits are spent as your pipelines run models. Only successful runs are charged. New accounts start with $5 in free credits, and credits never expire. Track your balance and spend in billing settings.

Enterprise adds dedicated Treza Enclaves, SSO, and postpaid invoicing. See [Plans & Pricing](/ai-gateway/plans-and-pricing.md).

***

## Advanced & Enterprise

The building blocks below power guardrails, hardware-attested execution, key management, and on-chain verification. Most pipelines never touch them directly, but they are available when you need hardware isolation, cryptographic attestation, or zero-knowledge identity.

***

### Providers

#### What they are

Backends capable of running secure enclaves. AWS Nitro Enclaves is the provider available today (additional providers are on the roadmap). Providers expose supported regions and a config schema (e.g., dockerImage, cpuCount, memoryMiB).

#### Why it matters

Each provider has different runtime limits, compliance certifications, and regional availability. You pick one and pass provider-specific providerConfig when creating an enclave.

#### Key objects & calls

* getProviders() → list all available providers, regions, and config schemas
* getProvider(providerId) → fetch details for a specific provider
* providerConfig → per-provider runtime settings (validated against schema)

#### Typical flow

1. List providers → choose one based on your compliance/region needs
2. Read provider's configSchema → understand required fields
3. Validate your config against schema
4. Create enclave with providerId + providerConfig

***

### Enclaves

#### What they are

Isolated, attested compute environments that run your container image in a hardware-protected enclave. They provide cryptographically verifiable isolation from cloud operators and other tenants.

#### Core ideas

* Creation: You provide providerId, region, providerConfig (e.g., Docker image + resources), and a sourceType (registry, private-registry, or github)
* Ownership: All resources are scoped to your wallet address
* Integration: Optionally link a GitHub repo/branch — Treza builds the image for you
* Attestation: Every deployed enclave can generate cryptographic proof of its integrity

#### Key objects & calls

* createEnclave(request) → deploy a new enclave
* getEnclave(enclaveId) → fetch enclave details and status
* getEnclaves(walletAddress) → list all your enclaves
* updateEnclave(request) → modify configuration or GitHub connection
* deleteEnclave(enclaveId, walletAddress) → permanently remove
* getEnclaveLogs(enclaveId, logType, limit) → fetch logs

#### What runs inside

Your Docker image (from a public registry, a private registry, or built from your GitHub repository and pushed to ECR) plus environment variables you configure through your provider's settings.

#### When to use

* Running sensitive computations that require hardware-level isolation
* Processing confidential data (PII, healthcare, financial)
* Building zero-trust applications with cryptographic verification
* Multi-party computation scenarios

***

### Lifecycle

#### What it is

The operational state machine that manages enclave deployment, operation, and teardown.

#### States

Build Flow (GitHub-sourced enclaves only):

* PENDING\_BUILD → build queued
* BUILDING → CodeBuild is building the image from your repo
* BUILD\_FAILED → build error (see Build logs)

Deployment Flow:

* PENDING\_DEPLOY → awaiting deployment initiation
* DEPLOYING → infrastructure provisioning in progress
* DEPLOYED → enclave is running and ready

Pause/Resume Flow:

* PAUSING → stopping compute resources
* PAUSED → enclave suspended, no compute costs
* RESUMING → restarting from paused state
* DEPLOYED → back to running state

Termination Flow:

* PENDING\_DESTROY → awaiting termination initiation
* DESTROYING → infrastructure teardown in progress
* DESTROYED → final state — enclave removed, resources freed (irreversible)

Error State:

* FAILED → deployment or operation error (see error\_message)

#### Actions

* pauseEnclave(enclaveId, walletAddress) → stop compute without destroying
* resumeEnclave(enclaveId, walletAddress) → restart a paused enclave
* terminateEnclave(enclaveId, walletAddress) → permanently destroy (irreversible)

#### When to use what

| Action    | Use When                                      | Result                                    |
| --------- | --------------------------------------------- | ----------------------------------------- |
| Pause     | Stop spending temporarily; keep configuration | No compute costs, quick restart           |
| Resume    | Bring paused enclave back online              | Returns to DEPLOYED state                 |
| Terminate | Done with enclave permanently                 | All data destroyed, cannot undo           |
| Delete    | Remove enclave record completely              | Enclave must be DESTROYED or FAILED first |

***

### Attestation & Verification

#### What it is

Cryptographic proof that your enclave is running genuine, unmodified code inside a hardware-protected secure enclave. Uses Platform Configuration Registers (PCRs), certificate chains, and signed attestation documents.

#### Why it matters

Allows you and third parties to verify:

* The exact code running in your enclave (via PCR measurements)
* The enclave is running in genuine AWS Nitro hardware
* No tampering has occurred since deployment
* Compliance with security standards (FIPS 140-2, SOC2, HIPAA, etc.)

#### Key concepts

**PCR Measurements**

Hardware-generated cryptographic hashes:

* PCR0: Hash of the enclave image file
* PCR1: Linux kernel and bootstrap hash
* PCR2: Application/container hash
* PCR8: Signing certificate hash

**Attestation Document**

Contains:

* PCR measurements
* X.509 certificate for verification
* Certificate authority bundle
* Timestamp and module ID
* Optional user data and nonce for replay protection

**Verification Details**

* Trust Level: HIGH, MEDIUM, LOW, or UNKNOWN
* Integrity Score: 0-100% confidence rating
* Verification Status: VERIFIED, PENDING, or FAILED
* Compliance Checks: SOC2, HIPAA, FIPS 140-2, Common Criteria
* Risk Score: Lower is better (0-100)

#### Key objects & calls

* getAttestation(enclaveId) → retrieve attestation document + verification details
* getVerificationStatus(enclaveId) → quick status check
* verifyAttestation(enclaveId, request?) → comprehensive verification with checks
* generateIntegrationSnippet(enclaveId, language) → code for third-party verification

#### Typical flow

1. Deploy enclave → wait for DEPLOYED status
2. Call getAttestation(enclaveId) → get attestation document
3. Share verification URL with third parties
4. Third parties call verification endpoint with optional nonce
5. Receive trust level, PCR hashes, and compliance status

#### When to use

* Before processing sensitive data: Verify enclave integrity first
* Compliance audits: Provide cryptographic proof of secure execution
* Multi-party scenarios: Let partners verify your enclave independently
* Zero-trust architectures: Continuously verify, never trust blindly
* Integration with external systems: Provide verification endpoints to partners

#### What you get

```json
{
  "attestationDocument": {
    "pcrs": {
      "0": "abc123...",
      "1": "def456...",
      "2": "ghi789...",
      "8": "jkl012..."
    },
    "certificate": "-----BEGIN CERTIFICATE-----...",
    "timestamp": 1234567890,
    "moduleId": "i-abc123..."
  },
  "verification": {
    "trustLevel": "HIGH",
    "verificationStatus": "VERIFIED",
    "integrityScore": 95
  },
  "endpoints": {
    "verificationUrl": "https://trezalabs.com/api/enclaves/{id}/attestation/verify",
    "apiEndpoint": "https://trezalabs.com/api/enclaves/{id}/attestation",
    "webhookUrl": "https://trezalabs.com/webhooks/attestation/{id}"
  }
}
```

***

### Tasks

#### What they are

Scheduled operations that run inside your enclaves. Tasks use cron expressions for flexible scheduling and can automate recurring workloads.

#### Core ideas

* Scheduling: Cron-style expressions (e.g., 0 0 \* \* \* for daily at midnight)
* Association: Each task is linked to a specific enclave
* Ownership: Scoped to your wallet address
* Execution tracking: History of runs with timestamps

#### States

* running → task is active and executing on schedule
* stopped → task is paused, not executing
* failed → last execution encountered an error
* pending → task created but not yet started

#### Key objects & calls

* createTask(request) → create new scheduled task
* getTasks(walletAddress) → list all your tasks
* updateTask(request) → modify schedule, status, or configuration
* deleteTask(taskId, walletAddress) → remove task

#### Typical flow

1. Create enclave → wait for DEPLOYED status
2. Create task with enclaveId, schedule, and description
3. Task runs automatically on schedule
4. Monitor via lastRun timestamp and status
5. Update status: 'stopped' to pause execution

#### When to use

* Batch processing: Run data processing jobs nightly
* Health checks: Periodic monitoring and alerts
* Data synchronization: Regular backups or sync operations
* Scheduled maintenance: Cleanup, archival, or rotation tasks
* Report generation: Daily/weekly/monthly automated reports

#### What you need

```json
{
  name: "Risk Assessment",
  description: "Calculate portfolio risk metrics every 6 hours",
  enclaveId: "enc_abc123",
  schedule: "0 */6 * * *",  // Every 6 hours
  walletAddress: "0x4B0897b0513fdc7C541B6d9D7E929C4e5364D2dB"
}
```

***

### Logs & Monitoring

#### What it is

Comprehensive logging system aggregating logs from multiple sources across your enclave lifecycle.

#### Log sources

**Application Logs**

Stdout/stderr from your Docker container. View what your application prints.

**ECS Deployment Logs**

AWS ECS service logs showing infrastructure-level events (task starting, stopping, health checks).

**Step Functions Logs**

Workflow orchestration logs from deployment/termination state machines.

**Lambda Logs**

Execution logs from trigger functions, validators, and error handlers.

**Build Logs**

CodeBuild output for GitHub-sourced enclaves (clone → build → push to ECR).

**Error Logs**

Aggregated errors from all sources for quick troubleshooting.

#### Key objects & calls

* getEnclaveLogs(enclaveId, logType, limit) → fetch logs
* logType: 'all', 'application', 'ecs', 'stepfunctions', 'lambda', 'build', 'errors'
* limit: max entries to return (default 100)

#### Log structure

```json
{
  timestamp: 1234567890,
  message: "Application started",
  source: "application",     // or "ecs", "stepfunctions", "lambda"
  stream: "stdout",
  logGroup: "/aws/ecs/...",
  type: "application"
}
```

#### When to use what

| Log Type      | Use When                                       |
| ------------- | ---------------------------------------------- |
| application   | Debugging your container code                  |
| ecs           | Infrastructure issues (deployment failures)    |
| stepfunctions | Understanding workflow state transitions       |
| lambda        | Troubleshooting triggers or validators         |
| build         | Following GitHub builds (clone → build → push) |
| errors        | Quick overview of all problems                 |
| all           | Comprehensive investigation across all sources |

#### Typical flow

1. Enclave enters FAILED or unexpected state
2. Call getEnclaveLogs(enclaveId, 'errors', 50)
3. Identify error source
4. Call specific log type for detailed context
5. Fix issue and redeploy

***

### API Keys & Authentication

#### What they are

Programmatic access credentials for using the Treza SDK. API keys provide scoped permissions and are tied to your wallet address.

#### Why it matters

Enables CI/CD pipelines, automation scripts, and third-party integrations to manage your enclaves without manual UI interaction.

#### Permission scopes

* enclaves:read → list and view enclave details
* enclaves:write → create, update, delete, pause, resume, terminate enclaves
* tasks:read → view tasks and execution history
* tasks:write → create, update, delete tasks
* logs:read → access logs from all sources

#### Key objects & calls

* createApiKey(request) → generate new API key (key shown once!)
* getApiKeys(walletAddress) → list your API keys
* updateApiKey(request) → change permissions or status
* deleteApiKey(apiKeyId, walletAddress) → revoke access

#### States

* active → key is valid and can authenticate requests
* inactive → key is disabled but not deleted (can be reactivated)

#### When to use

* CI/CD pipelines: Automate deployments from GitHub Actions, GitLab CI
* Infrastructure as Code: Manage enclaves with Terraform or Pulumi
* Monitoring systems: Automated health checks and log retrieval
* Multi-user scenarios: Different keys for different team members/systems
* Security rotation: Regular key rotation without affecting other systems

#### Best practices

```typescript
// Create limited-scope keys
const readOnlyKey = await client.createApiKey({
  name: "Monitoring Bot",
  permissions: ['enclaves:read', 'logs:read'],
  walletAddress: myWallet
});

// Production key with full access
const prodKey = await client.createApiKey({
  name: "Production Deploy",
  permissions: ['enclaves:read', 'enclaves:write', 'logs:read'],
  walletAddress: myWallet
});
```

***

### GitHub Integration

#### What it is

OAuth-based connection linking your enclaves to GitHub repositories and branches. Treza clones the selected repo and branch, builds the Docker image with AWS CodeBuild, and pushes it to a private ECR repository — no local Docker tooling required.

#### Core ideas

* OAuth flow: Secure authentication with GitHub (repo and read:user scopes)
* Repository linking: Connect specific repos to enclaves
* Branch selection: Choose which branch to build from (defaults to main)
* Token management: Access tokens are stored in AWS Secrets Manager for the duration of the build, then deleted

#### Key objects & calls

* getGitHubAuthUrl(state?) → start OAuth flow, get authorization URL
* exchangeGitHubCode(request) → exchange OAuth code for access token
* getGitHubRepositories(accessToken) → list user's repos
* getRepositoryBranches(request) → list branches for a repo
* updateEnclave({ githubConnection }) → link GitHub to enclave

#### GitHub connection object

```json
{
  isConnected: true,
  username: "yourusername",
  selectedRepo: "owner/repo-name",
  selectedBranch: "main",
  accessToken: "encrypted..."  // Never exposed to client
}
```

#### Typical flow

1. User initiates GitHub connection in UI
2. Call getGitHubAuthUrl() → redirect user to GitHub
3. User authorizes → GitHub redirects with code
4. Call exchangeGitHubCode({ code }) → get access\_token and user info
5. Call getGitHubRepositories(access\_token) → show user their repos
6. User selects repo → call getRepositoryBranches() → show branches
7. User selects branch → call updateEnclave() with githubConnection

#### When to use

* Managed builds: Deploy straight from source — Treza builds the image for you
* Development workflows: Feature branch → ephemeral test enclave
* Team collaboration: Share enclave configs via Git
* Version tracking: Each build is tagged with the enclave ID and branch
* Private repositories: Build from private repos without exposing credentials

***

### Docker Images

#### What they are

Container images that define your enclave's runtime environment. Treza supports public Docker Hub images, private registries, and ECR.

#### Why it matters

Your enclave runs whatever's in the Docker image. The image contains your application code, dependencies, runtime, and configuration.

#### Key concepts

* Image names: library/hello-world, nginx:latest, myorg/myapp:v1.2.3
* Tags: Version identifiers (:latest, :v1.0, :sha-abc123)
* Registries: Docker Hub (public), ECR (private AWS), custom registries

#### Key objects & calls

* searchDockerImages(query) → search Docker Hub for images
* getDockerTags(repository) → list available tags for an image

#### In provider config

```json
{
  dockerImage: "library/hello-world:latest"  // Public image
}

// or

{
  dockerImage: "123456789.dkr.ecr.us-west-2.amazonaws.com/myapp:v1.0"  // Private ECR
}
```

#### When to use what

| Image Type         | Use When                            | Example                                 |
| ------------------ | ----------------------------------- | --------------------------------------- |
| Public Docker Hub  | Testing, demos, open-source tools   | nginx:alpine                            |
| Private Docker Hub | Your proprietary apps (small teams) | yourorg/app:latest                      |
| AWS ECR            | Production workloads, enterprise    | 123.dkr.ecr.region.amazonaws.com/app:v1 |
| Custom registry    | On-prem, air-gapped environments    | registry.internal.com/app               |

#### Best practices

```typescript
// ✅ Good: Specific version tag
dockerImage: "postgres:15.2-alpine"

// ⚠️ Risky: Latest tag (changes without notice)
dockerImage: "postgres:latest"

// ✅ Good: Semantic versioning
dockerImage: "myapp:v1.2.3"

// ❌ Not supported: digest references (@sha256:...) are rejected by image URI validation
dockerImage: "postgres@sha256:abc123..."
```

***

### AI Control Plane (PII Redaction Proxy)

#### What it is

An OpenAI-compatible proxy that strips PII from your LLM traffic before it reaches the model provider. Your agents send chat completions to a Treza proxy endpoint instead of the provider directly; Treza redacts sensitive entities, forwards the request upstream, and returns the response.

#### Core ideas

* Proxies: Customer-configured redaction endpoints. Each proxy points at an upstream provider (openai, azure-openai, anthropic, or custom) and carries a redaction policy. Select one per request via the x-treza-proxy header.
* Redaction policy: Which PII entity types to strip (NAME, EMAIL, PHONE, ADDRESS, SSN, CC, MRN, DOB, ACCOUNT, URL, DATE, SECRET). Custom policies are plan-gated.
* Upstream keys: Send your provider API key per-request (x-model-key header) or store it KMS-encrypted on the proxy and let Treza use it server-side.
* TEE redaction: On Enterprise, redaction runs inside a Treza Nitro Enclave with hardware attestation; lower tiers use managed software redaction.
* Audit trail: Every redaction request is written to an audit log (export is plan-gated).

#### Key objects & calls

* POST /api/redact/chat/completions → OpenAI-compatible chat endpoint with redaction applied
* POST /api/redact/run → redact a raw text string, returns detected entities
* GET /api/redact/attest → fetch enclave attestation for the redaction pipeline (Enterprise)
* /api/proxies → create, list, update, and delete redaction proxies

#### Typical flow

1. Create a proxy → choose upstream provider and redaction policy
2. Point your agent's base URL at the Treza proxy endpoint
3. Treza redacts PII → forwards to the model → returns the response
4. Review usage and the audit log in the control plane

#### When to use

* Routing LLM traffic that may contain customer PII
* Compliance regimes (HIPAA, GDPR) where prompts can't leave with raw identifiers
* Adding redaction to existing OpenAI-based agents with only a base-URL change

Learn more: [AI Control Plane](/ai-gateway/ai-control-plane.md)

***

### Plans & Billing

#### What it is

Prepaid credits, with no subscription. You buy credit packs once through Stripe, and your balance is drawn down as pipelines run models.

#### Credit packs

| Price | Credits added | Bonus |
| ----- | ------------- | ----- |
| $10   | $10           | -     |
| $25   | $25           | -     |
| $50   | $52.50        | +5%   |

#### Core ideas

* No subscription: you pay for credits once, not on a recurring basis.
* Model usage: credits are spent as your pipelines run models. Only successful runs are charged.
* Free to start: new accounts begin with $5 in free credits, and credits never expire.
* Enterprise: dedicated enclaves, SSO, and postpaid invoicing instead of prepaid credits.

#### When to use what

Credit packs for everything from first prototype to production pipelines. Enterprise when you need hardware-attested execution, SSO, or invoicing on net terms.

Learn more: [Plans & Pricing](/ai-gateway/plans-and-pricing.md)

***

### Signers & Key Management

#### What they are

Pluggable signing strategies that decouple transaction signing from private key storage. Instead of storing raw private keys in environment variables or configuration files, you choose a SignerProvider that matches your security requirements. The SDK ships with three built-in signers: EnclaveSigner (production), LocalSigner (development), and BrowserWalletSigner (client-side).

#### Why it matters

* Key isolation: In production, private keys are generated and stored inside Treza Nitro Enclaves. They never leave the hardware-isolated TEE boundary.
* Attestation-backed signing: Before each signing operation, the EnclaveSigner can cryptographically verify that the enclave hasn't been tampered with.
* Flexibility: Swap between enclave, local, or browser wallet signing with a single config change -- same SDK code, different security posture.
* No PII exposure: Private keys never appear in logs, environment variables, or configuration files in production.
* Compliance: Hardware-isolated key management satisfies requirements for SOC2, FIPS 140-2, and financial services regulations.

#### Core ideas

SignerProviderInterface that all signers implement. Defines two methods: getSigner() returns an ethers.js Signer; getAddress() returns the signing address. Any custom key management system (AWS KMS, HashiCorp Vault, hardware wallets) can be integrated by implementing this interface.EnclaveSignerProduction-grade signer that routes signing requests through the Treza Platform API to a Nitro Enclave. The enclave holds the private key in memory-only storage (no persistent disk). Supports attestation verification before signing.LocalSignerDevelopment-only signer that wraps a raw private key string into an ethers.js Wallet. Emits a console warning if used in a production environment. Intended for local development, demos, and automated testing.BrowserWalletSignerClient-side signer that delegates to MetaMask or any injected Web3 wallet (window\.ethereum). Prompts the user to approve each transaction. Suitable for dApp frontends.Signer resolution priorityWhen TrezaKYCClient needs to sign a transaction, it resolves a signer using this priority chain:

1. Explicit signer passed to the method call
2. signerProvider from blockchain config (recommended)
3. Deprecated privateKey from blockchain config (backward compat only)

#### Signing flow (EnclaveSigner)

1. Your app calls submitProofOnChain() or verifyProofOnChain()
2. TrezaKYCClient resolves the signer via signerProvider.getSigner()
3. EnclaveSigner optionally verifies enclave attestation (PCR checks)
4. Unsigned transaction is sent to the enclave via POST /api/enclaves/{id}/sign/transaction
5. Enclave signs the transaction inside the TEE and returns the signed bytes
6. TrezaKYCClient submits the signed transaction to the blockchain
7. Your app receives the transaction hash

#### Key objects & calls

SignerProvider interface

* getSigner(provider?) -- Returns an ethers.js Signer connected to the given provider
* getAddress() -- Returns the signer's Ethereum address
* type -- Human-readable signer type name ('enclave', 'local', 'browser-wallet')

EnclaveSigner

* Constructor: new EnclaveSigner(platformClient, config)
* platformClient -- An authenticated TrezaClient instance
* config.enclaveId -- The enclave ID holding the signing key
* config.verifyAttestation -- Verify enclave integrity before signing (default: true)
* config.attestationNonce -- Optional nonce for replay protection

LocalSigner

* Constructor: new LocalSigner(privateKey)
* privateKey -- Hex-encoded private key (with or without 0x prefix)

BrowserWalletSigner

* Constructor: new BrowserWalletSigner()
* No arguments -- connects to window\.ethereum on first use
* disconnect() -- Clear cached wallet connection

#### When to use what

| Signer                | Environment        | Key Location                      | Attestation | Use Case                            |
| --------------------- | ------------------ | --------------------------------- | ----------- | ----------------------------------- |
| EnclaveSigner         | Production servers | Inside Nitro Enclave (TEE)        | Yes         | Backend services, automated systems |
| LocalSigner           | Local development  | .env file or environment variable | No          | Dev, testing, demos, CI             |
| BrowserWalletSigner   | Client-side dApps  | User's browser wallet             | No          | Frontend applications               |
| Custom SignerProvider | Any                | Your KMS / HSM / Vault            | Optional    | Enterprise, custom infrastructure   |

#### Configuration examples

```typescript
// Production (EnclaveSigner)
import { TrezaClient, TrezaKYCClient, EnclaveSigner } from '@treza/sdk';

const platform = new TrezaClient();
const signer = new EnclaveSigner(platform, {
  enclaveId: process.env.TREZA_ENCLAVE_ID,
  verifyAttestation: true,
});

const client = new TrezaKYCClient({
  apiUrl: process.env.TREZA_API_URL,
  blockchain: {
    rpcUrl: process.env.SEPOLIA_RPC_URL,
    contractAddress: process.env.SEPOLIA_KYC_VERIFIER_ADDRESS,
    signerProvider: signer,
  },
});
```

```typescript
// Custom signer (e.g., AWS KMS)
import { SignerProvider } from '@treza/sdk';
import { ethers } from 'ethers';

class KMSSigner implements SignerProvider {
  readonly type = 'aws-kms';

  async getSigner(provider?: ethers.Provider): Promise<ethers.Signer> {
    // Your KMS signing logic here
  }

  async getAddress(): Promise<string> {
    // Return the address derived from your KMS key
  }
}
```

```typescript
// Client side BrowserWalletSigner
import { TrezaKYCClient, BrowserWalletSigner } from '@treza/sdk';

const client = new TrezaKYCClient({
  apiUrl: 'https://api.trezalabs.com/api',
  blockchain: {
    rpcUrl: 'https://rpc.sepolia.org',
    contractAddress: '0x...',
    signerProvider: new BrowserWalletSigner(),
  },
});
// User will be prompted to connect their wallet on first signing operation
```

#### Best practices

* Always use EnclaveSigner in production -- never store private keys in environment variables, config files, or source code on production servers
* Enable verifyAttestation: true (the default) to cryptographically verify enclave integrity before each signing operation
* Use LocalSigner only for local development and testing; it emits a warning if NODE\_ENV=production
* For CI/CD pipelines, consider a custom SignerProvider that integrates with your secrets manager (AWS KMS, HashiCorp Vault, etc.)
* The deprecated privateKey field in TrezaKYCConfig.blockchain still works for backward compatibility but will be removed in a future major version
* Read-only operations (e.g., isAdult(), getClaims(), hasValidKYC()) don't require a signer at all -- only on-chain write operations need one

#### States

| State                | Description                                        | Can Sign?          |
| -------------------- | -------------------------------------------------- | ------------------ |
| Connected            | Signer resolved and ready                          | Yes                |
| Attestation verified | Enclave integrity confirmed (EnclaveSigner only)   | Yes                |
| Attestation failed   | Enclave integrity check failed                     | No (throws error)  |
| Disconnected         | Browser wallet disconnected or enclave unavailable | No (throws error)  |
| Deprecated           | Using raw privateKey fallback                      | Yes (with warning) |

***

### KYC & Zero-Knowledge Proofs

#### What they are

Privacy-preserving identity verification using zero-knowledge cryptography. Users prove they meet KYC requirements (e.g., age verification, identity checks) without revealing underlying personal data. Proofs are cryptographically verifiable, stored in DynamoDB, and optionally anchored on-chain for immutability.

#### Why it matters

**Privacy**: Users prove attributes (e.g., "I'm over 18") without sharing passport data, birth dates, or photos.

**Compliance**: Satisfy regulatory requirements (KYC/AML) while minimizing PII exposure and data breach risk.

**Portability**: One proof works across multiple services—verify once, use everywhere.

**Auditability**: Blockchain anchoring provides tamper-proof verification history.

**Cost reduction**: Eliminate redundant verification flows and reduce storage of sensitive data.

#### Core ideas

**Zero-Knowledge Proofs (ZK)**

Cryptographic method proving a statement is true without revealing why. Example: "I'm over 18" without sharing your birth date.

**Commitments**

64-character hex hash that binds the prover to specific data without revealing it. Acts as a fingerprint for the proof.

**Public Inputs**

Non-sensitive data visible to verifiers (e.g., commitment hash, proof type). Used to validate the proof without exposing private information.

**Proof Lifecycle**

1. **Generation**: Mobile app or client generates ZK proof from user's credentials
2. **Submission**: Proof submitted to Treza API (POST `/api/kyc/proof`)
3. **Verification**: Cryptographic validation + timestamp checks
4. **Storage**: Proof stored in DynamoDB with metadata
5. **Blockchain**: Optional on-chain submission for immutability
6. **Expiration**: Proofs expire after 7 days (configurable)

#### Key objects & calls

**submitProof(request)** → Submit new ZK proof for verification

Returns: `proofId`, `blockchainProofId`, `verificationUrl`, `expiresAt`, `chainTxHash`

**getProof(proofId, includePrivate?)** → Retrieve proof details

Returns public data by default; use `includePrivate=true` for proof signature (requires auth)

**verifyProof(proofId)** → Verify proof validity and check expiration

Returns: `isValid`, `publicInputs`, `chainVerified`, `expiresAt`

#### Proof structure

```json
{
  commitment: "1234...abcd",           // 64-char hex commitment hash
  proof: "0x1234...9876",              // ZK proof data (min 65 chars)
  publicInputs: ["0xabc...", "0xdef..."], // Public verification data
  timestamp: "2024-12-15T10:30:00Z",   // Must be within 1 hour
  algorithm: "Pedersen-SHA256"         // Cryptographic algorithm
}
```

**For Users (Mobile/Client)**

1. User provides credentials (passport, ID, etc.) to mobile app
2. App generates ZK proof locally using device secure enclave (iOS: Secure Enclave, Android: TEE)
3. Call `submitProof({ userId, proof, deviceInfo })`
4. Receive `proofId` and `verificationUrl`
5. Share `proofId` with services requiring KYC verification

**For Service Providers (Verifiers)**

1. User provides their `proofId` during onboarding
2. Call `verifyProof(proofId)` to check validity
3. Check `isValid`, `chainVerified`, and `expiresAt`
4. Optionally verify on blockchain using `chainTxHash`
5. Grant access based on verification result

**For Developers (Integration)**

1. Generate proof on client-side (mobile/web)
2. Submit to `/api/kyc/proof` endpoint
3. Store returned `proofId` with user account
4. Re-verify periodically using `/api/kyc/proof/{proofId}/verify`
5. Handle expiration by requesting new proof from user

#### When to use

| Scenario                     | Why KYC Proofs Help                                             |
| ---------------------------- | --------------------------------------------------------------- |
| **Age verification**         | Prove age without revealing birth date or ID documents          |
| **Identity checks**          | Verify user identity without storing PII (GDPR/CCPA compliance) |
| **Financial services**       | Meet KYC/AML requirements with minimal data exposure            |
| **Healthcare**               | Verify credentials while maintaining HIPAA compliance           |
| **Multi-platform access**    | One proof works across multiple services/platforms              |
| **Audit requirements**       | Blockchain anchoring provides immutable verification trail      |
| **International compliance** | Satisfy different jurisdictions without data transfer           |

#### Validation rules

**Commitment**

* Must be exactly 64 characters
* Hex format only (0-9, a-f, A-F)
* Unique per user/session

**Proof**

* Minimum 65 characters
* Contains cryptographic signature
* Generated by trusted client (device secure enclave)

**Timestamp**

* Must be within 1 hour of submission
* Prevents replay attacks
* Ensures proof freshness

**Public Inputs**

* Array of hex strings
* Contains non-sensitive verification data
* Minimum 1 input required

#### States

| State      | Description                                              | Queryable          |
| ---------- | -------------------------------------------------------- | ------------------ |
| `verified` | Proof passed cryptographic verification                  | ✅ Yes              |
| `pending`  | Proof submitted, awaiting blockchain confirmation        | ✅ Yes              |
| `failed`   | Verification failed (invalid proof or expired timestamp) | ✅ Yes              |
| `expired`  | Proof passed expiration date (7 days)                    | ❌ Returns HTTP 410 |

#### Integration examples

```typescript
import { TrezaKYCClient } from '@treza/sdk';

const kycClient = new TrezaKYCClient({ apiUrl: 'https://trezalabs.com' });
// Submit proof const result = await kycClient.submitProof({ userId: user.id, proof: zkProof, deviceInfo: { platform: 'web', version: '1.0.0' } });

console.log('Proof ID:', result.proofId); console.log('Verification URL:', result.verificationUrl);
// Verify proof const verification = await kycClient.verifyProof(result.proofId); if (verification.isValid && verification.chainVerified) { console.log('✅ Verified on blockchain'); }Backend Verification

app.post('/onboard', async (req, res) => { 
const { proofId } = req.body;
// Verify proof const result = await fetch( https://trezalabs.com/api/kyc/proof/${proofId}/verify ); const verification = await result.json();

if (!verification.isValid) { 
        return res.status(403).json({ error: 'Invalid KYC proof' }); 
    }
    // Grant access 
    await createUserAccount({ ...userData, kycProofId: proofId }); 
    res.json({ success: true }); 
});

```

* **Privacy-first verification**: Prove attributes without revealing sensitive data
* **Blockchain immutability**: Optional on-chain anchoring for audit trails
* **Automatic expiration**: 7-day validity reduces stale verification risk
* **Device tracking**: Platform and version info for security analysis
* **Flexible verification**: Public endpoints for third-party verification
* **Compliance ready**: GDPR, CCPA, HIPAA-friendly architecture

***

### On-Chain Proof Verification (zkVerify)

#### What it is

Integration with the zkVerify proof-verification chain (via the Horizen Relayer) for verifying ZK proofs on-chain and aggregating them for inexpensive smart-contract verification.

#### Core ideas

* Verification keys: Register a VK once per circuit; reuse the returned vkHash for all subsequent proof submissions
* Proof types: groth16 (default), risc0, ultrahonk, ultraplonk, sp1, ezkl
* Job lifecycle: Queued → Valid → Submitted → IncludedInBlock → Finalized, then AggregationPending → Aggregated → AggregationPublished
* Aggregation: Proofs are batched into a Merkle tree; the aggregation data (Merkle path, domain ID, leaf index, root) lets your smart contract verify the proof via verifyProofAggregation()

#### Key objects & calls

* POST /api/zkverify/register-vk → register a verification key (one-time per circuit)
* POST /api/zkverify/submit-proof → submit proof, publicSignals, and vk (defaults: groth16, Sepolia chainId 11155111)
* GET /api/zkverify/job-status/{jobId} → poll verification job status
* GET /api/zkverify/aggregation/{aggregationId} → fetch aggregation details for on-chain verification

#### Typical flow

1. Register your verification key → store the vkHash
2. Submit a proof → receive a jobId
3. Poll job status until Finalized / Aggregated
4. Fetch aggregation details → verify on-chain in your contract

#### When to use

* Anchoring KYC or compliance proofs on-chain without running your own verifier
* Reducing on-chain verification cost via proof aggregation
* Building smart contracts that consume Treza-issued ZK proofs

Learn more: [zkVerify](https://github.com/treza-labs/treza-docs-site/tree/main/developers/zkverify.md)

***

### zkPassport Verification

#### What it is

Privacy-preserving identity verification from government-issued IDs. Users prove claims about themselves ("I am over 18", "my nationality is X") directly from the NFC chip of their passport or ID card, using zero-knowledge proofs generated on their own phone. No document photos are uploaded, and only the requested claims are revealed.

#### Core ideas

* Server-owned policy: the claim constraints for a verification request are registered with the Treza server before the user scans — the client cannot weaken or modify them
* On-device proving: the ZKPassport mobile app reads the document chip via NFC and generates proofs for exactly the requested claims
* Claim constraints: disclose, gte, gt, lte, lt, eq, in, out, range over fields like age, nationality, birthdate, document\_number
* TEE-attested verification: in production, proof verification runs inside an AWS Nitro Enclave and the result can be wrapped in a hardware-signed attestation document

#### Key objects & calls

* POST /api/zkpassport/request → register a verification request and its claim constraints (server-owned policy)
* POST /api/zkpassport/verify → verify the proofs generated by the user's device, returns an attestation
* GET /api/zkpassport/verify?requestId= → poll the status of a verification request

#### Typical flow

1. Browser creates the request with the ZKPassport SDK → displays a QR code
2. Register the request and its claims with Treza (tamper prevention)
3. User scans the QR code with the ZKPassport app → proofs generated on-device
4. Browser submits the proofs to Treza → verification runs server-side (in a TEE in production)
5. Your app receives an attestation with the claim results

#### When to use

* Age or nationality checks without collecting document data
* KYC onboarding with minimal PII exposure
* Pairing with zkVerify to anchor verification results on-chain

Learn more: [zkPassport](https://github.com/treza-labs/treza-docs-site/tree/main/developers/zkpassport.md)

***

### See Also

* [**Build your first pipeline**](/pipelines/quickstart.md) → *Go from a prompt to a published API*
* [**Models**](/pipelines/models.md) → *The model catalog and how to use any model id*
* [**Pipeline API**](/api/pipeline-api.md) → *Call a published pipeline over HTTP*
* [**Publishing & versioning**](/pipelines/publishing.md) → *Publish, version, and roll back*
* [**AI Gateway**](/ai-gateway/ai-control-plane.md) → *The redaction gateway behind the PII guardrail*
* [**Plans & Pricing**](/ai-gateway/plans-and-pricing.md) → *Pro and Enterprise*

***
