From 669aaaff3b7b25e23e9c43b48b2c49df2175be22 Mon Sep 17 00:00:00 2001 From: Emmanuel Jacquier Date: Thu, 6 Aug 2026 15:20:10 -0400 Subject: [PATCH 1/5] Updated hello conf workflow descriptions --- .../hello-confidential-workflows.mdx | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) 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? From 22c005f649b9997953bbb587e8788fc0398c93bd Mon Sep 17 00:00:00 2001 From: Emmanuel Jacquier Date: Thu, 6 Aug 2026 15:41:56 -0400 Subject: [PATCH 2/5] Updated automated portfolio rebalancing template to match github readme --- .../automated-portfolio-rebalancing.mdx | 284 +++++------------- 1 file changed, 70 insertions(+), 214 deletions(-) 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 From aa8940eb66737ba615046588f7b22cee29870824 Mon Sep 17 00:00:00 2001 From: Emmanuel Jacquier Date: Thu, 6 Aug 2026 15:48:59 -0400 Subject: [PATCH 3/5] updated automated-liquidation-protection template to match github --- .../automated-liquidation-protection.mdx | 292 +++++------------- 1 file changed, 72 insertions(+), 220 deletions(-) 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 From 8930d9c8ea28fd861947805f6061021e4fbc0e6d Mon Sep 17 00:00:00 2001 From: Emmanuel Jacquier Date: Thu, 6 Aug 2026 15:54:57 -0400 Subject: [PATCH 4/5] updated ai-audit-firewall template to match github --- .../cre-templates/ai-audit-firewall.mdx | 326 ++++-------------- 1 file changed, 61 insertions(+), 265 deletions(-) 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 From e903c91bc8efe921bca6724b36ce0030f50079ea Mon Sep 17 00:00:00 2001 From: devin distefano Date: Fri, 7 Aug 2026 09:19:59 +0200 Subject: [PATCH 5/5] format fix --- src/pages/cre-templates/index.astro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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)