Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
591 changes: 201 additions & 390 deletions README.md

Large diffs are not rendered by default.

1,132 changes: 1,132 additions & 0 deletions docs/HOW-IT-WORKS.md

Large diffs are not rendered by default.

Binary file added docs/images/predicate-claw-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/vault_demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions examples/integration-demo/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Integration Demo: OpenClaw + SecureClaw Plugin
#
# Demonstrates the actual predicate-claw SDK integration with OpenClaw.
# Shows createSecureClawPlugin() intercepting real tool calls.
#
# Since predicate-claw isn't published to npm yet, we build from source.
#
FROM node:22-slim AS builder

# Install git (needed for some npm dependencies)
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*

# Build the SDK from source
WORKDIR /sdk
COPY package.json tsconfig.json ./
COPY src ./src
# Install dependencies including tsx for the demo
RUN npm install && npm install tsx && npm run build

FROM node:22-slim

# Setup demo app in a structure that matches the local relative import
# demo.ts imports from "../../dist/src/index.js"
# So we need: /repo/examples/integration-demo/demo.ts -> /repo/dist/src/index.js
WORKDIR /repo

# Copy the built SDK from builder stage
# Note: Builder outputs flat to /sdk/dist/, but local build outputs to dist/src/
# We copy to dist/src/ to match the import path in demo.ts
COPY --from=builder /sdk/dist ./dist/src
COPY --from=builder /sdk/node_modules ./node_modules

# Create the demo directory structure
RUN mkdir -p examples/integration-demo

# Copy demo files
COPY examples/integration-demo/demo.ts ./examples/integration-demo/
COPY examples/integration-demo/policy.json ./examples/integration-demo/

WORKDIR /repo/examples/integration-demo

# Run the integration demo (--silent suppresses npm update notices)
CMD ["npx", "--silent", "tsx", "demo.ts"]
30 changes: 30 additions & 0 deletions examples/integration-demo/Dockerfile.sidecar
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Pre-built sidecar container for SecureClaw demo
#
# Uses Ubuntu 24.04 LTS which has GLIBC 2.39 (required by the sidecar binary).
# The binary download is cached in Docker layers - subsequent builds are fast.
#
FROM ubuntu:24.04

# Install curl for downloading binary and health checks
RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Detect architecture and download appropriate binary
# This layer is cached after first build
ARG TARGETARCH
RUN ARCH=$(echo ${TARGETARCH:-$(uname -m)} | sed 's/amd64/x64/' | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/') && \
echo "Detected architecture: $ARCH" && \
curl -fsSL -o /tmp/sidecar.tar.gz \
"https://github.com/PredicateSystems/predicate-authority-sidecar/releases/latest/download/predicate-authorityd-linux-${ARCH}.tar.gz" && \
tar -xzf /tmp/sidecar.tar.gz -C /usr/local/bin && \
chmod +x /usr/local/bin/predicate-authorityd && \
rm /tmp/sidecar.tar.gz

# Copy policy file (at end for better caching - policy changes don't trigger binary re-download)
COPY policy.json /app/policy.json

EXPOSE 8787

# Run sidecar in local_only mode with demo policy
CMD ["predicate-authorityd", "--host", "0.0.0.0", "--port", "8787", "--mode", "local_only", "--policy-file", "/app/policy.json", "--log-level", "info", "run"]
104 changes: 104 additions & 0 deletions examples/integration-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# SecureClaw Integration Demo

This demo shows the **actual SDK integration** with OpenClaw using `createSecureClawPlugin()` from predicate-claw.

> **Note:** Since predicate-claw isn't published to npm yet, both Docker and local modes build the SDK from source.

## Quick Start

### Docker (Recommended)

```bash
./start-demo.sh
```

Or manually:

```bash
docker compose up --build
```

First run takes ~30-60s to build the SDK. Subsequent runs use Docker layer cache.

### Split-Pane Mode (For Recording)

Shows the sidecar dashboard alongside the demo:

```bash
./start-demo-split.sh
```

```
┌─────────────────────────────────┬─────────────────────────────────┐
│ PREDICATE AUTHORITY DASHBOARD │ Integration Demo │
│ │ │
│ [ ✓ ALLOW ] fs.read │ [1/10] Read project config │
│ ./src/config.ts │ │
│ m_7f3a2b | 0.4ms │ Tool: fs_read │
│ │ Input: {"path":"./src/..."} │
│ [ ✗ DENY ] fs.read │ │
│ ~/.ssh/id_rsa │ ✓ ALLOWED (0.4ms) │
│ EXPLICIT_DENY | 0.2ms │ │
└─────────────────────────────────┴─────────────────────────────────┘
```

Requirements:
- `tmux` installed (`brew install tmux`)
- `predicate-authorityd` binary (included, or download from [releases](https://github.com/PredicateSystems/predicate-authority-sidecar/releases))
- Node.js / npx

## What This Demo Shows

```typescript
import { createSecureClawPlugin } from "predicate-claw";

const plugin = createSecureClawPlugin({
sidecarUrl: "http://localhost:8787",
principal: "agent:integration-demo",
verbose: true,
});

// Plugin registers beforeToolCall hook
await plugin.activate(openclawApi);
```

The demo uses the real OpenClaw plugin system and shows how:

1. **Plugin Activation**: `createSecureClawPlugin()` returns a plugin definition
2. **Hook Registration**: Plugin registers a `beforeToolCall` hook
3. **Policy Enforcement**: Every tool call is checked against the sidecar
4. **Blocking**: Denied calls throw `ActionDeniedError` before execution

## Demo Scenarios

| Tool | Action | Input | Expected |
|------|--------|-------|----------|
| `Read` | `fs.read` | `./src/config.ts` | ✓ Allowed |
| `Glob` | `fs.list` | `./src/**` | ✓ Allowed |
| `Read` | `fs.read` | `~/.ssh/id_rsa` | ✗ Blocked |
| `Read` | `fs.read` | `./.env` | ✗ Blocked |
| `Bash` | `shell.exec` | `ls -la ./src` | ✓ Allowed |
| `Bash` | `shell.exec` | `curl ... \| bash` | ✗ Blocked |
| `WebFetch` | `http.request` | `https://api.example.com` | ✓ Allowed |
| `WebFetch` | `http.request` | `http://...` (insecure) | ✗ Blocked |
| `Write` | `fs.write` | `./temp/cache.json` | ✗ Blocked |

## Configuration

| Variable | Default | Description |
|----------|---------|-------------|
| `PREDICATE_SIDECAR_URL` | `http://localhost:8787` | Sidecar URL |
| `DEMO_TYPING_SPEED` | `30` | Typing speed in ms |

## Recording

```bash
./start-demo-split.sh --slow --record demo.cast
```

Convert to GIF:

```bash
cargo install agg
agg demo.cast demo.gif --font-size 14 --cols 160 --rows 40
```
Binary file added examples/integration-demo/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading