diff --git a/src/content/cre-templates/ai-audit-firewall.mdx b/src/content/cre-templates/ai-audit-firewall.mdx
index d2c7abf19f7..b69133ec380 100644
--- a/src/content/cre-templates/ai-audit-firewall.mdx
+++ b/src/content/cre-templates/ai-audit-firewall.mdx
@@ -23,7 +23,7 @@ datePublished: "2026-08-04"
lastModified: "2026-08-06"
---
-import { Aside, Accordion } from "@components"
+import { Aside } from "@components"
-This workflow runs inside a **Trusted Execution Environment (TEE)** and acts as a confidential gate for proposed
-token interactions. Contract source, transaction details, and model prompts never leave the confidential runtime.
-The TypeScript and Go implementations are behaviorally equivalent - pick whichever language you build in.
+This standalone CRE project implements a confidential pre-execution security firewall for smart contract interactions.
-**Quick navigation:**
+## Description
-- [TypeScript Implementation](#typescript-implementation)
-- [Go Implementation](#go-implementation)
+The workflow screens proposed transactions before they are allowed to proceed. It fetches and validates contract
+intelligence, runs confidential reasoning to classify risk, and then enforces a firewall decision path. Scanner and
+model credentials remain protected inside confidential execution throughout the process.
----
+## Target Customer
-## What This Template Does
+- Professional retail traders
+- Developer shops
+- Founders building trading products
-On every cron execution the workflow:
+## Structure
-1. Fetches a **proposed transaction**, including the token and protocol contract addresses
-2. Fetches the **token and protocol contract artifacts** from a scanner service, verifying scanner credential permissions before trusting the fetched data
-3. Runs **two independent LLM audits** — the second receives the first analysis as prior context
-4. Merges the risk flags and decides **ALLOW**, **DENY**, or **MANUAL_REVIEW**
-5. Writes an audit log entry and a firewall action
-6. Optionally writes the verdict onchain with `EVMClient`
+- `project.yaml`: project-level target settings
+- `secrets.yaml`: secret ID mappings used by the workflow
+- `mock-server.js`: local deterministic API server
+- `ai-audit-firewall-ts/`: TypeScript workflow implementation
+- `ai-audit-firewall-go/`: Go workflow implementation
-
+## Private Inputs
-## Risk Flags
+The following inputs are handled as confidential:
-Both models are asked to evaluate the same four checks:
+- Chain scanner API credentials used for contract metadata retrieval and verification checks.
+- LLM reasoning API credentials used for independent audit analysis.
-| Flag | What it detects |
-| --------------------- | ------------------------------------------------------------------ |
-| `obfuscatedTax` | Hidden or dynamically-adjustable transfer fees |
-| `privilegeEscalation` | Owner or admin functions that can seize funds or change core rules |
-| `externalCallRisk` | Untrusted external calls and reentrancy surface |
-| `logicBomb` | Conditional logic that changes behavior after a trigger is reached |
+## Workflow Notes
-## Verdict Logic
+1. Monitor and ingest the proposed interaction.
+ The workflow receives candidate transaction context, including token and protocol contract addresses.
+2. Fetch and validate contract data confidentially.
+ It retrieves source and ABI artifacts through the scanner and verifies scanner credential permissions before trusting fetched data.
+3. Run smart contract audit analysis.
+ The workflow submits context to multiple reasoning models and classifies behavior into structured risk signals:
+ - `obfuscatedTax`
+ - `privilegeEscalation`
+ - `externalCallRisk`
+ - `logicBomb`
+4. Enforce firewall action and record outcomes.
+ Based on aggregate risk, the workflow allows execution, blocks malicious interactions, or routes the attempt for manual review while preserving audit and action logs.
-The `determineVerdict` function merges both analyses:
+Note: Any reasoning stage can be replaced with deterministic rule-based logic if a purely policy-engine implementation is preferred.
-- **DENY** — any malicious risk flag is set in the merged flag set
-- **MANUAL_REVIEW** — either model recommends `review`, either model's confidence is below `0.7`, or the two models disagree
-- **ALLOW** — both models agree, both are confident, and no risk flag fired
+## Required Environment Variables
-
+Copy `.env.example` to `.env` and provide values for:
-## Prerequisites
+- `CRE_ETH_PRIVATE_KEY` (optional for local simulate, required for real chain writes)
+- `MOCK_PORT`
+- `MOCK_SCANNER_API_KEY`
+- `MOCK_PRIMARY_LLM_API_KEY`
+- `MOCK_SECONDARY_LLM_API_KEY`
-- **[Bun](https://bun.com/docs/installation)** — used to install dependencies and to run the shared mock server (both languages)
-- **[Go](https://go.dev/dl/) 1.25 or later** — only if you are building the Go implementation
-- **[Chainlink CRE CLI](https://docs.chain.link/cre/getting-started/cli-installation)** installed and configured
-- **Git** for cloning the repository
-- **A funded wallet on Ethereum Sepolia** — only if you want to test the optional onchain delivery path
+The local mock server for this project only exposes routes under `/audit-firewall/*`.
-`ai-audit-firewall/` is a single CRE project shared by both languages — `project.yaml`, `secrets.yaml`, `.env.example`, and `contracts/` live at the project root, with `ai-audit-firewall-ts/` and `ai-audit-firewall-go/` as sibling workflow directories underneath it.
+**Quick navigation:**
-## TypeScript Implementation
+- [TypeScript Quick Start](#typescript-quick-start)
+- [Go Quick Start](#go-quick-start)
-### Getting Started with TypeScript
+## TypeScript Quick Start
-
+1. Install dependencies
```bash
-git clone https://github.com/smartcontractkit/cre-templates.git
-cd cre-templates/starter-templates/confidential-workflows/ai-audit-firewall
bun install
```
-
-
-
+2. Create environment file
```bash
cp .env.example .env
```
-Set the values you want to use. The mock keys are used by both the workflow and the shared demo server:
+3. Start mock server
```bash
-MOCK_PORT=8787
-MOCK_SCANNER_API_KEY=mock-scanner-key
-MOCK_PRIMARY_LLM_API_KEY=mock-primary-llm-key
-MOCK_SECONDARY_LLM_API_KEY=mock-secondary-llm-key
-```
-
-`secrets.yaml` maps the logical secret IDs to these environment variables.
-
-
-
-
-
-Open `ai-audit-firewall-ts/config.staging.json`:
-
-```json
-{
- "schedule": "0 */5 * * * *",
- "mock_base_url": "http://127.0.0.1:8787/audit-firewall",
- "scanner_url": "http://127.0.0.1:8787/audit-firewall/scanner",
- "primary_llm_url": "http://127.0.0.1:8787/audit-firewall/v1/analysis/primary",
- "secondary_llm_url": "http://127.0.0.1:8787/audit-firewall/v1/analysis/secondary",
- "secrets_ids": {
- "scanner_api_key_id": "scanner_api_key",
- "primary_llm_api_key_id": "primary_llm_api_key",
- "secondary_llm_api_key_id": "secondary_llm_api_key"
- }
-}
+bun run mock:server
```
-1. Keep the default values if you are using the shared mock server on port `8787`
-2. Update `mock_base_url`, `scanner_url`, `primary_llm_url`, and `secondary_llm_url` if you are using a different port or host
-3. Keep `secrets_ids` aligned with `secrets.yaml`
-4. If you do not want to test onchain delivery yet, remove or clear the `evms` entry
-
-
-
-
+4. In another terminal, run checks
```bash
bun run typecheck
bun run test
```
-
-
-
-
-From the project root:
-
-```bash
-bun run mock:server
-```
-
-The server listens on `http://127.0.0.1:8787` and serves this workflow's routes under the `/audit-firewall/*` namespace — transaction proposals, contract artifact lookups, the two audit model endpoints, and the logging and action endpoints.
-
-
-
-
-
-In a new terminal, from the project root:
+5. Simulate workflow
```bash
cre workflow simulate ./ai-audit-firewall-ts --target=staging-settings
```
-The workflow logs each stage (`audit-firewall-onchain-report-start`, `audit-firewall-complete`) and returns a JSON result containing the verdict, reasoning, merged risk flags, both model analyses, the audit log ID, and the firewall action ID.
-
-
+## Go Quick Start
-## Go Implementation
-
-### Getting Started with Go
-
-
-
-From the shared project root:
+1. Create environment file (at the shared project root)
```bash
cp ../.env.example ../.env
```
-`../secrets.yaml` maps the same logical secret IDs shown above to these environment variables.
-
-
-
-
-
-```bash
-cd ai-audit-firewall-go
-go vet ./...
-go test ./...
-```
-
-
-
-
-
-From the `ai-audit-firewall-go` directory (requires Node or Bun):
+2. Start the mock server (requires Node or Bun)
```bash
bun mock-server.js
```
-
-
-
-
-In a new terminal, from the project root:
+3. In another terminal, run checks
```bash
-cre workflow simulate ./ai-audit-firewall-go --target=staging-settings
-```
-
-
-
-### Confidentiality Boundary (Go)
-
-The handler is registered with `cre.HandlerInTee`, so it receives a `cre.TeeRuntime` rather than a `cre.Runtime`. Scanner and model credentials are released by the Vault DON directly into the attested enclave and decrypted only when `GetSecret()` runs; HTTP calls go through `client.SendRequestInTee(runtime, ...)`, keeping URLs, headers, contract source, and model reasoning confidential from node operators. The only place that leaves the enclave is `writeVerdictOnChain`, which calls `runtime.UsingTheDons()` — and only the verdict code, the risk-flag bitmask, and the chain selector cross that boundary. The contract source, model reasoning, and scanner credentials never do.
-
-
-
-### Restrictions (Go pre-hook)
-
-The Go implementation registers with `cre.HandlerInTeeWithPreHook`. The pre-hook runs **in the DON, before the enclave executes**, and returns a closed capability set for that execution:
-
-| Restriction | Value | Why |
-| ---------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Capability set type | `CLOSED` | Any capability call not listed below is rejected outright |
-| `maxTotalCalls` | 10 | Overall ceiling across all capabilities |
-| `http-actions@1.0.0-alpha` / `SendRequest` | 8 | Steady state is 7 calls (proposal, credential check, 2 contract fetches, 2 model calls, audit log, firewall action); 8 leaves one call of headroom |
-| `consensus@1.0.0-alpha` / `Report` | 1 | One signed report per run |
-| `evm:ChainSelector:@1.0.0` / `WriteReport` | 1 | One onchain write per run, scoped to the configured chain |
-| `maxSecrets` | 3 | Exact-match only, in the `main` namespace |
-
-The EVM restriction is added only when an EVM target is configured, keeping the onchain leg opt-in. Because the set is closed, adding a capability call to the workflow means raising the matching limit here, or the run gets cut off by its own restrictions.
-
-## Secrets
-
-Both implementations expect these secret IDs in `secrets_ids`:
-
-- `scanner_api_key`
-- `primary_llm_api_key`
-- `secondary_llm_api_key`
-
-## Optional Onchain Delivery
-
-The workflow can encode the verdict as a CRE report and write it to a consumer contract.
-
-
-
-Deploy `contracts/AuditFirewallConsumer.sol`. It extends `contracts/ReceiverTemplate.sol`, which validates that reports arrive from the Chainlink Forwarder.
-
-Forwarder mode must match your environment:
-
-- **Simulation** uses the Mock Forwarder
-- **Production** uses the Keystone Forwarder
-
-Deploy or configure the consumer with the forwarder address that matches the mode you are running. See [Forwarder Addresses](https://docs.chain.link/cre/supported-networks-ts#forwarder-addresses) for the correct address.
-
-
-
-
-
-Set `evms[0]` in your config file:
-
-```json
-"evms": [
- {
- "chain_selector_name": "ethereum-testnet-sepolia",
- "consumer_address": "0xYourConsumer",
- "gas_limit": "500000"
- }
-]
+go vet ./...
+go test ./...
```
-1. Set `evms[0].consumer_address` to the deployed consumer address
-2. Keep `evms[0].chain_selector_name` aligned with the target network in `project.yaml`
-3. Increase `evms[0].gas_limit` if your deployed contract needs more gas
-
-
-
-
-
-## TEE Constraints
-
-The third argument to the TEE handler API declares which enclaves the handler accepts:
+4. Simulate workflow
-```ts
-{
-} // any registered TEE, any region
-{
- regions: ["us-west-2"]
-} // any TEE, restricted to a region
-;[{ tee: "nitro", regions: ["us-west-2"] }] // specific TEE types and regions
-```
-
-```go
-cre.AnyTee{} // any registered TEE, any region
-cre.AnyTeeInRegions{Regions: []cre.Region{cre.AwsUsWest2}} // any TEE, restricted to a region
-cre.OneOfTees{cre.Nitro{Regions: []cre.NitroRegion{cre.NitroUsWest2}}} // specific TEEs and regions
+```bash
+cd .. && cre workflow simulate ./ai-audit-firewall-go --target=staging-settings
```
-
-AWS Nitro in `us-west-2` is currently the only registered TEE type and region. In Go, each TEE binding owns its own
-region enum, so passing a region a TEE does not support is a compile-time error.
-
-## Production Checklist
-
-1. Replace the example URLs in `config.production.json` with real endpoints
-2. Set real secret values for the scanner and both model providers
-3. Deploy the consumer contract
-4. Update `config.production.json` so `evms[0].consumer_address`, `evms[0].chain_selector_name`, and `evms[0].gas_limit` match the deployed target
-5. Confirm the consumer's forwarder address matches your environment
-
-## Troubleshooting
-
-- **401 responses from the APIs** usually indicate a secret mismatch between `.env`, `secrets.yaml`, and `secrets_ids` in the config file
-- **Simulation failures tied to RPC config** usually come from incorrect `project.yaml` target values
-- **Model responses that fail to parse** mean your configured endpoint is not returning the expected JSON payload shape — the workflow expects `riskFlags`, `recommendation`, `confidence`, and `reasoning`
-- **Onchain write failures** mean the consumer rejected the report; confirm the forwarder address configured on the contract matches the mode you are simulating or deploying in
-- **Go simulation cut off mid-run** usually means a capability call was added without raising the matching limit in the pre-hook's restriction set
-
-## Further Reading
-
-- [Confidential Workflows in CRE](https://docs.chain.link/cre/concepts/confidential-workflows) - concepts and use cases
-- [Making a Workflow Confidential](https://docs.chain.link/cre/guides/workflow/using-confidential-workflows) - step-by-step guide
-- [Confidential Workflows Client SDK Reference](https://docs.chain.link/cre/reference/sdk/confidential-workflows-client) - full API
-- [Hello Confidential Workflows](/cre-templates/hello-confidential-workflows) - the minimal version of this pattern
diff --git a/src/content/cre-templates/automated-liquidation-protection.mdx b/src/content/cre-templates/automated-liquidation-protection.mdx
index 782b09bec2f..a9bd05bb8d2 100644
--- a/src/content/cre-templates/automated-liquidation-protection.mdx
+++ b/src/content/cre-templates/automated-liquidation-protection.mdx
@@ -23,7 +23,7 @@ datePublished: "2026-08-04"
lastModified: "2026-08-06"
---
-import { Aside, Accordion } from "@components"
+import { Aside } from "@components"
-This workflow runs inside a **Trusted Execution Environment (TEE)** and generates a policy-constrained defense plan
-for a leveraged position. Risk data, policy parameters, and model prompts never leave the confidential runtime. The
-TypeScript and Go implementations are behaviorally equivalent - pick whichever language you build in.
+This standalone CRE project implements a confidential liquidation-defense workflow for DeFi lending positions.
-**Quick navigation:**
+## Description
-- [TypeScript Implementation](#typescript-implementation)
-- [Go Implementation](#go-implementation)
+The workflow continuously evaluates borrower risk and takes defensive action before a position becomes unsafe.
+During periods of high volatility, it can increase collateral, reduce debt, or combine both strategies based on
+policy constraints. Sensitive operational data remains protected in confidential execution, including exchange
+credentials, model credentials, and user-defined risk thresholds.
----
+## Target Customer
-## What This Template Does
+- Professional retail traders
+- Developer shops
+- Founders building trading products
-On every cron execution the workflow:
+## Structure
-1. Fetches the exchange and model API secrets from the CRE secrets store
-2. Reads the account **policy** and the current **risk state** (leverage, liquidation proximity, collateral health, reserves)
-3. Computes a **risk score** from the risk state and policy thresholds
-4. Asks an LLM for a set of **defensive actions**
-5. Enforces reserve, slippage, and sequencing constraints on the proposed actions
-6. Executes the approved actions through an execution endpoint
+- `project.yaml`: project-level target settings
+- `secrets.yaml`: secret ID mappings used by the workflow
+- `mock-server.js`: local deterministic API server
+- `automated-liquidation-protection-ts/`: TypeScript workflow implementation
+- `automated-liquidation-protection-go/`: Go workflow implementation
-If the position is healthy or no action survives the policy filter, the workflow returns `SAFE` without executing anything.
+## Private Inputs
-
+The following inputs are treated as confidential:
-## Defensive Actions
-
-The LLM may propose any of the following action types. Each one is validated against the policy before it becomes executable:
-
-| Action | Description |
-| --------------------------- | -------------------------------------------------------- |
-| `add_collateral` | Post additional collateral from reserves |
-| `bridge_and_add_collateral` | Bridge funds from another chain, then post as collateral |
-| `reallocate_collateral` | Move collateral between positions or venues |
-| `reduce_position` | Partially deleverage the position |
-| `close_position` | Fully exit the position |
-| `hedge_short_perp` | Open an offsetting short perpetual |
-
-## Policy Constraints
-
-The policy is fetched at runtime and bounds everything the model is allowed to do:
-
-- `max_reserve_deployment_usdc` — ceiling on capital deployed in a single cycle
-- `min_reserve_balance_usdc` — reserve floor that must remain untouched
-- `max_acceptable_leverage` — leverage target used in risk scoring
-- `incremental_deleveraging_limit_pct` — cap on how much of the position can be reduced per cycle
-- `liquidation_warning_action_threshold` — proximity threshold that triggers a defense
-- `allow_leverage_reduction` — whether deleveraging actions are permitted at all
-- `execution_sequence_preference` — `collateral-first`, `deleverage-first`, or `hedge-first`
-- `preferred_venues` — venue allowlist used when routing each action
-
-
+- Exchange API credentials used to fetch account context such as stablecoin reserves and available cash balance.
+- LLM reasoning API credentials and policy parameters used to govern defense behavior, including minimum and target health factors, reserve deployment caps, minimum reserve balance, and collateral allocation limits.
+- Execution preferences that define how defense actions should be sequenced.
+
+## Workflow Notes
-## Prerequisites
+1. Observe liquidation risk signals.
+ The workflow tracks collateral and debt asset pricing, health factor, liquidation proximity, LTV, liquidation threshold, and market volatility.
+2. Enforce user policy constraints.
+ Confidential reasoning evaluates how much capital can be deployed, whether debt reduction should be prioritized, which reserve assets are eligible, and what execution sequence is preferred.
+3. Select defense actions.
+ The workflow builds a response plan that may include collateral-focused moves (deposit, bridge, swap-then-deposit) and debt-focused moves (repay, swap-then-repay, partial payoff, full payoff).
+4. Execute the approved defense plan.
-- **[Bun](https://bun.com/docs/installation)** — used to install dependencies and to run the shared mock server (both languages)
-- **[Go](https://go.dev/dl/) 1.25 or later** — only if you are building the Go implementation
-- **[Chainlink CRE CLI](https://docs.chain.link/cre/getting-started/cli-installation)** installed and configured
-- **Git** for cloning the repository
+Note: Every reasoning stage can be implemented with deterministic rule-based logic instead of an LLM, if your deployment requires a fully rules-driven policy engine.
-`automated-liquidation-protection/` is a single CRE project shared by both languages — `project.yaml`, `secrets.yaml`, and `.env.example` live at the project root, with `automated-liquidation-protection-ts/` and `automated-liquidation-protection-go/` as sibling workflow directories underneath it.
+## Required Environment Variables
-## TypeScript Implementation
+Copy `.env.example` to `.env` and provide values for:
+
+- `CRE_ETH_PRIVATE_KEY` (optional for local simulate)
+- `MOCK_PORT`
+- `MOCK_EXCHANGE_API_KEY`
+- `MOCK_OPENAI_API_KEY`
+- `MOCK_LIQUIDATION_WARNING_ACTION_THRESHOLD`
+- `MOCK_LIQUIDATION_MINIMUM_HEALTH_FACTOR`
+- `MOCK_LIQUIDATION_TARGET_HEALTH_FACTOR`
+- `MOCK_LIQUIDATION_MAX_STABLECOIN_RESERVE_DEPLOYMENT`
+- `MOCK_LIQUIDATION_MIN_STABLECOIN_RESERVE_BALANCE`
+- `MOCK_LIQUIDATION_MAX_COLLATERAL_ALLOCATION`
+- `MOCK_LIQUIDATION_MAX_PARTIAL_DEBT_REPAYMENT`
+- `MOCK_LIQUIDATION_DEFENSIVE_ACTION_SEQUENCING_PREFERENCE`
+- `MOCK_LIQUIDATION_PREFERRED_VENUES`
+
+The local mock server for this project only exposes routes under `/liquidation/*`.
+
+**Quick navigation:**
-### Getting Started with TypeScript
+- [TypeScript Quick Start](#typescript-quick-start)
+- [Go Quick Start](#go-quick-start)
-
+## TypeScript Quick Start
+
+1. Install dependencies
```bash
-git clone https://github.com/smartcontractkit/cre-templates.git
-cd cre-templates/starter-templates/confidential-workflows/automated-liquidation-protection
bun install
```
-
-
-
+2. Create environment file
```bash
cp .env.example .env
```
-Provide values for the required environment variables:
+3. Start mock server
-- `CRE_ETH_PRIVATE_KEY` (optional for local simulate)
-- `MOCK_PORT`, `MOCK_EXCHANGE_API_KEY`, `MOCK_OPENAI_API_KEY`
-- `MOCK_LIQUIDATION_WARNING_ACTION_THRESHOLD`, `MOCK_LIQUIDATION_MINIMUM_HEALTH_FACTOR`, `MOCK_LIQUIDATION_TARGET_HEALTH_FACTOR`
-- `MOCK_LIQUIDATION_MAX_STABLECOIN_RESERVE_DEPLOYMENT`, `MOCK_LIQUIDATION_MIN_STABLECOIN_RESERVE_BALANCE`, `MOCK_LIQUIDATION_MAX_COLLATERAL_ALLOCATION`
-- `MOCK_LIQUIDATION_MAX_PARTIAL_DEBT_REPAYMENT`, `MOCK_LIQUIDATION_DEFENSIVE_ACTION_SEQUENCING_PREFERENCE`, `MOCK_LIQUIDATION_PREFERRED_VENUES`
-
-`secrets.yaml` maps the exchange and model secret IDs to their environment variables. The local mock server only exposes routes under `/liquidation/*`.
-
-
-
-
-
-Open `automated-liquidation-protection-ts/config.staging.json`:
-
-```json
-{
- "schedule": "0 */5 * * * *",
- "mock_base_url": "http://127.0.0.1:8787/liquidation",
- "openai_url": "http://127.0.0.1:8787/liquidation/v1/responses",
- "openai_model": "gpt-4.1-mini",
- "secrets_ids": {
- "exchange_api_key_id": "exchange_api_key",
- "openai_api_key_id": "openai_api_key"
- }
-}
+```bash
+bun run mock:server
```
-1. Keep the default values if you are using the shared mock server on port `8787`
-2. Update `mock_base_url` and `openai_url` if you are using a different port or host
-3. Keep `secrets_ids` aligned with `secrets.yaml`
-
-
-
-
+4. In another terminal, run checks
```bash
bun run typecheck
bun run test
```
-
-
-
-
-From the project root:
-
-```bash
-bun run mock:server
-```
-
-The server listens on `http://127.0.0.1:8787` and serves this workflow's routes under the `/liquidation/*` namespace — policy, risk state, model responses, and the execution endpoint.
-
-
-
-
-
-In a new terminal, from the project root:
+5. Simulate workflow
```bash
cre workflow simulate ./automated-liquidation-protection-ts --target=staging-settings
```
-The workflow logs each stage (`liquidation-getsecret-ok`, `liquidation-defense-executed`) and returns either `SAFE` or a JSON summary with the status, action count, risk score, and execution ID.
-
-
-
-## Go Implementation
-
-### Getting Started with Go
+## Go Quick Start
-
-
-From the shared project root:
+1. Create environment file (at the shared project root)
```bash
cp ../.env.example ../.env
```
-`../secrets.yaml` maps the same logical secret IDs shown above to these environment variables.
-
-
-
-
-
-```bash
-cd automated-liquidation-protection-go
-go vet ./...
-go test ./...
-```
-
-
-
-
-
-From the `automated-liquidation-protection-go` directory (requires Node or Bun):
+2. Start the mock server (requires Node or Bun)
```bash
bun mock-server.js
```
-
-
-
-
-In a new terminal, from the project root:
+3. In another terminal, run checks
```bash
-cre workflow simulate ./automated-liquidation-protection-go --target=staging-settings
+go vet ./...
+go test ./...
```
-
-
-### Confidentiality Boundary (Go)
-
-The handler is registered with `cre.HandlerInTee`, so it receives a `cre.TeeRuntime` rather than a `cre.Runtime`. Policy secrets are released by the Vault DON directly into the attested enclave and decrypted only when `GetSecret()` runs; HTTP calls go through `client.SendRequestInTee(runtime, ...)`, keeping URLs, headers, and response bodies confidential from node operators. What is not confidential is the workflow binary itself — the logic is provided to the enclave by the Workflow DON and is revealed. `runtime.UsingTheDons()` is a one-way door: anything passed to a capability call there is no longer confidential.
-
-This template logs only non-sensitive markers (`liquidation-getsecret-ok`, action counts), and its tests assert that no secret reaches the logs — but remove the log lines entirely before deploying to production.
-
-## TEE Constraints
-
-The third argument to the TEE handler API declares which enclaves the handler accepts:
+4. Simulate workflow
-```ts
-{
-} // any registered TEE, any region
-{
- regions: ["us-west-2"]
-} // any TEE, restricted to a region
-;[{ tee: "nitro", regions: ["us-west-2"] }] // specific TEE types and regions
-```
-
-```go
-cre.AnyTee{} // any registered TEE, any region
-cre.AnyTeeInRegions{Regions: []cre.Region{cre.AwsUsWest2}} // any TEE, restricted to a region
-cre.OneOfTees{cre.Nitro{Regions: []cre.NitroRegion{cre.NitroUsWest2}}} // specific TEEs and regions
+```bash
+cd .. && cre workflow simulate ./automated-liquidation-protection-go --target=staging-settings
```
-
-AWS Nitro in `us-west-2` is currently the only registered TEE type and region. In Go, each TEE binding owns its own
-region enum, so passing a region a TEE does not support is a compile-time error.
-
-## Configuration
-
-`config.staging.json`:
-
-| Field | Description |
-| --------------- | --------------------------------------------------------- |
-| `schedule` | Cron expression (6 fields, seconds first) |
-| `mock_base_url` | Base URL for the risk-state and execute-defense endpoints |
-| `openai_url` | Reasoning endpoint called from inside the enclave |
-| `openai_model` | Model name passed to the reasoning endpoint |
-| `secrets_ids` | Maps each policy input to a secret ID in `secrets.yaml` |
-
-## Secrets
-
-Both implementations expect these secret IDs in `secrets_ids`:
-
-- `exchange_api_key`
-- `openai_api_key`
-
-## Production Checklist
-
-1. Replace `mock_base_url` with your real risk, policy, and execution service URL
-2. Use a production model endpoint and model in `openai_url` and `openai_model`
-3. Confirm `config.production.json` points to the correct service base URL before deployment
-4. Register production secret values for exchange and model access
-
-## Troubleshooting
-
-- **401 responses from the APIs** usually indicate a secret mismatch between `.env`, `secrets.yaml`, and `secrets_ids` in the config file
-- **Simulation failures tied to RPC config** usually come from incorrect `project.yaml` target values
-- **Model responses that fail to parse** mean your configured endpoint is not returning the expected JSON payload shape — the workflow expects `shouldDefend`, `reasoning`, and `actions`
-
-## Further Reading
-
-- [Confidential Workflows in CRE](https://docs.chain.link/cre/concepts/confidential-workflows) - concepts and use cases
-- [Making a Workflow Confidential](https://docs.chain.link/cre/guides/workflow/using-confidential-workflows) - step-by-step guide
-- [Confidential Workflows Client SDK Reference](https://docs.chain.link/cre/reference/sdk/confidential-workflows-client) - full API
-- [Hello Confidential Workflows](/cre-templates/hello-confidential-workflows) - the minimal version of this pattern
diff --git a/src/content/cre-templates/automated-portfolio-rebalancing.mdx b/src/content/cre-templates/automated-portfolio-rebalancing.mdx
index 5793304a61a..9168c3ccd6e 100644
--- a/src/content/cre-templates/automated-portfolio-rebalancing.mdx
+++ b/src/content/cre-templates/automated-portfolio-rebalancing.mdx
@@ -23,7 +23,7 @@ datePublished: "2026-08-04"
lastModified: "2026-08-06"
---
-import { Aside, Accordion } from "@components"
+import { Aside } from "@components"
-This workflow runs inside a **Trusted Execution Environment (TEE)** and generates policy-constrained rebalance
-trades when allocation drift exceeds the configured threshold. Holdings, prices, and target allocations never
-leave the confidential runtime. The TypeScript and Go implementations are behaviorally equivalent - pick whichever
-language you build in.
+This standalone CRE project implements a confidential portfolio rebalancing workflow for crypto allocations.
-**Quick navigation:**
+## Description
-- [TypeScript Implementation](#typescript-implementation)
-- [Go Implementation](#go-implementation)
+The workflow continuously tracks allocation drift and triggers rebalancing when policy thresholds are exceeded. It
+is designed to restore user-defined target weights while protecting sensitive operational inputs, including
+exchange credentials, model credentials, policy thresholds, and execution preferences inside confidential execution.
----
+## Target Customer
-## What This Template Does
+- Professional retail traders
+- Developer shops
+- Founders building trading products
-On every cron execution the workflow:
+## Structure
-1. Fetches the exchange and model API secrets from the CRE secrets store
-2. Reads **policy**, **holdings**, **prices**, and a **volatility index**
-3. Computes per-asset **allocation drift** against the target weights
-4. Asks an LLM for **trade proposals**
-5. Enforces slippage, reserve-floor, and max-trade-size constraints
-6. Chunks oversized trades and routes each chunk to a preferred venue
-7. Executes the approved trade plan through an execution endpoint
+- `project.yaml`: project-level target settings
+- `secrets.yaml`: secret ID mappings used by the workflow
+- `mock-server.js`: local deterministic API server
+- `automated-portfolio-rebalancing-ts/`: TypeScript workflow implementation
+- `automated-portfolio-rebalancing-go/`: Go workflow implementation
-If no asset has drifted past the threshold, the workflow returns without trading.
+## Private Inputs
-
+The following inputs are handled as confidential:
-## Policy Constraints
+- Exchange API credentials used to read holdings, reserve data, and execution context, including stablecoin reserve depth and cash balance.
+- LLM reasoning API credentials.
+- Portfolio policy settings such as target allocation mix, minimum drift threshold, maximum trade size per execution, and required stablecoin reserve floor.
+- Execution preferences such as venue priority, slippage limits, and trade chunking/ordering behavior.
-The policy is fetched at runtime and bounds every trade the model is allowed to propose:
+## Workflow Notes
-- `target_allocations` — target weight per symbol
-- `drift_threshold_pct` — minimum drift required before rebalancing runs at all
-- `max_trade_usd` — maximum notional per trade; larger trades are split into chunks
-- `reserve_floor_usdc` — USDC reserve that must remain untouched
-- `max_slippage_bps` — slippage ceiling applied to every trade
-- `preferred_venues` — venue allowlist used when routing each chunk
+1. Monitor portfolio state.
+ The workflow gathers market prices, current asset weights, drift from target allocations, reserve health, and volatility signals.
+2. Enforce user-defined portfolio constraints.
+ Confidential reasoning validates weight constraints, drift triggers, rebalance sizing limits, reserve protection requirements, and slippage controls.
+3. Build a rebalance action plan.
+ The plan can include buying underweight assets, selling overweight assets, enforcing reserve floors, capping per-trade notionals, and optimizing execution through chunking and smart venue routing.
+4. Execute rebalance actions across venues.
+ Depending on route selection, the workflow can execute both on-chain operations (such as swaps) and off-chain operations (such as centralized exchange API trades).
-
+Note: Reasoning stages can be implemented with deterministic rule-based logic instead of an LLM when a fully rules-driven execution model is preferred.
-## Prerequisites
+## Required Environment Variables
-- **[Bun](https://bun.com/docs/installation)** — used to install dependencies and to run the shared mock server (both languages)
-- **[Go](https://go.dev/dl/) 1.25 or later** — only if you are building the Go implementation
-- **[Chainlink CRE CLI](https://docs.chain.link/cre/getting-started/cli-installation)** installed and configured
-- **Git** for cloning the repository
+Copy `.env.example` to `.env` and provide values for:
-`automated-portfolio-rebalancing/` is a single CRE project shared by both languages — `project.yaml`, `secrets.yaml`, and `.env.example` live at the project root, with `automated-portfolio-rebalancing-ts/` and `automated-portfolio-rebalancing-go/` as sibling workflow directories underneath it.
+- `CRE_ETH_PRIVATE_KEY` (optional for local simulate)
+- `MOCK_PORT`
+- `MOCK_EXCHANGE_API_KEY`
+- `MOCK_OPENAI_API_KEY`
+- `MOCK_REBALANCING_TARGET_ALLOCATION_BTC_PCT`
+- `MOCK_REBALANCING_TARGET_ALLOCATION_ETH_PCT`
+- `MOCK_REBALANCING_TARGET_ALLOCATION_USDC_PCT`
+- `MOCK_REBALANCING_DRIFT_THRESHOLD_PCT`
+- `MOCK_REBALANCING_MAX_TRADE_USD`
+- `MOCK_REBALANCING_RESERVE_FLOOR_USDC`
+- `MOCK_REBALANCING_MAX_SLIPPAGE_BPS`
+- `MOCK_REBALANCING_PREFERRED_VENUES`
+- `MOCK_REBALANCING_ORDER_SEQUENCE_PREFERENCE`
+
+The local mock server for this project only exposes routes under `/rebalancing/*`.
+
+**Quick navigation:**
-## TypeScript Implementation
+- [TypeScript Quick Start](#typescript-quick-start)
+- [Go Quick Start](#go-quick-start)
-### Getting Started with TypeScript
+## TypeScript Quick Start
-
+1. Install dependencies
```bash
-git clone https://github.com/smartcontractkit/cre-templates.git
-cd cre-templates/starter-templates/confidential-workflows/automated-portfolio-rebalancing
bun install
```
-
-
-
+2. Create environment file
```bash
cp .env.example .env
```
-Provide values for the required environment variables:
+3. Start mock server
-- `CRE_ETH_PRIVATE_KEY` (optional for local simulate)
-- `MOCK_PORT`, `MOCK_EXCHANGE_API_KEY`, `MOCK_OPENAI_API_KEY`
-- `MOCK_REBALANCING_TARGET_ALLOCATION_BTC_PCT`, `MOCK_REBALANCING_TARGET_ALLOCATION_ETH_PCT`, `MOCK_REBALANCING_TARGET_ALLOCATION_USDC_PCT`
-- `MOCK_REBALANCING_DRIFT_THRESHOLD_PCT`, `MOCK_REBALANCING_MAX_TRADE_USD`, `MOCK_REBALANCING_RESERVE_FLOOR_USDC`
-- `MOCK_REBALANCING_MAX_SLIPPAGE_BPS`, `MOCK_REBALANCING_PREFERRED_VENUES`, `MOCK_REBALANCING_ORDER_SEQUENCE_PREFERENCE`
-
-`secrets.yaml` maps the exchange and model secret IDs to their environment variables. The local mock server only exposes routes under `/rebalancing/*`.
-
-
-
-
-
-Open `automated-portfolio-rebalancing-ts/config.staging.json`:
-
-```json
-{
- "schedule": "0 */5 * * * *",
- "mock_base_url": "http://127.0.0.1:8787/rebalancing",
- "openai_url": "http://127.0.0.1:8787/rebalancing/v1/responses",
- "openai_model": "gpt-4.1-mini",
- "secrets_ids": {
- "exchange_api_key_id": "exchange_api_key",
- "openai_api_key_id": "openai_api_key"
- }
-}
+```bash
+bun run mock:server
```
-1. Keep the default values if you are using the shared mock server on port `8787`
-2. Update `mock_base_url` and `openai_url` if you are using a different port or host
-3. Keep `secrets_ids` aligned with `secrets.yaml`
-
-
-
-
+4. In another terminal, run checks
```bash
bun run typecheck
bun run test
```
-
-
-
-
-From the project root:
-
-```bash
-bun run mock:server
-```
-
-The server listens on `http://127.0.0.1:8787` and serves this workflow's routes under the `/rebalancing/*` namespace — portfolio, prices, volatility, policy, model responses, and the execution endpoint.
-
-
-
-
-
-In a new terminal, from the project root:
+5. Simulate workflow
```bash
cre workflow simulate ./automated-portfolio-rebalancing-ts --target=staging-settings
```
-The workflow logs each stage (`rebalance-executed`) and returns a JSON summary with the status, trade count, maximum drift percentage, and execution ID.
-
-
+## Go Quick Start
-## Go Implementation
-
-### Getting Started with Go
-
-
-
-From the shared project root:
+1. Create environment file (at the shared project root)
```bash
cp ../.env.example ../.env
```
-`../secrets.yaml` maps the same logical secret IDs shown above to these environment variables.
-
-
-
-
-
-```bash
-cd automated-portfolio-rebalancing-go
-go vet ./...
-go test ./...
-```
-
-
-
-
-
-From the `automated-portfolio-rebalancing-go` directory (requires Node or Bun):
+2. Start the mock server (requires Node or Bun)
```bash
bun mock-server.js
```
-
-
-
-
-In a new terminal, from the project root:
+3. In another terminal, run checks
```bash
-cre workflow simulate ./automated-portfolio-rebalancing-go --target=staging-settings
+go vet ./...
+go test ./...
```
-
-
-### Confidentiality Boundary (Go)
-
-The handler is registered with `cre.HandlerInTee`, so it receives a `cre.TeeRuntime` rather than a `cre.Runtime`. Policy secrets are released by the Vault DON directly into the attested enclave and decrypted only when `GetSecret()` runs; HTTP calls go through `client.SendRequestInTee(runtime, ...)`, keeping URLs, headers, and response bodies confidential from node operators. What is not confidential is the workflow binary itself — the logic is provided to the enclave by the Workflow DON and is revealed. `runtime.UsingTheDons()` is a one-way door: anything passed to a capability call there is no longer confidential.
-
-This template logs only non-sensitive markers (`rebalance-getsecret-ok`, trade counts), and its tests assert that no secret reaches the logs — but remove the log lines entirely before deploying to production.
-
-
-
-## TEE Constraints
-
-The third argument to the TEE handler API declares which enclaves the handler accepts:
+4. Simulate workflow
-```ts
-{
-} // any registered TEE, any region
-{
- regions: ["us-west-2"]
-} // any TEE, restricted to a region
-;[{ tee: "nitro", regions: ["us-west-2"] }] // specific TEE types and regions
-```
-
-```go
-cre.AnyTee{} // any registered TEE, any region
-cre.AnyTeeInRegions{Regions: []cre.Region{cre.AwsUsWest2}} // any TEE, restricted to a region
-cre.OneOfTees{cre.Nitro{Regions: []cre.NitroRegion{cre.NitroUsWest2}}} // specific TEEs and regions
+```bash
+cd .. && cre workflow simulate ./automated-portfolio-rebalancing-go --target=staging-settings
```
-
-AWS Nitro in `us-west-2` is currently the only registered TEE type and region. In Go, each TEE binding owns its own
-region enum, so passing a region a TEE does not support is a compile-time error.
-
-## Configuration
-
-`config.staging.json`:
-
-| Field | Description |
-| --------------- | ----------------------------------------------------------------------- |
-| `schedule` | Cron expression (6 fields, seconds first) |
-| `mock_base_url` | Base URL for the portfolio, prices, volatility, and execution endpoints |
-| `openai_url` | Reasoning endpoint called from inside the enclave |
-| `openai_model` | Model name passed to the reasoning endpoint |
-| `secrets_ids` | Maps each policy input to a secret ID in `secrets.yaml` |
-
-## Secrets
-
-Both implementations expect these secret IDs in `secrets_ids`:
-
-- `exchange_api_key`
-- `openai_api_key`
-
-## Production Checklist
-
-1. Replace `mock_base_url` with your real policy, market, and execution service URL
-2. Use a production model endpoint and model in `openai_url` and `openai_model`
-3. Confirm `config.production.json` points to the correct service base URL before deployment
-4. Register production secret values for exchange and model access
-
-## Troubleshooting
-
-- **401 responses from the APIs** usually indicate a secret mismatch between `.env`, `secrets.yaml`, and `secrets_ids` in the config file
-- **Simulation failures tied to RPC config** usually come from incorrect `project.yaml` target values
-- **Model responses that fail to parse** mean your configured endpoint is not returning the expected JSON payload shape — the workflow expects `shouldRebalance`, `reasoning`, and `trades`
-
-## Further Reading
-
-- [Confidential Workflows in CRE](https://docs.chain.link/cre/concepts/confidential-workflows) - concepts and use cases
-- [Making a Workflow Confidential](https://docs.chain.link/cre/guides/workflow/using-confidential-workflows) - step-by-step guide
-- [Confidential Workflows Client SDK Reference](https://docs.chain.link/cre/reference/sdk/confidential-workflows-client) - full API
-- [Hello Confidential Workflows](/cre-templates/hello-confidential-workflows) - the minimal version of this pattern
diff --git a/src/content/cre-templates/hello-confidential-workflows.mdx b/src/content/cre-templates/hello-confidential-workflows.mdx
index b68a7ceecbe..a9f30f62578 100644
--- a/src/content/cre-templates/hello-confidential-workflows.mdx
+++ b/src/content/cre-templates/hello-confidential-workflows.mdx
@@ -45,11 +45,11 @@ result back to the Workflow DON for consensus-backed operations.
## What This Template Does
By default, a CRE workflow callback runs on Workflow DON nodes, where node operators can inspect what it is computing.
-That is acceptable for many workflows, but not for logic where the policy, model, or threshold itself is sensitive.
+That is acceptable for many workflows, but not for when sensitive or proprietary data is required for workflows.
-A **[Confidential Workflow](https://docs.chain.link/cre/concepts/confidential-workflows)** moves that sensitive part
-into a hardware-isolated [enclave](https://docs.chain.link/cre/key-terms#enclave). This template demonstrates the
-minimal end-to-end shape in four steps:
+A **[Confidential Workflow](https://docs.chain.link/cre/concepts/confidential-workflows)** executes the logic
+requiring confidential inputs in a hardware-isolated [enclave](https://docs.chain.link/cre/key-terms#enclave).
+This template demonstrates the minimal end-to-end shape in four steps:
| Step | What it demonstrates | API |
| ---- | ---------------------------------------------------- | --------------------------------------------------- |
@@ -66,27 +66,27 @@ minimal end-to-end shape in four steps:
└──────┬───────┘
│ DON hands the triggered request to an enclave
v
-╔══════════════════════════════════════════════════════════════╗
-║ ENCLAVE (TEE - hidden from node operators) ║
-║ ║
-║ Step 2: runtime.getSecret({ id: 'API_TOKEN' }) ║
-║ ▲ ║
-║ └──── released by Vault DON, decrypted in-enclave║
-║ ║
-║ Step 3: HTTPClient.sendRequest(runtime, { ... }) ║
-║ Authorization: Bearer ║
-║ ▲ trust from enclave attestation, not consensus ║
-║ ║
-║ Confidential logic: score(response) vs. scoreThreshold ║
-║ -> verdict = APPROVE | REJECT ║
-╚═══════════════════════════╤══════════════════════════════════╝
- │ Step 4: runtime.usingTheDons()
- │ ONLY the verdict + score cross out
- v
-┌──────────────────────────────────────────────────────────────┐
-│ WORKFLOW DON - donRuntime.report({ ... }) │
-│ BFT consensus verifies the enclave attestation, then signs │
-└──────────────────────────────────────────────────────────────┘
+╔══════════════════════════════════════════════════════════════════════╗
+║ ENCLAVE ║
+║ ║
+║ Step 2: runtime.getSecret({ id: 'API_TOKEN' }) ║
+║ ▲ ║
+║ └── released by Vault DON, decrypted in-enclave ║
+║ ║
+║ Step 3: HTTPClient.sendRequest(runtime, { ... }) ║
+║ Authorization: Bearer ║
+║ ▲ trust from enclave attestation, not consensus ║
+║ ║
+║ Logic with confidential data: score(response) vs. scoreThreshold ║
+║ -> verdict = APPROVE | REJECT ║
+╚═══════════════════════════╤══════════════════════════════════════════╝
+ │ Step 4: runtime.usingTheDons()
+ │ ONLY the verdict + score cross out
+ v
+┌──────────────────────────────────────────────────────────────────────┐
+│ WORKFLOW DON - donRuntime.report({ ... }) │
+│ BFT consensus verifies the enclave attestation, then signs │
+└──────────────────────────────────────────────────────────────────────┘
```
## How It Works
@@ -290,16 +290,16 @@ Understanding what is and is not protected matters more here than in a regular w
Consequences worth internalizing:
-- **Your source and binary are readable.** If the logic itself is the secret, make sure it actually executes inside
- the enclave - do not rely on the binary being opaque, because it is not.
+- **Your handler’s source code and compiled binary are not confidential just because part of its logic runs inside an enclave.** Confidential Workflows protect only the
+ confidential data processed during execution inside the enclave, including Vault DON secrets (such as API keys), HTTP response, and intermediate values that are not
+ explicitly shared outside the enclave. Support for confidential logic or workflow is planned as a future enhancement, not part of the current beta.
- **`usingTheDons()` is a one-way door.** Anything you pass into a capability call on that runtime executes on
Workflow DON nodes like any non-confidential call. Cross over only what does not need to stay hidden.
- **Do not log from inside the enclave in production.** Logs leave the confidentiality boundary. This template logs
only the verdict, and the comment marks it for removal before deploying.
- **Keep enclave logic deterministic.** The enclave result is attested and verified by DON consensus.
-- **Enclaves are not tenant-isolated today.** A single enclave can run confidential workflows from multiple customers
- concurrently, sharing execution memory. Isolation between confidential executions is planned, not part of the
- current beta.
+- **Multiple confidential workflows may execute within the same enclave.** Workflows are isolated from one another by the wasmtime. Dedicated per workflow enclave
+ isolation is planned as a future enhancement.
## Which Secrets Belong in an Enclave?
diff --git a/src/pages/cre-templates/index.astro b/src/pages/cre-templates/index.astro
index 085f5f70795..953a0b03db6 100644
--- a/src/pages/cre-templates/index.astro
+++ b/src/pages/cre-templates/index.astro
@@ -3,8 +3,8 @@ import { getCollection } from "astro:content"
import BaseLayout from "~/layouts/BaseLayout.astro"
import TemplateCard from "~/components/CRETemplate/TemplateCard.astro"
-const templates = (await getCollection("cre-templates")).sort(
- (a, b) => (b.data.datePublished ?? "").localeCompare(a.data.datePublished ?? "")
+const templates = (await getCollection("cre-templates")).sort((a, b) =>
+ (b.data.datePublished ?? "").localeCompare(a.data.datePublished ?? "")
)
const featuredTemplate = templates.find((t) => t.data.featured)