

What this post is: a short, copy-paste technical walkthrough showing how PR #5 adds a Trust Center widget to the erc-8004-tee-agent UI, how to enable it in a VibeVM (env / docker-compose), and how to test the enabled vs disabled behavior. This guide uses the PR as an example implementation you can run in your Phala Cloud VibeVM.
- Example PR: https://github.com/Phala-Network/erc-8004-tee-agent/pull/5
- Trust Center (widget host): https://trust.phala.com
- Demo video:
TL;DR (30s)
- PR adds a floating Trust Center widget + modal iframe in the frontend and a backend endpoint
/api/trust-center-urlthat returns the configured widget URL (or 404 when disabled). - Enable with an env var:
TRUST_CENTER_URL=https://trust.phala.com/widget/app/<dstack-app-id>. - Test quickly with
curland by loading the app UI — widget appears when enabled, disappears when unset.
Why add a Trust Center widget?
A small in-app widget gives users immediate, discoverable access to attestation/verification information (the Trust Center) without leaving the app. For TEE-backed agents this improves UX and trust signals: users can inspect attestations, key provenance, and governance info directly from the agent UI. The implementation below is designed to be opt-in (env toggle) and minimal attack surface (iframe + backend echo endpoint).
What changed in the PR
Key pieces implemented in PR #5:
- Backend: new route
/api/trust-center-urlthat readsTRUST_CENTER_URLfrom env and returns JSON{ "trust_center_url": "<url>" }when set, or HTTP 404 when not configured. - Frontend:
trust-center.jscomponent that injects a small floating widget; clicking it opens a modal with an iframe pointed at the value returned by/api/trust-center-url. - Config:
.env.exampleupdated withTRUST_CENTER_URLplaceholder;docker-compose.ymlupdated to pass the env through. - UI & CSS: minimal floating control and modal styling.
(See PR: https://github.com/Phala-Network/erc-8004-tee-agent/pull/5)
Quick config & code snippets
.env example (enable the widget)
# enable the Trust Center widget (production/staging)
TRUST_CENTER_URL=https://trust.phala.com/widget/app/<dstack-app-id>
docker-compose.yml excerpt (pass env)
services:
# Other container info
agent:
image: ubuntu:22.04
platform: linux/amd64
container_name: erc8004-agent
environment:
- TRUST_CENTER_URL=${TRUST_CENTER_URL:-https://trust.phala.com/widget/app/${DSTACK_APP_ID}}
# Other env vars and command
ports:
- "8000:8000"
Backend (conceptual Python/Flask snippet)
# /api/trust-center-url
from flask import Flask, jsonify, abort
import os
app = Flask(__name__)
@app.get("/api/trust-center-url")
def trust_center_url():
url = os.getenv("TRUST_CENTER_URL", "").strip()
if not url:
abort(404)
return jsonify({"trust_center_url": url})
Frontend (conceptual widget component)
// trust-center.js (simplified)
async function fetchTrustUrl() {
const res = await fetch("/api/trust-center-url");
if (!res.ok) return null;
const { trust_center_url } = await res.json();
return trust_center_url;
}
async function initTrustWidget() {
const url = await fetchTrustUrl();
if (!url) return; // widget disabled
// render floating button; open modal with <iframe src="{url}" sandbox="allow-scripts allow-same-origin">
}
Keep the iframe sandboxed and enforce a CSP that restricts framing origins to trust.phala.com if possible.
Deploy & reproduce (step-by-step)
- cd into the
erc-8004-tee-agentfolder and apply the changes locally in VibeVM:cd erc-8004-tee-agent git switch feat/trust-center - Enable widget:
cp .env.example .env # edit .env -> set TRUST_CENTER_URL=https://trust.phala.com
- Install dependencies and deploy locally in VibeVM:
pip install -e . python deployment/local_agent_server.py - Verify backend behavior:
- Enabled:
curl -sS http://<dstack-app-id>-8000.<dstack-gateway-domain>/api/trust-center-url # Ex. curl https://6ff54f6770a95e28ed7b9bba1460b09b0f35c0e4-8000.dstack-pha-prod9.phala.network/api/trust-center-url # {"trust_center_url":"https://trust.phala.com/widget/app/6ff54f6770a95e28ed7b9bba1460b09b0f35c0e4"}
- Go to the
TRUST_CENTER_URLin the browser

- Enabled:
- Open the app UI (e.g.,
https://<dstack-app-id>-8000.<dstack-gateway-domain>):- With
TRUST_CENTER_URLset: confirm the floating widget appears. Click it → modal opens an iframe tohttps://trust.phala.com.
- With
TRUST_CENTER_URLunset: widget not present.
- With
- Staging checks:
- Test behind your staging reverse proxy to ensure CSP/frame-ancestors behave correctly.
- Confirm
/api/trust-center-urlonly echoes a server-side configuration value — never accept or render arbitrary client-supplied URLs.
Security & UX checklist (short)
- Iframe sandbox: use
sandboxattribute (allow-scriptsonly if necessary) and avoidallow-top-navigation. - CSP: add
frame-ancestors 'self' https://trust.phala.comand other header protections. - Server-side control: the endpoint must only return the configured URL; do not accept a query param or request body URL.
- Privacy: Trust Center pages should not capture or leak user tokens; the widget is a navigational/trust surface, not a data channel.
Test matrix (quick)
- Unit: endpoint returns JSON when set; 404 when empty.
- Integration: widget renders when endpoint returns URL.
- Manual: click widget → iframe loads
trust.phala.comand presents attestation UI.
Resources & next steps
- PR: https://github.com/Phala-Network/erc-8004-tee-agent/pull/5 — review, fetch, and test locally.
- Deploy a VibeVM: https://cloud.phala.network/templates/VibeVM
- Trust Center: https://trust.phala.com (use this as
TRUST_CENTER_URL). - Demo video: https://youtu.be/xEM3oIeAVtU — step-through of the change and verification.
Call to action: Add more trust to your agents and enable the Trust Center widget in your VibeVM, run the tests above.