* fix(plugin-sdk): export declare global types through package dependency Rename globals.d.ts to globals.ts so vite-plugin-dts emits it to dist/, preserving the declare global block. Remove rollupTypes which silently dropped global type augmentations. This lets ts-plugin-sample resolve plugin API globals (div, button, prove, etc.) through @tlsn/plugin-sdk instead of a fragile relative path into the monorepo. * refactor(plugin-sdk): add lightweight types entry point for plugins Add a separate '/types' entry point exporting only enums and interfaces, so plugins can import HandlerType/HandlerPart/HandlerAction without pulling in the full SDK (Host, QuickJS, logger). Update ts-plugin-sample to import from '@tlsn/plugin-sdk/types', reducing its build output size and eliminating bundled logger code. Also fix ./src/types backward-compat export to point to the new lightweight dist/types.js instead of the full dist/index.js. * refactor(plugin-sdk): replace Handler enums with string union types HandlerType, HandlerPart, and HandlerAction are now string unions instead of TypeScript enums, eliminating runtime code and allowing plugins to use plain string literals without any SDK runtime import. * refactor(plugin-sdk): remove unused /types entry point The separate types entry was added for enum runtime imports, but enums have been replaced with string unions that need no runtime import. Remove the empty chunk and simplify to two entries. * fix(ts-plugin-sample): cache auth headers in state to avoid re-extraction Port header caching pattern from demo plugin: extract and cache header values individually in state on first detection, read from cache in onClick, and only include optional headers when present. * feat(ts-plugin-sample): derive output filename from package.json name Output filename is now derived from the package.json "name" field with @scope/ stripped (e.g. @tlsn/ts-plugin-sample → ts-plugin-sample.js). The dev script now reuses build-wrapper.cjs --watch instead of an inline esbuild command. * refactor(demo): convert plugins to typed TypeScript with esbuild build Replace Vite-based plugin build with esbuild (same approach as ts-plugin-sample). Add proper SDK type imports, type annotations, and satisfies checks to all 4 demo plugins. Add shared tsconfig.json for plugin type checking. * fix(demo): remove @tlsn/plugin-sdk from devDependencies for Docker compat The workspace package can't resolve in isolated Docker builds. Since esbuild strips import type without resolving, and the monorepo workspace hoisting handles local type checking, the explicit dependency is unnecessary. * fix(extension): single wildcard should not match across path segments URLPattern API treats * as a full wildcard matching across / segments. Replace with regex approach where * matches a single segment ([^/]*) and ** matches across multiple segments (.*).
TLSN Extension Monorepo
A Chrome Extension for TLSNotary with plugin SDK and verifier server.
Important
When running the extension against a notary server, please ensure that the server's version is the same as the version of this extension.
Table of Contents
- Monorepo Structure
- Architecture Overview
- Getting Started
- Development
- Production Build
- End-to-End Testing
- Running the Demo
- Websockify Integration
- Publishing
- License
Monorepo Structure
This repository is organized as an npm workspaces monorepo with six main packages:
tlsn-extension/
├── packages/
│ ├── extension/ # Chrome Extension (Manifest V3)
│ │ ├── src/
│ │ │ ├── entries/
│ │ │ │ ├── Background/ # Service worker for extension logic
│ │ │ │ ├── Content/ # Content scripts injected into pages
│ │ │ │ ├── DevConsole/ # Developer Console with code editor
│ │ │ │ ├── Popup/ # Extension popup UI (optional)
│ │ │ │ └── Offscreen/ # Offscreen document for DOM operations
│ │ │ ├── manifest.json
│ │ │ └── utils/
│ │ ├── webpack.config.js
│ │ └── package.json
│ │
│ ├── plugin-sdk/ # SDK for developing TLSN plugins
│ │ ├── src/
│ │ ├── examples/
│ │ └── package.json
│ │
│ ├── common/ # Shared utilities (logging system)
│ │ ├── src/
│ │ │ └── logger/ # Centralized logging with configurable levels
│ │ └── package.json
│ │
│ ├── verifier/ # Rust-based verifier server
│ │ ├── src/
│ │ │ └── main.rs # Server setup, routing, and verification
│ │ ├── config.yaml # Webhook configuration
│ │ └── Cargo.toml
│ │
│ ├── demo/ # Demo server with Docker setup
│ │ ├── *.js # Example plugin files
│ │ └── docker-compose.yml # Docker services configuration
│ │
│ ├── tutorial/ # Tutorial examples
│ │ └── *.js # Tutorial plugin files
│ │
│ └── tlsn-wasm-pkg/ # Pre-built TLSN WebAssembly package
│ └── (WASM binaries)
│
├── package.json # Root workspace configuration
└── README.md
Package Details
1. extension - Chrome Extension (Manifest V3)
A browser extension that enables TLSNotary functionality with the following key features:
- Multi-Window Management: Track multiple browser windows with request interception
- Developer Console: Interactive code editor for writing and testing TLSN plugins
- Request Interception: Capture HTTP/HTTPS requests from managed windows
- Plugin Execution: Run sandboxed JavaScript plugins using QuickJS
- TLSN Overlay: Visual display of intercepted requests
Key Entry Points:
Background: Service worker for extension logic, window management, and message routingContent: Scripts injected into pages for communication and overlay displayDevConsole: Code editor page accessible via right-click context menuPopup: Optional extension popup UIOffscreen: Background DOM operations for service worker limitations
2. plugin-sdk - Plugin Development SDK
SDK for developing and running TLSN WebAssembly plugins with QuickJS sandboxing:
- Secure JavaScript execution in isolated WebAssembly environment
- Host capability system for controlled plugin access
- React-like hooks:
useHeaders(),useRequests(),useEffect(),useState(),setState() - Isomorphic package for Node.js and browser environments
- TypeScript support with full type declarations
3. common - Shared Utilities
Centralized logging system used across packages:
- Configurable log levels:
DEBUG,INFO,WARN,ERROR - Timestamped output with level prefixes
- Singleton pattern for consistent logging across modules
4. verifier - Verifier Server
Rust-based HTTP/WebSocket server for TLSNotary verification:
- Health check endpoint (
GET /health) - Session creation endpoint (
WS /session) - WebSocket verification endpoint (
WS /verifier?sessionId=<id>) - WebSocket proxy endpoint (
WS /proxy?token=<host>) - compatible with notary.pse.dev - Webhook API for POST notifications to external services
- YAML configuration for webhook endpoints (
config.yaml) - CORS enabled for cross-origin requests
- Runs on
localhost:7047by default
5. demo - Demo Server
Docker-based demo environment with:
- Pre-configured example plugins (Twitter, SwissBank)
- React + Vite frontend with environment-based configuration
- Docker Compose setup with verifier and nginx
- Configurable verifier URLs via
.envfiles or Docker build args
6. tlsn-wasm-pkg - TLSN WebAssembly Package
Pre-built WebAssembly binaries for TLSNotary functionality in the browser.
Architecture Overview
Extension Architecture
The extension uses a message-passing architecture with five main entry points:
┌─────────────────────────────────────────────────────────────┐
│ Browser Extension │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Background │◄────►│ Content │◄──── Page Scripts │
│ │ (SW) │ │ Script │ │
│ └──────┬───────┘ └──────────────┘ │
│ │ │
│ ├─► Window Management (WindowManager) │
│ ├─► Request Interception (webRequest API) │
│ ├─► Session Management (SessionManager) │
│ └─► Message Routing │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ DevConsole │ │ Offscreen │ │
│ │ (Editor) │ │ (Background)│ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌──────────────┐
│ Verifier │
│ Server │
│ (localhost: │
│ 7047) │
└──────────────┘
Message Flow
Opening a Managed Window:
Page → window.tlsn.open(url)
↓ window.postMessage(TLSN_OPEN_WINDOW)
Content Script → event listener
↓ browser.runtime.sendMessage(OPEN_WINDOW)
Background → WindowManager.registerWindow()
↓ browser.windows.create()
↓ Returns window info with UUID
Request Interception:
Browser → HTTP request in managed window
↓ webRequest.onBeforeRequest
Background → WindowManager.addRequest()
↓ browser.tabs.sendMessage(UPDATE_TLSN_REQUESTS)
Content Script → Update TLSN overlay UI
Getting Started
Prerequisites
- Node.js >= 18
- Rust (for verifier server) - Install from rustup.rs
- Chrome/Chromium browser
Installation
- Clone the repository:
git clone https://github.com/tlsnotary/tlsn-extension.git
cd tlsn-extension
- Install all dependencies:
npm install
This installs dependencies for all packages in the monorepo and automatically sets up workspace links between packages.
Development
Running the Extension in Development Mode
- Start the development server:
npm run dev
This automatically builds all dependencies (common, plugin-sdk) and then starts webpack-dev-server on port 3000 with hot module replacement. Files are written to packages/extension/build/.
-
Load the extension in Chrome:
- Navigate to
chrome://extensions/ - Enable "Developer mode" toggle (top right)
- Click "Load unpacked"
- Select the
packages/extension/build/folder
- Navigate to
-
The extension will auto-reload on file changes (manual refresh needed for manifest changes).
Running the Verifier Server
The verifier server is required for E2E testing. Run it in a separate terminal:
cd packages/verifier
cargo run
The server will start on http://localhost:7047.
Verifier API Endpoints:
GET /health- Health checkWS /session- Create new verification sessionWS /verifier?sessionId=<id>- WebSocket verification endpointWS /proxy?token=<host>- WebSocket proxy for TLS connections (compatible with notary.pse.dev)
Webhook Configuration:
Configure packages/verifier/config.yaml to receive POST notifications after successful verifications:
webhooks:
"api.x.com":
url: "https://your-backend.example.com/webhook/twitter"
headers:
Authorization: "Bearer your-secret-token"
"*": # Wildcard for unmatched server names
url: "https://your-backend.example.com/webhook/default"
Package-Specific Development
Extension:
cd packages/extension
npm run dev # Development mode
npm run test # Run tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
npm run lint # Lint check
npm run lint:fix # Auto-fix linting issues
Plugin SDK:
cd packages/plugin-sdk
npm run build # Build SDK
npm run test # Run tests
npm run lint # Run all linters
npm run lint:fix # Auto-fix issues
Note: The plugin-SDK builds automatically when the extension is built, so manual building is usually not necessary.
Verifier:
cd packages/verifier
cargo run # Development mode
cargo build --release # Production build
cargo test # Run tests
Production Build
Build Extension for Production
From the repository root:
NODE_ENV=production npm run build
This automatically:
- Builds dependencies (
@tlsn/commonand@tlsn/plugin-sdk) - Builds the extension with production optimizations
- Creates:
- Optimized build in
packages/extension/build/ - Packaged extension in
packages/extension/zip/extension-{version}.zip
- Optimized build in
The zip file is ready for Chrome Web Store submission.
Alternative build commands:
npm run build:extension- Build only the extension (assumes dependencies are built)npm run build:deps- Build only the dependencies
Build All Packages
npm run build:all
This builds all packages in the monorepo (extension, plugin-sdk).
Build Verifier for Production
cd packages/verifier
cargo build --release
The binary will be in target/release/.
End-to-End Testing
To test the complete TLSN workflow:
1. Start the Verifier Server
In a terminal:
cd packages/verifier
cargo run
Verify it's running:
curl http://localhost:7047/health
# Should return: ok
2. Start the Extension in Development Mode
In another terminal:
npm run dev
Load the extension in Chrome (see Getting Started).
3. Open the Developer Console
- Right-click anywhere on any web page
- Select "Developer Console" from the context menu
- A new tab will open with the code editor
4. Run a Test Plugin
The Developer Console comes with a default X.com profile prover plugin. To test:
- Ensure the verifier is running on
localhost:7047 - Review the default code in the editor (or modify as needed)
- Click "▶️ Run Code" button
- The plugin will:
- Open a new window to X.com
- Intercept requests
- Create a prover connection to the verifier
- Display a UI overlay showing progress
- Execute the proof workflow
Console Output:
- Execution status and timing
- Plugin logs and results
- Any errors encountered
5. Verify Request Interception
When a managed window is opened:
- An overlay appears showing "TLSN Plugin In Progress"
- Intercepted requests are listed in real-time
- Request count updates as more requests are captured
Testing Different Plugins
You can write custom plugins in the Developer Console editor:
// Example: Simple plugin that generates a proof
const config = {
name: 'My Plugin',
description: 'A custom TLSN plugin'
};
async function onClick() {
console.log('Starting proof...');
// Wait for specific headers to be intercepted
const [header] = useHeaders(headers => {
return headers.filter(h => h.url.includes('example.com'));
});
console.log('Captured header:', header);
// Generate proof using unified prove() API
const proof = await prove(
// Request options
{
url: 'https://example.com/api/endpoint',
method: 'GET',
headers: {
'Authorization': header.requestHeaders.find(h => h.name === 'Authorization')?.value,
'Accept-Encoding': 'identity',
'Connection': 'close',
},
},
// Prover options
{
verifierUrl: 'http://localhost:7047',
proxyUrl: 'wss://notary.pse.dev/proxy?token=example.com',
maxRecvData: 16384,
maxSentData: 4096,
handlers: [
{ type: 'SENT', part: 'START_LINE', action: 'REVEAL' },
{ type: 'RECV', part: 'START_LINE', action: 'REVEAL' },
{ type: 'RECV', part: 'BODY', action: 'REVEAL',
params: { type: 'json', path: 'username' } }
]
}
);
console.log('Proof generated:', proof);
done(JSON.stringify(proof));
}
function main() {
const [header] = useHeaders(headers => {
return headers.filter(h => h.url.includes('example.com'));
});
// Open a managed window on first render
useEffect(() => {
openWindow('https://example.com');
}, []);
// Render plugin UI component
return div({}, [
div({}, [header ? 'Ready to prove' : 'Waiting for headers...']),
header ? button({ onclick: 'onClick' }, ['Generate Proof']) : null
]);
}
export default {
main,
onClick,
config,
};
Testing Tips
- Monitor Background Service Worker: Open Chrome DevTools for the background service worker via
chrome://extensions/→ Extension Details → "Inspect views: service worker" - Check Console Logs: Look for WindowManager logs, request interception logs, and message routing logs
- Test Multiple Windows: Try opening multiple managed windows simultaneously (max 10)
- Verifier Connection: Ensure verifier is accessible at
localhost:7047before running proofs
Running the Demo
The demo package provides a complete environment for testing TLSNotary plugins.
Quick Start with Docker
# Start all services (verifier + demo server)
npm run docker:up
# Stop services
npm run docker:down
This starts:
- Verifier server on port 7047
- Demo static files served via nginx on port 80
Manual Demo Setup
# Serve demo files locally
npm run demo
# Open http://localhost:8080 in your browser
Environment Variables
The demo uses .env files for configuration:
.env- Local development defaults (localhost:7047).env.production- Production settings (verifier.tlsnotary.org, SSL enabled)
For Docker deployments, override via environment variables:
# Local development (default)
npm run docker:up
# Production with custom verifier
VITE_VERIFIER_HOST=verifier.example.com VITE_SSL=true docker compose up --build
Tutorial
# Serve tutorial examples
npm run tutorial
# Open http://localhost:8080 in your browser
Websockify Integration
For WebSocket proxying of TLS connections (optional):
Build Websockify Docker Image
git clone https://github.com/novnc/websockify && cd websockify
./docker/build.sh
Run Websockify
# For X.com
docker run -it --rm -p 55688:80 novnc/websockify 80 api.x.com:443
# For Twitter
docker run -it --rm -p 55688:80 novnc/websockify 80 api.twitter.com:443
This proxies HTTPS connections through WebSocket for browser-based TLS operations.
Publishing
Chrome Web Store
- Create a production build:
NODE_ENV=production npm run build
-
Test the extension thoroughly
-
Upload
packages/extension/zip/extension-{version}.zipto Chrome Web Store Developer Dashboard -
Follow the Chrome Web Store publishing guide
Pre-built Extension
The easiest way to install the TLSN browser extension is from the Chrome Web Store.
Resources
- TLSNotary Documentation
- Webpack Documentation
- Chrome Extension Documentation
- Manifest V3 Migration Guide
- webextension-polyfill
License
This repository is licensed under either of:
at your option.