// pages/docs.jsx

const SIDEBAR_SECTIONS = [
  {
    heading: 'Getting Started',
    items: [
      { id: 'overview',      label: 'Overview' },
      { id: 'installation',  label: 'Installation' },
      { id: 'quickstart',    label: 'Quickstart' },
    ],
  },
  {
    heading: 'Core Concepts',
    items: [
      { id: 'capability-tokens',    label: 'Capability Tokens' },
      { id: 'policy-engine',        label: 'Policy Engine' },
      { id: 'telemetry',            label: 'Telemetry' },
      { id: 'intrusion-detection',  label: 'Intrusion Detection' },
    ],
  },
  {
    heading: 'Framework Integrations',
    items: [
      { id: 'langchain',   label: 'LangChain' },
      { id: 'llamaindex',  label: 'LlamaIndex' },
      { id: 'crewai',      label: 'CrewAI' },
      { id: 'openai',      label: 'OpenAI' },
    ],
  },
  {
    heading: 'Cloud API',
    items: [
      { id: 'authentication', label: 'Authentication' },
      { id: 'execute',        label: 'POST /execute' },
      { id: 'webhooks',       label: 'Webhooks' },
      { id: 'rate-limiting',  label: 'Rate Limiting' },
    ],
  },
  {
    heading: 'Self-Hosting',
    items: [
      { id: 'requirements',    label: 'Requirements' },
      { id: 'firecracker',     label: 'Firecracker Setup' },
      { id: 'configuration',   label: 'Configuration Reference' },
    ],
  },
];

// ── Quickstart code constants ────────────────────────────────

const QUICKSTART_CODE_1 = `# Rust daemon + CLI
cargo install vela-engine

# Python client
pip install vela-agent`;

const QUICKSTART_CODE_2 = `export VELA_TOKEN_SECRET="$(openssl rand -hex 32)"`;

const QUICKSTART_CODE_3 = `vela aegis-generate-token \\
  --allow-file /tmp \\
  --allow-network false \\
  --max-memory-mb 128 \\
  --max-timeout-ms 10000 \\
  --expires-in-seconds 86400 \\
  > /tmp/my-token.json`;

const QUICKSTART_CODE_4_TABS = [
  {
    label: 'With Firecracker', lang: 'bash',
    code: `vela daemon \\
  --rootfs /opt/vela/rootfs.ext4 \\
  --kernel /opt/vela/vmlinux.bin \\
  --pool-size 4`,
  },
  {
    label: 'Without KVM (dev)', lang: 'bash',
    code: `# --no-vm runs as host subprocesses
# All features work identically
vela daemon --no-vm`,
  },
];

const QUICKSTART_CODE_5 = `from aegis_agent import DaemonClient

client = DaemonClient(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/my-token.json",
)

result = client.execute(
    ["python3", "-c", "print(sum(range(1_000_000)))"]
)
print(result.stdout)       # 499999500000
print(result.return_code)  # 0`;

// ── Callout helper ───────────────────────────────────────────

function CalloutBlock({ type, children }) {
  const styles = {
    note:    { bg: 'rgba(56,189,248,0.07)', border: 'rgba(56,189,248,0.2)', color: '#7dd3fc', icon: 'ℹ' },
    tip:     { bg: 'rgba(34,197,94,0.07)',  border: 'rgba(34,197,94,0.2)',  color: '#4ade80', icon: '💡' },
    warning: { bg: 'rgba(245,158,11,0.07)', border: 'rgba(245,158,11,0.2)', color: '#fbbf24', icon: '⚠' },
  };
  const s = styles[type] || styles.note;
  return (
    <div style={{ background: s.bg, border: `1px solid ${s.border}`, borderRadius: 'var(--radius-md)', padding: '0.875rem 1.125rem', margin: '1.25rem 0', color: s.color, fontSize: '0.9rem', lineHeight: 1.65 }}>
      <span style={{ marginRight: '0.5rem' }}>{s.icon}</span>{children}
    </div>
  );
}

// ── Helper: heading with id for TOC scroll ───────────────────

function slugify(text) {
  return text.replace(/[^a-z0-9]+/gi, '-').toLowerCase();
}

function H2({ children }) {
  const id = slugify(typeof children === 'string' ? children : '');
  return <h2 id={id}>{children}</h2>;
}

// ── DOC_PAGES ────────────────────────────────────────────────

const DOC_PAGES = {

  /* ================================================================
     GETTING STARTED — Overview
     ================================================================ */
  'overview': {
    toc: ['What is Vela?', 'Key features', 'Architecture overview', 'How it works', 'Next steps'],
    content: (
      <div className="prose">
        <h1 id={slugify('What is Vela?')}>Overview</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Vela is a secure code-execution runtime purpose-built for AI agents.
          It lets large-language-model agents run arbitrary code — Python scripts, shell commands, data pipelines —
          inside an isolated sandbox that you fully control.
        </p>

        <H2>What is Vela?</H2>
        <p>
          When AI agents generate and execute code on your infrastructure, you face a fundamental tension: the agent needs enough freedom to be useful,
          but unconstrained execution is a security nightmare.  Vela resolves this by wrapping every execution in a Firecracker micro-VM with
          hardware-enforced isolation, fine-grained capability tokens, and a real-time intrusion-detection system — all with sub-200ms cold-start latency.
        </p>
        <p>
          Vela is open source and available on <a href="https://github.com/karnati-praveen/VELA" target="_blank" rel="noopener noreferrer">GitHub</a>.
          It ships as a single <code>vela</code> binary for the daemon/CLI, plus native SDKs for Python and TypeScript.
        </p>

        <H2>Key features</H2>
        <ul>
          <li><strong>Firecracker micro-VM isolation</strong> — each execution runs in its own lightweight VM with a dedicated Linux kernel.</li>
          <li><strong>HMAC capability tokens</strong> — cryptographically signed tokens that control exactly what code may access: network, filesystem, environment variables, execution time.</li>
          <li><strong>Policy engine</strong> — declarative YAML rules for allowed domains, resource ceilings, and syscall filtering.</li>
          <li><strong>Intrusion detection</strong> — real-time behavioural analysis that flags port scans, privilege-escalation attempts, crypto mining, and more.</li>
          <li><strong>Audit logging</strong> — structured JSON logs of every execution for compliance and debugging.</li>
          <li><strong>Framework integrations</strong> — drop-in adapters for LangChain, LlamaIndex, CrewAI, and OpenAI function calling.</li>
          <li><strong>Cloud API</strong> — fully managed REST API so you never need to operate your own infra.</li>
        </ul>

        <H2>Architecture overview</H2>
        <p>
          At a high level Vela consists of three layers:
        </p>
        <CodeBlock lang="text" showDots={false} code={`┌─────────────────────────────────────────────────┐
│  AI Agent  (LangChain / CrewAI / custom code)   │
└──────────────────┬──────────────────────────────┘
                   │  SDK / REST call
┌──────────────────▼──────────────────────────────┐
│  Vela Daemon (velad)                            │
│  ├─ Token validator (HMAC)                      │
│  ├─ Policy engine                               │
│  ├─ VM pool manager                             │
│  └─ Intrusion detection + audit logger          │
└──────────────────┬──────────────────────────────┘
                   │  Firecracker API
┌──────────────────▼──────────────────────────────┐
│  Firecracker micro-VMs  (one per execution)     │
│  └─ Minimal Linux kernel + rootfs               │
└─────────────────────────────────────────────────┘`} />

        <H2>How it works</H2>
        <p>
          A typical execution flow looks like this:
        </p>
        <ol>
          <li>Your AI agent calls <code>client.execute(["python3", "script.py"])</code> via the SDK.</li>
          <li>The Vela daemon validates the attached HMAC capability token, ensuring the agent has permission for the requested resources.</li>
          <li>The policy engine checks the request against your YAML rules (allowed domains, memory limits, etc.).</li>
          <li>A pre-warmed Firecracker micro-VM is pulled from the pool and the command is executed inside it.</li>
          <li>Intrusion detection monitors the execution in real-time; any suspicious activity triggers an alert and optional kill.</li>
          <li>stdout, stderr, exit code, and execution metadata are returned to the agent. A structured audit log entry is written.</li>
        </ol>

        <H2>Next steps</H2>
        <ul>
          <li><a href="#/docs/installation" onClick={e => { e.preventDefault(); navigate('/docs'); window.__velaSetDoc && window.__velaSetDoc('installation'); }}>Install Vela</a> on your machine</li>
          <li>Follow the <a href="#/docs/quickstart" onClick={e => { e.preventDefault(); navigate('/docs'); window.__velaSetDoc && window.__velaSetDoc('quickstart'); }}>Quickstart guide</a> to run your first sandboxed execution</li>
          <li>Read about <a href="#/docs/capability-tokens" onClick={e => { e.preventDefault(); navigate('/docs'); window.__velaSetDoc && window.__velaSetDoc('capability-tokens'); }}>Capability Tokens</a> to understand the permission model</li>
        </ul>
      </div>
    ),
  },

  /* ================================================================
     GETTING STARTED — Installation
     ================================================================ */
  'installation': {
    toc: ['System requirements', 'Install via Cargo', 'Install the Python SDK', 'Install the TypeScript SDK', 'Docker quick-start', 'Verify your installation'],
    content: (
      <div className="prose">
        <h1>Installation</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Install the Vela daemon, CLI, and language SDKs on your system.
        </p>

        <H2>System requirements</H2>
        <ul>
          <li><strong>OS:</strong> Linux (x86_64) — Ubuntu 20.04+, Debian 11+, Amazon Linux 2</li>
          <li><strong>KVM:</strong> Required for Firecracker isolation. Verify with <code>ls /dev/kvm</code></li>
          <li><strong>CPU:</strong> 2+ cores recommended</li>
          <li><strong>RAM:</strong> 512 MB minimum for the daemon; each micro-VM defaults to 128 MB</li>
          <li><strong>Rust toolchain:</strong> 1.75+ (install via <a href="https://rustup.rs" target="_blank" rel="noopener noreferrer">rustup.rs</a>)</li>
        </ul>
        <CalloutBlock type="note">
          On macOS or Windows, use the <code>--no-vm</code> development mode or run inside a Linux VM / WSL2.
          All features except hardware-level isolation work identically.
        </CalloutBlock>

        <H2>Install via Cargo</H2>
        <p>
          The <code>vela-engine</code> crate includes both the daemon (<code>velad</code>) and the CLI (<code>vela</code>):
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Install the Vela daemon + CLI
cargo install vela-engine

# Verify
vela --version
# vela 0.9.4`} />

        <H2>Install the Python SDK</H2>
        <p>
          The Python client library works with Python 3.9 and above:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`pip install vela-agent

# Or with optional LangChain extras
pip install "vela-agent[langchain]"`} />

        <H2>Install the TypeScript SDK</H2>
        <p>
          For Node.js 18+ projects:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`npm install @vela/sdk

# Or with yarn
yarn add @vela/sdk`} />

        <H2>Docker quick-start</H2>
        <p>
          If you prefer containers, the official Docker image bundles the daemon, a minimal rootfs, and a pre-compiled kernel:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`docker run -d --name velad \\
  --device /dev/kvm \\
  -v /tmp/vela:/data \\
  -p 8080:8080 \\
  ghcr.io/karnati-praveen/vela:latest`} />
        <CalloutBlock type="warning">
          The container needs <code>--device /dev/kvm</code> access to launch Firecracker VMs.
          Without it, the daemon falls back to <code>--no-vm</code> mode automatically.
        </CalloutBlock>

        <H2>Verify your installation</H2>
        <p>
          Run the built-in health check to confirm everything is working:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Start the daemon in the background
vela daemon --no-vm &

# Run a quick smoke test
vela exec -- echo "Hello from Vela!"
# Hello from Vela!

# Check daemon status
vela status
# velad v0.9.4 | uptime: 12s | pool: 4/4 ready | mode: no-vm`} />
      </div>
    ),
  },

  /* ================================================================
     GETTING STARTED — Quickstart  (EXISTING CONTENT — preserved)
     ================================================================ */
  'quickstart': {
    toc: ['Prerequisites', 'Step 1: Install Vela', 'Step 2: Set your token secret', 'Step 3: Generate a capability token', 'Step 4: Start the daemon', 'Step 5: Run your first execution', 'Next steps'],
    content: (
      <div className="prose">
        <h1>Quickstart</h1>
        <p style={{ fontSize: '1.0625rem' }}>Run your first sandboxed execution in under 5 minutes.</p>

        <H2>Prerequisites</H2>
        <ul>
          <li>Linux host with KVM support (<code>ls /dev/kvm</code> should exist)</li>
          <li>Rust toolchain (<code>rustup.rs</code>)</li>
          <li>Python 3.9+</li>
          <li>Firecracker binary (see <a href="#/docs/firecracker" onClick={e => e.preventDefault()}>Firecracker setup</a>)</li>
        </ul>
        <CalloutBlock type="note">
          No KVM? Use <code>--no-vm</code> mode to run as host subprocesses. All other features work identically.
        </CalloutBlock>

        <H2>Step 1: Install Vela</H2>
        <CodeBlock code={QUICKSTART_CODE_1} lang="bash" showDots={true} />

        <H2>Step 2: Set your token secret</H2>
        <CodeBlock code={QUICKSTART_CODE_2} lang="bash" showDots={true} />

        <H2>Step 3: Generate a capability token</H2>
        <CodeBlock code={QUICKSTART_CODE_3} lang="bash" showDots={true} />

        <H2>Step 4: Start the daemon</H2>
        <TabbedCode tabs={QUICKSTART_CODE_4_TABS} showDots={true} />

        <H2>Step 5: Run your first execution</H2>
        <CodeBlock code={QUICKSTART_CODE_5} lang="python" showDots={true} />

        <CalloutBlock type="tip">
          Use the LangChain adapter to skip socket management entirely — <code>pip install vela-agent langchain</code> and you're done.
        </CalloutBlock>

        <H2>Next steps</H2>
        <ul>
          <li><a href="#/docs/policy-engine" onClick={e => { e.preventDefault(); window.__velaSetDoc && window.__velaSetDoc('policy-engine'); }}>Configure the policy engine</a></li>
          <li><a href="#/docs/intrusion-detection" onClick={e => { e.preventDefault(); window.__velaSetDoc && window.__velaSetDoc('intrusion-detection'); }}>Add intrusion detection rules</a></li>
          <li><a href="#/integrations" onClick={e => { e.preventDefault(); navigate('/integrations'); }}>Connect to your AI framework</a></li>
        </ul>
      </div>
    ),
  },

  /* ================================================================
     CORE CONCEPTS — Capability Tokens
     ================================================================ */
  'capability-tokens': {
    toc: ['What are capability tokens?', 'Token anatomy', 'Generating tokens', 'Token scopes', 'Token expiration and rotation', 'Validating tokens programmatically'],
    content: (
      <div className="prose">
        <h1>Capability Tokens</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          HMAC-signed tokens that define exactly what an AI agent's code is allowed to do inside the sandbox.
        </p>

        <H2>What are capability tokens?</H2>
        <p>
          Capability tokens are the primary authorization mechanism in Vela. Instead of broad IAM roles or API keys,
          each execution is scoped to a cryptographically signed token that encodes fine-grained permissions:
          which files can be read, whether the network is accessible, how much memory the process may use, and how long it can run.
        </p>
        <p>
          Tokens follow the <strong>principle of least privilege</strong> — you create a token with the minimum set of
          permissions your agent needs, and the Vela daemon enforces those boundaries at the VM level. If a token doesn't
          grant network access, the micro-VM's network interface is simply never attached.
        </p>

        <H2>Token anatomy</H2>
        <p>A decoded capability token is a JSON object with the following structure:</p>
        <CodeBlock lang="json" filename="token-payload.json" showDots={true} code={`{
  "version": 1,
  "subject": "data-analysis-agent",
  "issued_at": "2025-01-15T10:30:00Z",
  "expires_at": "2025-01-16T10:30:00Z",
  "capabilities": {
    "filesystem": {
      "allow_read":  ["/tmp", "/data/input"],
      "allow_write": ["/tmp/output"]
    },
    "network": {
      "enabled": true,
      "allow_domains": ["api.openai.com", "huggingface.co"]
    },
    "resources": {
      "max_memory_mb": 256,
      "max_timeout_ms": 30000,
      "max_cpu_cores": 1
    },
    "environment": {
      "allow_vars": ["OPENAI_API_KEY", "HF_TOKEN"],
      "deny_vars":  ["AWS_*", "VELA_TOKEN_SECRET"]
    }
  },
  "signature": "hmac-sha256:a4f8c1..."
}`} />

        <H2>Generating tokens</H2>
        <p>Use the CLI to generate tokens. The token is signed with the secret set in <code>VELA_TOKEN_SECRET</code>:</p>
        <CodeBlock lang="bash" showDots={true} code={`# Minimal token: read-only /tmp, no network, 128MB, 10s timeout
vela aegis-generate-token \\
  --subject "my-agent" \\
  --allow-file /tmp \\
  --allow-network false \\
  --max-memory-mb 128 \\
  --max-timeout-ms 10000 \\
  --expires-in-seconds 3600 \\
  > /tmp/agent-token.json

# Full-featured token for a data pipeline agent
vela aegis-generate-token \\
  --subject "pipeline-agent" \\
  --allow-file /tmp,/data/input \\
  --allow-write /tmp/output \\
  --allow-network true \\
  --allow-domains "api.openai.com,s3.amazonaws.com" \\
  --allow-env "OPENAI_API_KEY,AWS_ACCESS_KEY_ID" \\
  --max-memory-mb 512 \\
  --max-timeout-ms 120000 \\
  --expires-in-seconds 86400 \\
  > /tmp/pipeline-token.json`} />

        <H2>Token scopes</H2>
        <p>The following scopes are available:</p>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.875rem', marginTop: '0.5rem' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Scope</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Flag</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>filesystem.read</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>--allow-file</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Paths the process may read from</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>filesystem.write</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>--allow-write</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Paths the process may write to</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>network.enabled</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>--allow-network</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Whether outbound networking is attached</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>network.domains</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>--allow-domains</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Allowlisted egress domains</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>resources.memory</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>--max-memory-mb</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Maximum RAM in megabytes</td></tr>
            <tr><td style={{ padding: '0.5rem 0.75rem' }}><code>resources.timeout</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>--max-timeout-ms</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Maximum wall-clock execution time</td></tr>
          </tbody>
        </table>

        <H2>Token expiration and rotation</H2>
        <p>
          Every token has an <code>expires_at</code> timestamp. After expiry, the daemon rejects the token with a <code>401 TOKEN_EXPIRED</code> error.
          For long-running agents, set up a token-rotation strategy:
        </p>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent import DaemonClient, generate_token
import time

def get_fresh_token():
    """Generate a new token valid for 1 hour."""
    return generate_token(
        secret=os.environ["VELA_TOKEN_SECRET"],
        subject="my-agent",
        allow_file=["/tmp"],
        max_timeout_ms=30000,
        expires_in_seconds=3600,
    )

client = DaemonClient(socket_path="/tmp/velad.sock")

# Refresh the token before each batch of executions
client.set_token(get_fresh_token())
result = client.execute(["python3", "analysis.py"])`} />

        <H2>Validating tokens programmatically</H2>
        <p>You can inspect and validate a token without starting the daemon:</p>
        <CodeBlock lang="bash" showDots={true} code={`# Inspect token contents
vela token inspect /tmp/agent-token.json

# Validate signature and expiry
vela token validate /tmp/agent-token.json
# ✓ signature valid
# ✓ expires in 23h 45m`} />
      </div>
    ),
  },

  /* ================================================================
     CORE CONCEPTS — Policy Engine
     ================================================================ */
  'policy-engine': {
    toc: ['What is the policy engine?', 'Policy file format', 'Network policies', 'Resource limits', 'Filesystem policies', 'Applying policies', 'Policy inheritance'],
    content: (
      <div className="prose">
        <h1>Policy Engine</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Declarative YAML-based rules that enforce organisation-wide security policies on every execution.
        </p>

        <H2>What is the policy engine?</H2>
        <p>
          While capability tokens define what an <em>individual agent</em> is allowed to do, the policy engine defines
          what <em>your organisation</em> allows. Policies are loaded at daemon start-up and act as a second layer of
          enforcement — even if a token grants network access, a policy can restrict which domains are reachable.
        </p>
        <p>
          This two-layer model means you can issue broad tokens to trusted agents while still maintaining guardrails
          at the infrastructure level. Policies are evaluated in order: the first matching rule wins.
        </p>

        <H2>Policy file format</H2>
        <CodeBlock lang="yaml" filename="policy.yaml" showDots={true} code={`# /etc/vela/policy.yaml
version: 1
name: production-default

rules:
  - name: allow-openai
    match:
      subject: "*"
    network:
      allow_domains:
        - "api.openai.com"
        - "*.googleapis.com"
      deny_domains:
        - "*.crypto-pool.org"
      max_egress_bytes: 10485760  # 10 MB

  - name: resource-caps
    match:
      subject: "*"
    resources:
      max_memory_mb: 512
      max_timeout_ms: 60000
      max_cpu_percent: 80

  - name: filesystem-lockdown
    match:
      subject: "*"
    filesystem:
      deny_paths:
        - "/etc/shadow"
        - "/root"
        - "/proc/kcore"
      read_only_paths:
        - "/usr"
        - "/lib"`} />

        <H2>Network policies</H2>
        <p>
          Network policies control which external domains the sandbox can reach. They use an allowlist model:
          only domains explicitly listed in <code>allow_domains</code> are reachable. Wildcards are supported.
        </p>
        <CodeBlock lang="yaml" showDots={true} code={`network:
  allow_domains:
    - "api.openai.com"
    - "*.huggingface.co"
    - "pypi.org"
  deny_domains:
    - "*.onion"
    - "*.crypto-pool.org"
  max_egress_bytes: 52428800   # 50 MB total
  max_connections: 10          # concurrent outbound connections`} />
        <CalloutBlock type="tip">
          Use <code>deny_domains</code> as an additional safety net. Deny rules are evaluated before allow rules,
          so <code>deny_domains: ["*"]</code> blocks all traffic regardless of allow rules.
        </CalloutBlock>

        <H2>Resource limits</H2>
        <p>Resource policies set hard ceilings on what a single execution may consume:</p>
        <CodeBlock lang="yaml" showDots={true} code={`resources:
  max_memory_mb: 256       # OOM-killed if exceeded
  max_timeout_ms: 30000    # SIGKILL after 30 seconds
  max_cpu_percent: 50      # cgroup CPU quota
  max_disk_mb: 100         # writable disk space inside VM
  max_open_files: 256      # file descriptor limit
  max_processes: 32        # fork bomb protection`} />

        <H2>Filesystem policies</H2>
        <p>
          Filesystem rules restrict which paths are visible inside the micro-VM. By default the rootfs is read-only;
          only explicitly allowed paths are mounted writable.
        </p>
        <CodeBlock lang="yaml" showDots={true} code={`filesystem:
  deny_paths:
    - "/etc/shadow"
    - "/etc/passwd"
    - "/root"
  read_only_paths:
    - "/usr"
    - "/opt"
  writable_paths:
    - "/tmp"
    - "/data/output"`} />

        <H2>Applying policies</H2>
        <p>Pass your policy file when starting the daemon:</p>
        <CodeBlock lang="bash" showDots={true} code={`vela daemon \\
  --policy /etc/vela/policy.yaml \\
  --rootfs /opt/vela/rootfs.ext4 \\
  --kernel /opt/vela/vmlinux.bin

# Validate a policy file without starting the daemon
vela policy validate /etc/vela/policy.yaml
# ✓ 3 rules loaded, no errors`} />

        <H2>Policy inheritance</H2>
        <p>
          Policies support an <code>extends</code> field that lets you compose layered policies. Child policies
          can only <em>restrict</em> further — they cannot grant permissions beyond what the parent allows.
        </p>
        <CodeBlock lang="yaml" filename="strict-policy.yaml" showDots={true} code={`version: 1
name: strict-research-agent
extends: production-default

rules:
  - name: restrict-memory
    match:
      subject: "research-*"
    resources:
      max_memory_mb: 128
      max_timeout_ms: 10000`} />
      </div>
    ),
  },

  /* ================================================================
     CORE CONCEPTS — Telemetry
     ================================================================ */
  'telemetry': {
    toc: ['Overview', 'Audit log format', 'Log destinations', 'Querying logs', 'Structured fields reference', 'Metrics and observability'],
    content: (
      <div className="prose">
        <h1>Telemetry &amp; Audit Logging</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Structured JSON audit logs and execution metrics for every sandbox invocation.
        </p>

        <H2>Overview</H2>
        <p>
          Every execution in Vela produces a structured audit log entry. These logs capture the full lifecycle
          of an execution: who requested it, what token was used, which resources were consumed, and whether
          any security events were triggered. Audit logs are essential for compliance, debugging agent behaviour,
          and forensic investigation.
        </p>
        <p>
          Vela also exports Prometheus-compatible metrics for real-time monitoring of daemon health, VM pool
          utilisation, and execution latency.
        </p>

        <H2>Audit log format</H2>
        <p>Each log entry is a single JSON line written to the configured log destination:</p>
        <CodeBlock lang="json" filename="audit.jsonl (one line)" showDots={true} code={`{
  "timestamp": "2025-01-15T14:22:31.445Z",
  "event": "execution.completed",
  "execution_id": "exec_8f3a9c2e",
  "subject": "data-analysis-agent",
  "command": ["python3", "pipeline.py"],
  "token_hash": "sha256:ab12cd34...",
  "duration_ms": 2847,
  "exit_code": 0,
  "resources": {
    "memory_peak_mb": 87,
    "cpu_time_ms": 1923,
    "network_egress_bytes": 4096,
    "disk_written_bytes": 12288
  },
  "security_events": [],
  "vm_id": "fc-pool-02",
  "policy": "production-default"
}`} />

        <H2>Log destinations</H2>
        <p>Configure where audit logs are written via the daemon config or CLI flags:</p>
        <CodeBlock lang="bash" showDots={true} code={`# Write to a local file (default)
vela daemon --audit-log /var/log/vela/audit.jsonl

# Stream to stdout (for container log aggregators)
vela daemon --audit-log stdout

# Send to a remote syslog endpoint
vela daemon --audit-log syslog://logs.example.com:514

# Multiple destinations
vela daemon \\
  --audit-log /var/log/vela/audit.jsonl \\
  --audit-log stdout`} />
        <CalloutBlock type="tip">
          Pipe stdout logs to tools like <code>jq</code>, Datadog, or Elasticsearch for real-time dashboards.
        </CalloutBlock>

        <H2>Querying logs</H2>
        <p>Use <code>jq</code> or the built-in <code>vela logs</code> command to filter audit entries:</p>
        <CodeBlock lang="bash" showDots={true} code={`# Find all failed executions in the last hour
vela logs --since 1h --filter "exit_code != 0"

# Find executions by a specific agent
vela logs --filter "subject == 'data-analysis-agent'" --limit 20

# Raw jq query
cat /var/log/vela/audit.jsonl | \\
  jq 'select(.security_events | length > 0)'`} />

        <H2>Structured fields reference</H2>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.875rem', marginTop: '0.5rem' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Field</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Type</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>execution_id</code></td><td style={{ padding: '0.5rem 0.75rem' }}>string</td><td style={{ padding: '0.5rem 0.75rem' }}>Unique identifier for this execution</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>subject</code></td><td style={{ padding: '0.5rem 0.75rem' }}>string</td><td style={{ padding: '0.5rem 0.75rem' }}>Token subject (agent identity)</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>duration_ms</code></td><td style={{ padding: '0.5rem 0.75rem' }}>number</td><td style={{ padding: '0.5rem 0.75rem' }}>Wall-clock execution time</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>security_events</code></td><td style={{ padding: '0.5rem 0.75rem' }}>array</td><td style={{ padding: '0.5rem 0.75rem' }}>IDS alerts triggered during execution</td></tr>
            <tr><td style={{ padding: '0.5rem 0.75rem' }}><code>resources</code></td><td style={{ padding: '0.5rem 0.75rem' }}>object</td><td style={{ padding: '0.5rem 0.75rem' }}>Peak resource consumption metrics</td></tr>
          </tbody>
        </table>

        <H2>Metrics and observability</H2>
        <p>The daemon exposes a Prometheus-compatible metrics endpoint:</p>
        <CodeBlock lang="bash" showDots={true} code={`# Enable metrics on port 9090
vela daemon --metrics-port 9090

# Scrape metrics
curl http://localhost:9090/metrics

# Key metrics:
# vela_executions_total{status="success|error|timeout"}
# vela_execution_duration_seconds{quantile="0.5|0.9|0.99"}
# vela_vm_pool_available
# vela_vm_pool_in_use
# vela_ids_alerts_total{type="port_scan|priv_esc|crypto_mine"}`} />
      </div>
    ),
  },

  /* ================================================================
     CORE CONCEPTS — Intrusion Detection
     ================================================================ */
  'intrusion-detection': {
    toc: ['Overview', 'Built-in detection rules', 'Alert format', 'Custom rules', 'Response actions', 'Testing your rules'],
    content: (
      <div className="prose">
        <h1>Intrusion Detection</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Real-time behavioural monitoring that detects and responds to suspicious activity inside sandboxed executions.
        </p>

        <H2>Overview</H2>
        <p>
          Vela's Intrusion Detection System (IDS) monitors every execution for anomalous behaviour patterns.
          Unlike traditional network-based IDS tools, Vela's system operates at the VM level — it can observe
          syscalls, process trees, network connections, and filesystem mutations in real time.
        </p>
        <p>
          When suspicious activity is detected, the IDS generates a structured alert and can optionally terminate
          the execution immediately. Alerts are included in the audit log and can trigger webhook notifications.
        </p>

        <H2>Built-in detection rules</H2>
        <p>Vela ships with a set of pre-configured detection rules:</p>
        <ul>
          <li><strong>Port scanning</strong> — rapid connection attempts to multiple ports on a single host</li>
          <li><strong>Privilege escalation</strong> — attempts to use <code>sudo</code>, <code>su</code>, or exploit SUID binaries</li>
          <li><strong>Crypto mining</strong> — detection of known mining binaries and Stratum protocol connections</li>
          <li><strong>Reverse shell</strong> — outbound connections with shell I/O redirection patterns</li>
          <li><strong>Data exfiltration</strong> — unusually large outbound data transfers</li>
          <li><strong>Container escape</strong> — attempts to access host namespaces or cgroups</li>
        </ul>
        <CalloutBlock type="note">
          Built-in rules are enabled by default. You can disable individual rules in your policy file
          with <code>ids.disable_rules: ["crypto-mining"]</code>.
        </CalloutBlock>

        <H2>Alert format</H2>
        <p>When a rule triggers, the IDS emits a structured alert:</p>
        <CodeBlock lang="json" filename="ids-alert.json" showDots={true} code={`{
  "timestamp": "2025-01-15T14:22:35.112Z",
  "alert_id": "ids_7b2f9e1a",
  "execution_id": "exec_8f3a9c2e",
  "rule": "port-scan",
  "severity": "high",
  "description": "Rapid connection attempts to 47 ports on 10.0.0.5",
  "evidence": {
    "target_host": "10.0.0.5",
    "ports_scanned": 47,
    "duration_ms": 230,
    "source_process": "python3"
  },
  "action_taken": "execution_killed"
}`} />

        <H2>Custom rules</H2>
        <p>
          Define custom detection rules in your policy YAML. Rules match on syscalls, process names, network
          patterns, and filesystem access:
        </p>
        <CodeBlock lang="yaml" filename="policy.yaml" showDots={true} code={`ids:
  custom_rules:
    - name: block-curl-uploads
      description: "Detect curl uploading files to external servers"
      match:
        process: "curl"
        args_contain: ["-X POST", "--upload-file", "-F"]
        network: outbound
      severity: high
      action: kill

    - name: detect-env-dump
      description: "Detect attempts to read all environment variables"
      match:
        command_pattern: "env|printenv|set"
        or:
          file_read: "/proc/*/environ"
      severity: medium
      action: alert

    - name: rate-limit-network
      description: "Kill execution if it opens too many connections"
      match:
        network_connections_per_second: 50
      severity: high
      action: kill`} />

        <H2>Response actions</H2>
        <p>Each rule specifies an action when triggered:</p>
        <ul>
          <li><code>alert</code> — log the event and continue execution (default)</li>
          <li><code>kill</code> — immediately terminate the execution with a non-zero exit code</li>
          <li><code>pause</code> — freeze the VM and wait for manual review (Cloud API only)</li>
          <li><code>webhook</code> — send the alert to a configured webhook URL in addition to logging</li>
        </ul>

        <H2>Testing your rules</H2>
        <p>Validate custom rules with the dry-run mode, which simulates executions against your ruleset:</p>
        <CodeBlock lang="bash" showDots={true} code={`# Test a policy's IDS rules against simulated scenarios
vela ids test --policy /etc/vela/policy.yaml

# Run a live execution in IDS debug mode (verbose logging)
vela exec --ids-debug -- python3 -c "
import socket
# This will trigger the port-scan rule
for port in range(80, 100):
    s = socket.socket()
    s.settimeout(0.1)
    try: s.connect(('10.0.0.5', port))
    except: pass
    s.close()
"
# [IDS] ALERT: port-scan triggered (19 ports in 120ms)
# [IDS] ACTION: execution_killed`} />
      </div>
    ),
  },

  /* ================================================================
     FRAMEWORK INTEGRATIONS — LangChain
     ================================================================ */
  'langchain': {
    toc: ['Overview', 'Installation', 'Basic usage', 'Configuring permissions', 'Using with agents', 'Error handling'],
    content: (
      <div className="prose">
        <h1>LangChain Integration</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Use Vela as a secure code-execution tool inside your LangChain agents and chains.
        </p>

        <H2>Overview</H2>
        <p>
          The <code>vela-agent</code> package includes a drop-in LangChain <code>Tool</code> that wraps Vela's
          sandboxed execution. Your LangChain agent can generate Python code, execute it safely inside a
          Firecracker micro-VM, and receive the results — all with the full protection of capability tokens,
          policy enforcement, and intrusion detection.
        </p>

        <H2>Installation</H2>
        <CodeBlock lang="bash" showDots={true} code={`pip install "vela-agent[langchain]" langchain langchain-openai`} />

        <H2>Basic usage</H2>
        <p>Create a <code>VelaTool</code> and add it to your agent's toolkit:</p>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent.integrations.langchain import VelaTool
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.prompts import ChatPromptTemplate

# Create the Vela sandbox tool
vela_tool = VelaTool(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/agent-token.json",
    name="python_sandbox",
    description="Execute Python code in a secure sandbox. Input is Python code.",
)

# Set up the LangChain agent
llm = ChatOpenAI(model="gpt-4o", temperature=0)
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a data analyst. Use the sandbox to run code."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

agent = create_openai_tools_agent(llm, [vela_tool], prompt)
executor = AgentExecutor(agent=agent, tools=[vela_tool], verbose=True)

result = executor.invoke({"input": "Calculate the first 20 Fibonacci numbers"})
print(result["output"])`} />

        <H2>Configuring permissions</H2>
        <p>
          The <code>VelaTool</code> accepts the same permission parameters as the CLI token generator.
          You can also pass a pre-generated token file:
        </p>
        <CodeBlock lang="python" showDots={true} code={`# Option A: use a pre-generated token file
vela_tool = VelaTool(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/my-token.json",
)

# Option B: inline permissions (token generated automatically)
vela_tool = VelaTool(
    socket_path="/tmp/velad.sock",
    token_secret=os.environ["VELA_TOKEN_SECRET"],
    allow_network=True,
    allow_domains=["api.openai.com"],
    max_memory_mb=256,
    max_timeout_ms=30000,
)`} />
        <CalloutBlock type="warning">
          Never hard-code <code>VELA_TOKEN_SECRET</code> in your source code. Use environment variables or a secrets manager.
        </CalloutBlock>

        <H2>Using with agents</H2>
        <p>
          The tool integrates with any LangChain agent type — OpenAI tools agents, ReAct agents,
          and plan-and-execute agents all work out of the box. The tool automatically captures
          stdout, stderr, and the exit code and returns them to the LLM.
        </p>
        <CodeBlock lang="python" showDots={true} code={`# The agent receives structured output from each execution:
# {
#   "stdout": "1, 1, 2, 3, 5, 8, 13, 21, 34, 55...",
#   "stderr": "",
#   "exit_code": 0,
#   "duration_ms": 45
# }`} />

        <H2>Error handling</H2>
        <p>
          When an execution fails — due to a timeout, OOM kill, or IDS alert — the tool returns the error
          details to the LLM so it can retry or adjust its approach:
        </p>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent.exceptions import ExecutionTimeout, SecurityViolation

try:
    result = vela_tool.invoke("import time; time.sleep(999)")
except ExecutionTimeout as e:
    print(f"Timed out after {e.timeout_ms}ms")
except SecurityViolation as e:
    print(f"IDS alert: {e.rule} — {e.description}")`} />
      </div>
    ),
  },

  /* ================================================================
     FRAMEWORK INTEGRATIONS — LlamaIndex
     ================================================================ */
  'llamaindex': {
    toc: ['Overview', 'Installation', 'Basic usage', 'Using with query pipelines', 'Custom tool configuration'],
    content: (
      <div className="prose">
        <h1>LlamaIndex Integration</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Plug Vela's secure sandbox into LlamaIndex agents and query pipelines.
        </p>

        <H2>Overview</H2>
        <p>
          Vela provides a native LlamaIndex <code>FunctionTool</code> wrapper that lets your LlamaIndex agents
          execute code securely. Whether you're building RAG pipelines with code execution, data analysis agents,
          or multi-step reasoning workflows, the integration handles sandbox lifecycle, token management, and
          result formatting automatically.
        </p>

        <H2>Installation</H2>
        <CodeBlock lang="bash" showDots={true} code={`pip install "vela-agent[llamaindex]" llama-index llama-index-llms-openai`} />

        <H2>Basic usage</H2>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent.integrations.llamaindex import VelaCodeTool
from llama_index.llms.openai import OpenAI
from llama_index.core.agent import ReActAgent

# Create the Vela tool for LlamaIndex
code_tool = VelaCodeTool(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/agent-token.json",
    name="sandbox",
    description="Run Python code in a secure sandbox and return output.",
)

# Build a ReAct agent
llm = OpenAI(model="gpt-4o", temperature=0)
agent = ReActAgent.from_tools(
    tools=[code_tool],
    llm=llm,
    verbose=True,
)

response = agent.chat("What is the SHA-256 hash of 'hello world'?")
print(response)`} />

        <H2>Using with query pipelines</H2>
        <p>
          You can also use the Vela tool inside a LlamaIndex query pipeline for post-processing or data
          transformation steps:
        </p>
        <CodeBlock lang="python" showDots={true} code={`from llama_index.core.query_pipeline import QueryPipeline
from aegis_agent.integrations.llamaindex import VelaQueryComponent

# Create a pipeline component that executes code
vela_step = VelaQueryComponent(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/agent-token.json",
)

pipeline = QueryPipeline(chain=[retriever, synthesizer, vela_step])
result = pipeline.run(query="Analyze the sales data and plot a chart")`} />

        <H2>Custom tool configuration</H2>
        <p>
          Pass sandbox permissions directly when creating the tool:
        </p>
        <CodeBlock lang="python" showDots={true} code={`code_tool = VelaCodeTool(
    socket_path="/tmp/velad.sock",
    token_secret=os.environ["VELA_TOKEN_SECRET"],
    allow_network=True,
    allow_domains=["api.openai.com"],
    max_memory_mb=512,
    max_timeout_ms=60000,
    # Install packages in the sandbox before execution
    setup_commands=["pip install pandas matplotlib"],
)`} />
        <CalloutBlock type="tip">
          Use <code>setup_commands</code> to pre-install Python packages. These run once when the VM is
          provisioned and are cached across executions for the same agent.
        </CalloutBlock>
      </div>
    ),
  },

  /* ================================================================
     FRAMEWORK INTEGRATIONS — CrewAI
     ================================================================ */
  'crewai': {
    toc: ['Overview', 'Installation', 'Setting up a sandboxed crew', 'Per-agent permissions', 'Full crew example'],
    content: (
      <div className="prose">
        <h1>CrewAI Integration</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Give your CrewAI agents access to secure code execution via Vela's sandboxed tool.
        </p>

        <H2>Overview</H2>
        <p>
          CrewAI is a framework for orchestrating teams of AI agents. Vela's CrewAI integration provides a
          tool class that any crew member can use to run code in an isolated micro-VM. Each agent in the crew
          can have its own capability token with different permissions, allowing you to enforce the principle
          of least privilege across the team.
        </p>

        <H2>Installation</H2>
        <CodeBlock lang="bash" showDots={true} code={`pip install "vela-agent[crewai]" crewai crewai-tools`} />

        <H2>Setting up a sandboxed crew</H2>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent.integrations.crewai import VelaCodeTool
from crewai import Agent, Task, Crew

# Create a Vela sandbox tool
sandbox = VelaCodeTool(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/agent-token.json",
)

# Create agents with sandbox access
researcher = Agent(
    role="Data Researcher",
    goal="Gather and analyze data from various sources",
    tools=[sandbox],
    verbose=True,
)

analyst = Agent(
    role="Data Analyst",
    goal="Process data and produce statistical insights",
    tools=[sandbox],
    verbose=True,
)

# Define tasks
research_task = Task(
    description="Compute the average of the first 1000 prime numbers",
    agent=researcher,
    expected_output="The average value as a decimal number",
)

analysis_task = Task(
    description="Verify the result and compute the standard deviation",
    agent=analyst,
    expected_output="Standard deviation value and verification",
)

crew = Crew(agents=[researcher, analyst], tasks=[research_task, analysis_task])
result = crew.kickoff()
print(result)`} />

        <H2>Per-agent permissions</H2>
        <p>
          Give each agent a different token to enforce role-specific permissions:
        </p>
        <CodeBlock lang="python" showDots={true} code={`# Researcher: network + filesystem access
researcher_sandbox = VelaCodeTool(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/researcher-token.json",  # has network access
)

# Analyst: no network, more memory
analyst_sandbox = VelaCodeTool(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/analyst-token.json",  # no network, 512MB RAM
)`} />
        <CalloutBlock type="note">
          Each agent's token is validated independently. If the researcher's token expires mid-crew-run,
          only the researcher's tasks fail — the analyst continues with its own valid token.
        </CalloutBlock>

        <H2>Full crew example</H2>
        <p>
          A complete example with task dependencies and output parsing:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Generate tokens for each agent role
vela aegis-generate-token \\
  --subject "researcher" \\
  --allow-network true \\
  --allow-domains "api.github.com" \\
  --max-memory-mb 256 \\
  > /tmp/researcher-token.json

vela aegis-generate-token \\
  --subject "analyst" \\
  --allow-network false \\
  --max-memory-mb 512 \\
  > /tmp/analyst-token.json`} />
      </div>
    ),
  },

  /* ================================================================
     FRAMEWORK INTEGRATIONS — OpenAI
     ================================================================ */
  'openai': {
    toc: ['Overview', 'Installation', 'Function calling setup', 'Assistants API', 'Handling tool calls', 'Streaming responses'],
    content: (
      <div className="prose">
        <h1>OpenAI Integration</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Use Vela as a function-calling tool with the OpenAI Chat API and Assistants API.
        </p>

        <H2>Overview</H2>
        <p>
          Vela integrates with OpenAI's function calling (tool use) feature, allowing GPT-4 and other models
          to generate code and execute it in a secure sandbox. The integration works with both the Chat
          Completions API and the newer Assistants API.
        </p>

        <H2>Installation</H2>
        <CodeBlock lang="bash" showDots={true} code={`pip install vela-agent openai`} />

        <H2>Function calling setup</H2>
        <p>
          Define Vela as a tool in your OpenAI function calling schema, then handle tool calls by routing
          code to the sandbox:
        </p>
        <CodeBlock lang="python" showDots={true} code={`import openai
from aegis_agent import DaemonClient
import json

client = openai.OpenAI()
vela = DaemonClient(
    socket_path="/tmp/velad.sock",
    token_file="/tmp/agent-token.json",
)

# Define the sandbox as an OpenAI tool
tools = [{
    "type": "function",
    "function": {
        "name": "execute_python",
        "description": "Execute Python code in a secure sandbox",
        "parameters": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string",
                    "description": "Python code to execute"
                }
            },
            "required": ["code"]
        }
    }
}]

messages = [
    {"role": "system", "content": "You can execute Python in a sandbox."},
    {"role": "user", "content": "What's the 50th Fibonacci number?"},
]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)`} />

        <H2>Assistants API</H2>
        <p>
          With the Assistants API, you can create a persistent assistant that uses Vela for code execution:
        </p>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent.integrations.openai import VelaAssistantTool

# Register Vela as a tool for an assistant
assistant = client.beta.assistants.create(
    name="Data Analyst",
    instructions="You analyze data using Python code.",
    model="gpt-4o",
    tools=[VelaAssistantTool.schema()],
)

# The tool handler automatically routes code to the Vela sandbox
thread = client.beta.threads.create()
client.beta.threads.messages.create(
    thread_id=thread.id,
    role="user",
    content="Analyze the prime distribution up to 10,000",
)`} />

        <H2>Handling tool calls</H2>
        <p>Process tool calls from the model response and execute them in the sandbox:</p>
        <CodeBlock lang="python" showDots={true} code={`# Process tool calls from the response
if response.choices[0].message.tool_calls:
    for tool_call in response.choices[0].message.tool_calls:
        if tool_call.function.name == "execute_python":
            code = json.loads(tool_call.function.arguments)["code"]

            # Execute in Vela sandbox
            result = vela.execute(["python3", "-c", code])

            # Send result back to the model
            messages.append(response.choices[0].message)
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result.stdout or result.stderr,
            })

    # Get the final response
    final = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
    )
    print(final.choices[0].message.content)`} />

        <H2>Streaming responses</H2>
        <p>
          For streaming use cases, handle tool calls incrementally:
        </p>
        <CodeBlock lang="python" showDots={true} code={`# Streaming with tool call handling
stream = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    stream=True,
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
    # Tool calls are accumulated and executed after the stream completes`} />
        <CalloutBlock type="tip">
          Combine the OpenAI integration with Vela's audit logging to maintain a complete record of every
          piece of code your AI generates and executes.
        </CalloutBlock>
      </div>
    ),
  },

  /* ================================================================
     CLOUD API — Authentication
     ================================================================ */
  'authentication': {
    toc: ['Overview', 'API keys', 'Authenticating requests', 'Key rotation', 'Scoped keys'],
    content: (
      <div className="prose">
        <h1>Authentication</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Authenticate requests to the Vela Cloud API using API keys and bearer tokens.
        </p>

        <H2>Overview</H2>
        <p>
          The Vela Cloud API uses API keys for authentication. Every request must include a valid API key in
          the <code>Authorization</code> header. API keys are scoped to a project and can be restricted to
          specific operations (read-only, execute, admin).
        </p>

        <H2>API keys</H2>
        <p>
          Generate API keys from the Vela dashboard or using the CLI. Each key is tied to a project and
          inherits the project's policies:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Generate a new API key
vela cloud key create \\
  --project my-project \\
  --name "production-key" \\
  --scope execute,read \\
  --expires 90d

# List existing keys
vela cloud key list --project my-project

# Revoke a key
vela cloud key revoke key_abc123def456`} />

        <H2>Authenticating requests</H2>
        <p>Include the API key as a Bearer token in the <code>Authorization</code> header:</p>
        <CodeBlock lang="bash" showDots={true} code={`curl -X POST https://api.vela.dev/v1/execute \\
  -H "Authorization: Bearer vela_key_abc123def456" \\
  -H "Content-Type: application/json" \\
  -d '{
    "command": ["python3", "-c", "print(42)"],
    "timeout_ms": 5000
  }'`} />
        <p>Or using the SDK:</p>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent import CloudClient

client = CloudClient(
    api_key="vela_key_abc123def456",
    # or set VELA_API_KEY environment variable
)

result = client.execute(["python3", "-c", "print(42)"])
print(result.stdout)  # 42`} />

        <H2>Key rotation</H2>
        <p>
          Rotate keys without downtime by creating a new key before revoking the old one.
          The API supports a 24-hour grace period during which both keys are valid:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Create replacement key
vela cloud key create --project my-project --name "prod-key-v2"

# Update your application to use the new key
# ...

# Revoke the old key (with 24h grace period)
vela cloud key revoke key_old123 --grace-period 24h`} />
        <CalloutBlock type="warning">
          Treat API keys like passwords. Never commit them to version control. Use environment variables
          or a secrets manager like HashiCorp Vault or AWS Secrets Manager.
        </CalloutBlock>

        <H2>Scoped keys</H2>
        <p>
          Restrict API keys to specific operations for defence in depth:
        </p>
        <ul>
          <li><code>execute</code> — can submit code for execution</li>
          <li><code>read</code> — can query execution results and logs</li>
          <li><code>admin</code> — can manage policies, keys, and webhooks</li>
        </ul>
      </div>
    ),
  },

  /* ================================================================
     CLOUD API — POST /execute
     ================================================================ */
  'execute': {
    toc: ['Endpoint overview', 'Request format', 'Response format', 'File uploads', 'Async execution', 'Error codes'],
    content: (
      <div className="prose">
        <h1>POST /execute</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          The primary API endpoint for running code in a secure Vela sandbox.
        </p>

        <H2>Endpoint overview</H2>
        <p>
          <code>POST https://api.vela.dev/v1/execute</code> creates a new sandboxed execution.
          The code runs inside a Firecracker micro-VM with the permissions defined by your project's
          policy and the request parameters. The response includes stdout, stderr, exit code, and
          resource usage metrics.
        </p>

        <H2>Request format</H2>
        <CodeBlock lang="bash" showDots={true} code={`curl -X POST https://api.vela.dev/v1/execute \\
  -H "Authorization: Bearer vela_key_abc123" \\
  -H "Content-Type: application/json" \\
  -d '{
    "command": ["python3", "-c", "import sys; print(sys.version)"],
    "timeout_ms": 10000,
    "memory_mb": 256,
    "environment": {
      "MY_VAR": "hello"
    },
    "network": {
      "enabled": true,
      "allow_domains": ["api.openai.com"]
    },
    "files": {
      "/tmp/input.csv": "name,value\\nfoo,42\\nbar,99"
    }
  }'`} />
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.875rem', marginTop: '0.5rem' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Field</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Type</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Required</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>command</code></td><td style={{ padding: '0.5rem 0.75rem' }}>string[]</td><td style={{ padding: '0.5rem 0.75rem' }}>Yes</td><td style={{ padding: '0.5rem 0.75rem' }}>Command and arguments to execute</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>timeout_ms</code></td><td style={{ padding: '0.5rem 0.75rem' }}>number</td><td style={{ padding: '0.5rem 0.75rem' }}>No</td><td style={{ padding: '0.5rem 0.75rem' }}>Max execution time (default: 30000)</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>memory_mb</code></td><td style={{ padding: '0.5rem 0.75rem' }}>number</td><td style={{ padding: '0.5rem 0.75rem' }}>No</td><td style={{ padding: '0.5rem 0.75rem' }}>Memory limit (default: 128)</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>environment</code></td><td style={{ padding: '0.5rem 0.75rem' }}>object</td><td style={{ padding: '0.5rem 0.75rem' }}>No</td><td style={{ padding: '0.5rem 0.75rem' }}>Environment variables to set</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>network</code></td><td style={{ padding: '0.5rem 0.75rem' }}>object</td><td style={{ padding: '0.5rem 0.75rem' }}>No</td><td style={{ padding: '0.5rem 0.75rem' }}>Network access configuration</td></tr>
            <tr><td style={{ padding: '0.5rem 0.75rem' }}><code>files</code></td><td style={{ padding: '0.5rem 0.75rem' }}>object</td><td style={{ padding: '0.5rem 0.75rem' }}>No</td><td style={{ padding: '0.5rem 0.75rem' }}>Files to inject (path → content)</td></tr>
          </tbody>
        </table>

        <H2>Response format</H2>
        <CodeBlock lang="json" filename="response.json" showDots={true} code={`{
  "execution_id": "exec_8f3a9c2e",
  "status": "completed",
  "exit_code": 0,
  "stdout": "3.11.5 (main, Sep 2 2024)\\n",
  "stderr": "",
  "duration_ms": 234,
  "resources": {
    "memory_peak_mb": 32,
    "cpu_time_ms": 89,
    "network_egress_bytes": 0
  },
  "security_events": []
}`} />

        <H2>File uploads</H2>
        <p>
          For large files, use the multipart upload endpoint instead of inline <code>files</code>:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`curl -X POST https://api.vela.dev/v1/execute \\
  -H "Authorization: Bearer vela_key_abc123" \\
  -F 'config={"command":["python3","process.py"],"timeout_ms":60000};type=application/json' \\
  -F "file=@./data.csv;filename=/tmp/data.csv" \\
  -F "file=@./process.py;filename=/tmp/process.py"`} />

        <H2>Async execution</H2>
        <p>
          For long-running jobs, use async mode. The API returns immediately with an execution ID,
          and you poll for results or receive a webhook:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Submit async execution
curl -X POST https://api.vela.dev/v1/execute?async=true \\
  -H "Authorization: Bearer vela_key_abc123" \\
  -H "Content-Type: application/json" \\
  -d '{"command": ["python3", "train_model.py"], "timeout_ms": 300000}'

# Response: {"execution_id": "exec_abc123", "status": "running"}

# Poll for results
curl https://api.vela.dev/v1/executions/exec_abc123 \\
  -H "Authorization: Bearer vela_key_abc123"`} />

        <H2>Error codes</H2>
        <ul>
          <li><code>400</code> — Invalid request (missing command, invalid parameters)</li>
          <li><code>401</code> — Invalid or expired API key</li>
          <li><code>403</code> — Operation not allowed by policy or key scope</li>
          <li><code>408</code> — Execution timed out</li>
          <li><code>429</code> — Rate limit exceeded</li>
          <li><code>500</code> — Internal server error</li>
          <li><code>503</code> — No VMs available in pool (try again)</li>
        </ul>
      </div>
    ),
  },

  /* ================================================================
     CLOUD API — Webhooks
     ================================================================ */
  'webhooks': {
    toc: ['Overview', 'Registering a webhook', 'Event types', 'Payload format', 'Signature verification', 'Retry policy'],
    content: (
      <div className="prose">
        <h1>Webhooks</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Receive real-time HTTP notifications when executions complete or security events are triggered.
        </p>

        <H2>Overview</H2>
        <p>
          Webhooks let you subscribe to execution events without polling. Vela sends HTTP POST requests to
          your configured endpoint whenever an execution completes, fails, or triggers a security alert.
          This is especially useful for async executions and monitoring pipelines.
        </p>

        <H2>Registering a webhook</H2>
        <CodeBlock lang="bash" showDots={true} code={`# Register a webhook endpoint
vela cloud webhook create \\
  --project my-project \\
  --url https://my-app.com/vela/webhook \\
  --events execution.completed,execution.failed,ids.alert \\
  --secret "whsec_my_signing_secret"

# List active webhooks
vela cloud webhook list --project my-project

# Delete a webhook
vela cloud webhook delete whk_abc123`} />

        <H2>Event types</H2>
        <ul>
          <li><code>execution.completed</code> — execution finished successfully (exit code 0)</li>
          <li><code>execution.failed</code> — execution finished with non-zero exit code</li>
          <li><code>execution.timeout</code> — execution exceeded its timeout</li>
          <li><code>execution.oom</code> — execution killed due to memory limit</li>
          <li><code>ids.alert</code> — intrusion detection rule triggered</li>
          <li><code>ids.kill</code> — IDS terminated an execution</li>
        </ul>

        <H2>Payload format</H2>
        <CodeBlock lang="json" filename="webhook-payload.json" showDots={true} code={`{
  "id": "evt_9a8b7c6d",
  "type": "execution.completed",
  "timestamp": "2025-01-15T14:22:31.445Z",
  "project": "my-project",
  "data": {
    "execution_id": "exec_8f3a9c2e",
    "command": ["python3", "analysis.py"],
    "exit_code": 0,
    "duration_ms": 2847,
    "stdout_length": 1024,
    "security_events": []
  }
}`} />

        <H2>Signature verification</H2>
        <p>
          Every webhook includes an <code>X-Vela-Signature</code> header. Verify it using HMAC-SHA256
          to ensure the payload is authentic:
        </p>
        <CodeBlock lang="python" showDots={true} code={`import hmac, hashlib

def verify_webhook(payload_bytes, signature, secret):
    """Verify the webhook signature."""
    expected = hmac.new(
        secret.encode(),
        payload_bytes,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

# In your webhook handler (Flask example):
@app.post("/vela/webhook")
def handle_webhook():
    sig = request.headers.get("X-Vela-Signature")
    if not verify_webhook(request.data, sig, WEBHOOK_SECRET):
        abort(401)
    event = request.json
    print(f"Received {event['type']}: {event['data']['execution_id']}")
    return "", 200`} />

        <H2>Retry policy</H2>
        <p>
          If your endpoint returns a non-2xx status code or times out (10s), Vela retries with exponential
          backoff: 1s, 5s, 30s, 5min, 1hr. After 5 failed attempts, the webhook is marked as failing and
          an email alert is sent to the project owner.
        </p>
        <CalloutBlock type="note">
          You can view webhook delivery history in the dashboard or via <code>vela cloud webhook deliveries whk_abc123</code>.
        </CalloutBlock>
      </div>
    ),
  },

  /* ================================================================
     CLOUD API — Rate Limiting
     ================================================================ */
  'rate-limiting': {
    toc: ['Overview', 'Default limits', 'Rate limit headers', 'Handling 429 responses', 'Requesting limit increases'],
    content: (
      <div className="prose">
        <h1>Rate Limiting</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Understand and work with the Vela Cloud API's rate limiting system.
        </p>

        <H2>Overview</H2>
        <p>
          The Vela Cloud API enforces rate limits to ensure fair usage and protect infrastructure stability.
          Rate limits are applied per API key and are based on a sliding-window counter. When you exceed the
          limit, the API returns a <code>429 Too Many Requests</code> response.
        </p>

        <H2>Default limits</H2>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.875rem', marginTop: '0.5rem' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Plan</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Executions/min</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Concurrent VMs</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Max timeout</th>
            </tr>
          </thead>
          <tbody>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}>Free</td><td style={{ padding: '0.5rem 0.75rem' }}>10</td><td style={{ padding: '0.5rem 0.75rem' }}>2</td><td style={{ padding: '0.5rem 0.75rem' }}>30s</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}>Pro</td><td style={{ padding: '0.5rem 0.75rem' }}>100</td><td style={{ padding: '0.5rem 0.75rem' }}>10</td><td style={{ padding: '0.5rem 0.75rem' }}>5min</td></tr>
            <tr><td style={{ padding: '0.5rem 0.75rem' }}>Enterprise</td><td style={{ padding: '0.5rem 0.75rem' }}>1000+</td><td style={{ padding: '0.5rem 0.75rem' }}>100+</td><td style={{ padding: '0.5rem 0.75rem' }}>30min</td></tr>
          </tbody>
        </table>

        <H2>Rate limit headers</H2>
        <p>Every API response includes rate-limit headers so you can adjust your request rate:</p>
        <CodeBlock lang="text" showDots={false} code={`X-RateLimit-Limit: 100         # Your plan's limit per window
X-RateLimit-Remaining: 87      # Remaining requests in this window
X-RateLimit-Reset: 1705330951  # Unix timestamp when the window resets
Retry-After: 12                # Seconds to wait (only on 429 responses)`} />

        <H2>Handling 429 responses</H2>
        <p>
          When rate-limited, implement exponential backoff. The Python SDK handles this automatically:
        </p>
        <CodeBlock lang="python" showDots={true} code={`from aegis_agent import CloudClient

# The SDK automatically retries on 429 with exponential backoff
client = CloudClient(
    api_key="vela_key_abc123",
    max_retries=3,        # retry up to 3 times on rate limit
    retry_backoff=2.0,    # exponential backoff multiplier
)

# Or handle manually
import time

def execute_with_retry(client, command, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.execute(command)
        except RateLimitError as e:
            wait = e.retry_after or (2 ** attempt)
            print(f"Rate limited, waiting {wait}s...")
            time.sleep(wait)
    raise Exception("Max retries exceeded")`} />

        <H2>Requesting limit increases</H2>
        <p>
          If your use case requires higher limits, contact the Vela team or upgrade your plan:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Check your current limits
vela cloud limits --project my-project

# Request a limit increase (Enterprise plan)
vela cloud limits request \\
  --project my-project \\
  --executions-per-min 500 \\
  --concurrent-vms 50 \\
  --reason "Production AI agent serving 10k users"`} />
      </div>
    ),
  },

  /* ================================================================
     SELF-HOSTING — Requirements
     ================================================================ */
  'requirements': {
    toc: ['Hardware requirements', 'Software dependencies', 'KVM setup', 'Firewall rules', 'Production checklist'],
    content: (
      <div className="prose">
        <h1>Requirements</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Hardware, software, and network prerequisites for self-hosting the Vela runtime.
        </p>

        <H2>Hardware requirements</H2>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.875rem', marginTop: '0.5rem' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Component</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Minimum</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Recommended</th>
            </tr>
          </thead>
          <tbody>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}>CPU</td><td style={{ padding: '0.5rem 0.75rem' }}>2 cores (x86_64 with VT-x)</td><td style={{ padding: '0.5rem 0.75rem' }}>8+ cores</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}>RAM</td><td style={{ padding: '0.5rem 0.75rem' }}>2 GB</td><td style={{ padding: '0.5rem 0.75rem' }}>16+ GB</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}>Disk</td><td style={{ padding: '0.5rem 0.75rem' }}>10 GB SSD</td><td style={{ padding: '0.5rem 0.75rem' }}>100+ GB NVMe</td></tr>
            <tr><td style={{ padding: '0.5rem 0.75rem' }}>Network</td><td style={{ padding: '0.5rem 0.75rem' }}>100 Mbps</td><td style={{ padding: '0.5rem 0.75rem' }}>1+ Gbps</td></tr>
          </tbody>
        </table>
        <CalloutBlock type="note">
          Each Firecracker micro-VM defaults to 128 MB RAM. With a pool size of 8, budget at least
          1 GB for VMs plus 512 MB for the daemon itself.
        </CalloutBlock>

        <H2>Software dependencies</H2>
        <ul>
          <li><strong>Linux kernel 5.10+</strong> with KVM modules (<code>kvm</code>, <code>kvm_intel</code> or <code>kvm_amd</code>)</li>
          <li><strong>Firecracker v1.5+</strong> binary at <code>/usr/local/bin/firecracker</code></li>
          <li><strong>Rust 1.75+</strong> (for building from source; not needed for binary releases)</li>
          <li><strong>iptables</strong> or <strong>nftables</strong> for VM networking</li>
          <li><strong>CNI plugins</strong> (optional, for advanced networking)</li>
        </ul>

        <H2>KVM setup</H2>
        <CodeBlock lang="bash" showDots={true} code={`# Verify KVM support
ls /dev/kvm
# /dev/kvm

# Load KVM modules (if not auto-loaded)
sudo modprobe kvm
sudo modprobe kvm_intel  # or kvm_amd

# Grant the vela user access
sudo usermod -aG kvm vela
sudo chmod 660 /dev/kvm

# Verify
vela check kvm
# ✓ /dev/kvm accessible
# ✓ Hardware virtualisation enabled
# ✓ Nested virtualisation: supported`} />

        <H2>Firewall rules</H2>
        <p>
          Open the following ports for the Vela daemon:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Unix socket (default, no ports needed)
# TCP listener (if using remote clients)
sudo ufw allow 8080/tcp comment "Vela API"
sudo ufw allow 9090/tcp comment "Vela metrics"

# VM egress: allow outbound from the VM bridge interface
sudo iptables -A FORWARD -i vela-br0 -j ACCEPT
sudo iptables -A FORWARD -o vela-br0 -m state --state RELATED,ESTABLISHED -j ACCEPT`} />

        <H2>Production checklist</H2>
        <ul>
          <li>✅ KVM accessible by the daemon user</li>
          <li>✅ Firecracker binary installed and executable</li>
          <li>✅ Root filesystem image (<code>rootfs.ext4</code>) downloaded</li>
          <li>✅ Kernel binary (<code>vmlinux.bin</code>) downloaded</li>
          <li>✅ <code>VELA_TOKEN_SECRET</code> set to a strong random value</li>
          <li>✅ Policy file reviewed and applied</li>
          <li>✅ Audit log destination configured</li>
          <li>✅ Monitoring and alerting set up</li>
        </ul>
      </div>
    ),
  },

  /* ================================================================
     SELF-HOSTING — Firecracker Setup
     ================================================================ */
  'firecracker': {
    toc: ['What is Firecracker?', 'Installing Firecracker', 'Downloading rootfs and kernel', 'VM pool configuration', 'Networking', 'Performance tuning'],
    content: (
      <div className="prose">
        <h1>Firecracker Setup</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Install and configure Firecracker micro-VMs for hardware-enforced code isolation.
        </p>

        <H2>What is Firecracker?</H2>
        <p>
          <a href="https://firecracker-microvm.github.io/" target="_blank" rel="noopener noreferrer">Firecracker</a> is
          an open-source Virtual Machine Monitor (VMM) created by AWS for serverless computing. Each micro-VM
          boots in under 125ms and uses as little as 5 MB of overhead memory. Vela uses Firecracker to give
          every code execution its own Linux kernel and isolated filesystem — a level of isolation that
          containers alone cannot provide.
        </p>

        <H2>Installing Firecracker</H2>
        <CodeBlock lang="bash" showDots={true} code={`# Download the latest Firecracker release
ARCH=$(uname -m)
FC_VERSION="1.6.0"
curl -L -o firecracker \\
  "https://github.com/firecracker-microvm/firecracker/releases/download/v\${FC_VERSION}/firecracker-v\${FC_VERSION}-\${ARCH}.tgz" \\
  | tar -xz

# Install to PATH
sudo mv release-v*/firecracker-v* /usr/local/bin/firecracker
sudo chmod +x /usr/local/bin/firecracker

# Verify
firecracker --version
# Firecracker v1.6.0`} />

        <H2>Downloading rootfs and kernel</H2>
        <p>
          Vela provides pre-built rootfs images with Python, Node.js, and common tools pre-installed:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Download the Vela rootfs and kernel
sudo mkdir -p /opt/vela
cd /opt/vela

# Download rootfs (Python 3.11 + Node 20 + common tools)
curl -L -o rootfs.ext4 \\
  https://github.com/karnati-praveen/VELA/releases/download/v0.9/rootfs-full.ext4

# Download kernel
curl -L -o vmlinux.bin \\
  https://github.com/karnati-praveen/VELA/releases/download/v0.9/vmlinux-5.10.bin

# Verify checksums
sha256sum rootfs.ext4 vmlinux.bin`} />
        <CalloutBlock type="tip">
          Use <code>rootfs-minimal.ext4</code> (200 MB) for faster boot times if you only need Python.
          The full image (<code>rootfs-full.ext4</code>, 800 MB) includes Node.js, Go, and system tools.
        </CalloutBlock>

        <H2>VM pool configuration</H2>
        <p>
          Vela pre-warms a pool of micro-VMs for near-instant execution. Configure the pool size based on
          your expected concurrency:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`# Start with a pool of 4 pre-warmed VMs
vela daemon \\
  --rootfs /opt/vela/rootfs.ext4 \\
  --kernel /opt/vela/vmlinux.bin \\
  --pool-size 4 \\
  --vm-memory-mb 128 \\
  --vm-vcpus 1

# For high-throughput production workloads
vela daemon \\
  --rootfs /opt/vela/rootfs.ext4 \\
  --kernel /opt/vela/vmlinux.bin \\
  --pool-size 16 \\
  --vm-memory-mb 256 \\
  --vm-vcpus 2 \\
  --pool-refill-strategy eager`} />

        <H2>Networking</H2>
        <p>
          Vela creates a bridge network for VM egress. The bridge is set up automatically, but you can
          customise the network CIDR and DNS settings:
        </p>
        <CodeBlock lang="yaml" filename="vela-config.yaml" showDots={true} code={`networking:
  bridge_name: vela-br0
  cidr: "172.20.0.0/24"
  gateway: "172.20.0.1"
  dns:
    - "8.8.8.8"
    - "8.8.4.4"
  # Rate-limit VM egress
  egress_rate_mbps: 10`} />

        <H2>Performance tuning</H2>
        <p>Tips for optimising Firecracker performance in production:</p>
        <ul>
          <li><strong>Use hugepages</strong> — enable 2 MB hugepages to reduce TLB pressure: <code>echo 256 | sudo tee /proc/sys/vm/nr_hugepages</code></li>
          <li><strong>Pin CPU cores</strong> — use <code>--cpu-affinity</code> to pin VMs to specific cores for consistent latency</li>
          <li><strong>NVMe storage</strong> — store rootfs images on NVMe for fastest boot times</li>
          <li><strong>Eager pool refill</strong> — use <code>--pool-refill-strategy eager</code> to pre-warm replacement VMs immediately after use</li>
          <li><strong>Balloon device</strong> — enable memory ballooning to reclaim unused memory from idle VMs</li>
        </ul>
      </div>
    ),
  },

  /* ================================================================
     SELF-HOSTING — Configuration Reference
     ================================================================ */
  'configuration': {
    toc: ['Configuration file', 'Daemon options', 'Environment variables', 'Token configuration', 'Logging configuration', 'Example configuration'],
    content: (
      <div className="prose">
        <h1>Configuration Reference</h1>
        <p style={{ fontSize: '1.0625rem' }}>
          Complete reference for all Vela daemon configuration options, environment variables, and CLI flags.
        </p>

        <H2>Configuration file</H2>
        <p>
          The Vela daemon reads configuration from a YAML file. By default it looks for <code>/etc/vela/config.yaml</code>,
          or you can specify a path with <code>--config</code>:
        </p>
        <CodeBlock lang="bash" showDots={true} code={`vela daemon --config /path/to/config.yaml`} />

        <H2>Daemon options</H2>
        <CodeBlock lang="yaml" filename="/etc/vela/config.yaml" showDots={true} code={`# Core daemon settings
daemon:
  listen: /tmp/velad.sock        # Unix socket path
  http_listen: 0.0.0.0:8080     # Optional HTTP listener
  pid_file: /var/run/velad.pid
  log_level: info                # debug, info, warn, error

# Firecracker VM settings
vm:
  rootfs: /opt/vela/rootfs.ext4
  kernel: /opt/vela/vmlinux.bin
  pool_size: 8
  memory_mb: 128
  vcpus: 1
  boot_timeout_ms: 5000
  pool_refill_strategy: eager    # eager or lazy

# Security
security:
  token_secret_env: VELA_TOKEN_SECRET
  policy_file: /etc/vela/policy.yaml
  ids_enabled: true

# Networking
networking:
  bridge_name: vela-br0
  cidr: "172.20.0.0/24"
  dns: ["8.8.8.8", "8.8.4.4"]

# Telemetry
telemetry:
  audit_log: /var/log/vela/audit.jsonl
  metrics_port: 9090
  metrics_path: /metrics`} />

        <H2>Environment variables</H2>
        <p>All configuration options can be set via environment variables with the <code>VELA_</code> prefix:</p>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.875rem', marginTop: '0.5rem' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Variable</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Default</th>
              <th style={{ textAlign: 'left', padding: '0.5rem 0.75rem', color: 'var(--color-muted)' }}>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_TOKEN_SECRET</code></td><td style={{ padding: '0.5rem 0.75rem' }}>—</td><td style={{ padding: '0.5rem 0.75rem' }}>HMAC secret for signing capability tokens (required)</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_LISTEN</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>/tmp/velad.sock</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Unix socket path</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_HTTP_LISTEN</code></td><td style={{ padding: '0.5rem 0.75rem' }}>disabled</td><td style={{ padding: '0.5rem 0.75rem' }}>HTTP listen address (e.g. <code>0.0.0.0:8080</code>)</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_LOG_LEVEL</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>info</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Log level: debug, info, warn, error</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_POOL_SIZE</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>4</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Number of pre-warmed VMs</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_VM_MEMORY_MB</code></td><td style={{ padding: '0.5rem 0.75rem' }}><code>128</code></td><td style={{ padding: '0.5rem 0.75rem' }}>Default VM memory in MB</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_POLICY_FILE</code></td><td style={{ padding: '0.5rem 0.75rem' }}>none</td><td style={{ padding: '0.5rem 0.75rem' }}>Path to policy YAML file</td></tr>
            <tr style={{ borderBottom: '1px solid var(--color-border)' }}><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_AUDIT_LOG</code></td><td style={{ padding: '0.5rem 0.75rem' }}>stdout</td><td style={{ padding: '0.5rem 0.75rem' }}>Audit log destination</td></tr>
            <tr><td style={{ padding: '0.5rem 0.75rem' }}><code>VELA_METRICS_PORT</code></td><td style={{ padding: '0.5rem 0.75rem' }}>disabled</td><td style={{ padding: '0.5rem 0.75rem' }}>Prometheus metrics port</td></tr>
          </tbody>
        </table>
        <CalloutBlock type="note">
          Environment variables override config file values. CLI flags override both.
          Precedence: CLI flags → environment variables → config file → defaults.
        </CalloutBlock>

        <H2>Token configuration</H2>
        <p>
          Configure default token parameters that apply when tokens don't specify explicit values:
        </p>
        <CodeBlock lang="yaml" showDots={true} code={`token_defaults:
  max_memory_mb: 128
  max_timeout_ms: 30000
  max_cpu_cores: 1
  allow_network: false
  # Maximum values any token can request (hard ceiling)
  max_allowed_memory_mb: 2048
  max_allowed_timeout_ms: 300000`} />

        <H2>Logging configuration</H2>
        <CodeBlock lang="yaml" showDots={true} code={`logging:
  level: info
  format: json               # json or text
  output: /var/log/vela/daemon.log
  # Separate audit log
  audit:
    output: /var/log/vela/audit.jsonl
    include_stdout: false     # don't log execution stdout (large)
    include_stderr: true
    max_file_size_mb: 100
    rotation: daily`} />

        <H2>Example configuration</H2>
        <p>
          A complete production configuration:
        </p>
        <CodeBlock lang="yaml" filename="/etc/vela/config.yaml" showDots={true} code={`daemon:
  listen: /tmp/velad.sock
  http_listen: 0.0.0.0:8080
  log_level: info

vm:
  rootfs: /opt/vela/rootfs.ext4
  kernel: /opt/vela/vmlinux.bin
  pool_size: 16
  memory_mb: 256
  vcpus: 2
  pool_refill_strategy: eager

security:
  token_secret_env: VELA_TOKEN_SECRET
  policy_file: /etc/vela/policy.yaml
  ids_enabled: true

networking:
  bridge_name: vela-br0
  cidr: "172.20.0.0/24"
  dns: ["8.8.8.8", "8.8.4.4"]
  egress_rate_mbps: 10

telemetry:
  audit_log: /var/log/vela/audit.jsonl
  metrics_port: 9090

token_defaults:
  max_memory_mb: 256
  max_timeout_ms: 60000
  allow_network: false`} />
      </div>
    ),
  },
};

// ── Main component ───────────────────────────────────────────

function DocsPage() {
  useSEO("Documentation — Vela Runtime", "Comprehensive documentation and guides for Vela.");
  const [activeDoc, setActiveDoc] = React.useState('overview');
  const [mobileNavOpen, setMobileNavOpen] = React.useState(false);

  // Expose setter so intra-page links can switch docs
  React.useEffect(() => {
    window.__velaSetDoc = setActiveDoc;
    return () => { delete window.__velaSetDoc; };
  }, []);

  const pageEntry = DOC_PAGES[activeDoc];
  const currentContent = pageEntry
    ? pageEntry.content
    : (
      <div>
        <h1 style={{ fontSize: '1.875rem', fontWeight: 800, letterSpacing: '-0.02em', marginBottom: '0.5rem' }}>
          {SIDEBAR_SECTIONS.flatMap(s => s.items).find(i => i.id === activeDoc)?.label || activeDoc}
        </h1>
        <div style={{ background: 'var(--color-surface)', border: '1px solid var(--color-border)', borderRadius: 'var(--radius-md)', padding: '2rem', textAlign: 'center', color: 'var(--color-muted)', marginTop: '2rem' }}>
          <IcoBookOpen size={32} style={{ margin: '0 auto 0.875rem', opacity: 0.4 }} />
          <p style={{ margin: 0 }}>This page is coming soon. Check the GitHub repo for the latest documentation.</p>
        </div>
      </div>
    );

  const TOC_ITEMS = pageEntry ? (pageEntry.toc || []) : [];

  return (
    <div style={{ paddingTop: '64px', minHeight: '100vh', background: 'var(--color-bg)' }}>
      <div style={{ display: 'flex', minHeight: 'calc(100vh - 64px)' }}>

        {/* Sidebar */}
        <aside style={{
          width: '240px', flexShrink: 0,
          borderRight: '1px solid var(--color-border)',
          padding: '2rem 0', position: 'sticky', top: '64px',
          height: 'calc(100vh - 64px)', overflowY: 'auto',
          background: 'var(--color-surface)',
        }} className="hide-mobile">
          {SIDEBAR_SECTIONS.map(({ heading, items }) => (
            <div key={heading} style={{ marginBottom: '0.5rem' }}>
              <div className="docs-sidebar-group">{heading}</div>
              {items.map(({ id, label }) => (
                <a key={id} href={'#/docs/' + id}
                  onClick={e => { e.preventDefault(); setActiveDoc(id); }}
                  className={`docs-sidebar-link${activeDoc === id ? ' active' : ''}`}
                >
                  {label}
                </a>
              ))}
            </div>
          ))}
        </aside>

        {/* Main content */}
        <main style={{ flex: 1, minWidth: 0, padding: 'clamp(1.5rem, 4vw, 3rem)', maxWidth: '720px' }}>
          {/* Mobile nav trigger */}
          <button className="hide-desktop" onClick={() => setMobileNavOpen(!mobileNavOpen)}
            style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', background: 'var(--color-surface)', border: '1px solid var(--color-border)', borderRadius: 'var(--radius-md)', padding: '0.5rem 0.875rem', fontSize: '0.875rem', color: 'var(--color-muted)', cursor: 'pointer', marginBottom: '1.5rem', width: '100%', justifyContent: 'space-between' }}>
            <span>Navigate docs</span>
            <IcoChevronDown size={14} style={{ transform: mobileNavOpen ? 'rotate(180deg)' : 'none', transition: 'transform 0.15s' }} />
          </button>

          {/* Mobile nav dropdown */}
          {mobileNavOpen && (
            <div className="hide-desktop" style={{ background: 'var(--color-surface)', border: '1px solid var(--color-border)', borderRadius: 'var(--radius-lg)', padding: '0.75rem', marginBottom: '1.5rem' }}>
              {SIDEBAR_SECTIONS.map(({ heading, items }) => (
                <div key={heading}>
                  <div style={{ fontSize: '0.7rem', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em', color: 'var(--color-text)', padding: '0.5rem 0.5rem 0.25rem' }}>{heading}</div>
                  {items.map(({ id, label }) => (
                    <a key={id} href={'#/docs/' + id}
                      onClick={e => { e.preventDefault(); setActiveDoc(id); setMobileNavOpen(false); }}
                      className={`docs-sidebar-link${activeDoc === id ? ' active' : ''}`}
                    >{label}</a>
                  ))}
                </div>
              ))}
            </div>
          )}

          {currentContent}
        </main>

        {/* On This Page TOC */}
        {TOC_ITEMS.length > 0 && (
          <aside style={{
            width: '200px', flexShrink: 0,
            padding: '2rem 1rem', position: 'sticky', top: '64px',
            height: 'calc(100vh - 64px)', overflowY: 'auto',
          }} className="hide-mobile">
            <div style={{ fontSize: '0.72rem', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.07em', color: 'var(--color-muted)', marginBottom: '0.75rem' }}>On this page</div>
            {TOC_ITEMS.map(item => {
              const targetId = slugify(item);
              return (
                <a key={item} href={'#' + targetId}
                  onClick={e => {
                    e.preventDefault();
                    const el = document.getElementById(targetId);
                    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
                  }}
                  style={{ display: 'block', fontSize: '0.8125rem', color: 'var(--color-muted)', padding: '0.25rem 0', textDecoration: 'none', lineHeight: 1.4, transition: 'color 0.12s' }}
                  onMouseEnter={e => e.target.style.color = 'var(--color-text)'}
                  onMouseLeave={e => e.target.style.color = 'var(--color-muted)'}
                >
                  {item}
                </a>
              );
            })}
          </aside>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { DocsPage });
