1
0
forked from wrenn/wrenn
pptx704 915d934c26 Frontend consistency pass: delight, audit, and normalization
Delight (keys page):
- Animated checkmark draw + circle pop on key reveal dialog open
- Key display area pulses accent glow on open to draw eye to "copy this"
- Copy button spring-bounces on successful copy (re-triggers on repeat)
- Empty state key icon floats (iconFloat, now global)
- Row hover uses scaleY left-accent stripe (matches capsules pattern)
- New key row flashes accent on reveal dialog dismiss (matches capsule-born)

Audit fixes (all dashboard pages):
- Page titles standardized to em dash: "Wrenn — X" across all four pages
- formatDate/timeAgo extracted to src/lib/utils/format.ts (string | undefined
  signatures); keys and snapshots now import from there instead of duplicating
- team formatDate gains undefined guard (kept local, date-only format differs)
- spin-once and iconFloat keyframes moved to app.css as globals; scoped copies
  removed from capsules and keys
- Snapshots empty state icon was referencing undefined @keyframes float; fixed
  to iconFloat

Normalization:
- Snapshots table rows: replaced ::before pseudo-element accent (opacity-only,
  single color) with DOM row-stripe element using scaleY transition, type-keyed
  color (green for snapshots, blue for images) — matches capsules pattern
- Create Key dialog: max-w-[400px] → max-w-[420px] to align with form dialogs
- Snapshots count and empty-state heading are now terminology-aware: shows
  "templates/snapshots/images" based on active filter; empty heading for all
  filter reads "No templates yet" instead of "No snapshots yet"

Not done (documented in audit, deferred):
- Sidebar nav items pointing to unimplemented routes (audit, usage, billing,
  notifications, settings) — left as-is, needs product decision
- Dialog max-widths fully normalized beyond Create Key — minor, deferred
- capsules timeAgo not imported from shared util (formatTime differs intentionally)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 15:51:11 +06:00
2026-03-22 19:01:38 +00:00
2026-03-24 13:29:54 +06:00
2026-03-24 12:34:58 +06:00
2026-03-24 12:34:58 +06:00
2026-03-10 04:28:51 +06:00
2026-03-22 19:01:38 +00:00
2026-03-13 05:42:10 +06:00
2026-03-22 19:01:38 +00:00

Wrenn Sandbox

MicroVM-based code execution platform. Firecracker VMs, not containers. Pool-based pricing, persistent sandboxes, Python/TS/Go SDKs.

Deployment

Prerequisites

  • Linux host with /dev/kvm access (bare metal or nested virt)
  • Firecracker binary at /usr/local/bin/firecracker
  • PostgreSQL
  • Go 1.25+

Build

make build    # outputs to builds/

Produces three binaries: wrenn-cp (control plane), wrenn-agent (host agent), envd (guest agent).

Host setup

The host agent machine needs:

# Kernel for guest VMs
mkdir -p /var/lib/wrenn/kernels
# Place a vmlinux kernel at /var/lib/wrenn/kernels/vmlinux

# Rootfs images
mkdir -p /var/lib/wrenn/images
# Build or place .ext4 rootfs images (e.g., minimal.ext4)

# Sandbox working directory
mkdir -p /var/lib/wrenn/sandboxes

# Snapshots directory
mkdir -p /var/lib/wrenn/snapshots

# Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1

Configure

Copy .env.example to .env and edit:

# Required
DATABASE_URL=postgres://wrenn:wrenn@localhost:5432/wrenn?sslmode=disable

# Control plane
CP_LISTEN_ADDR=:8000
CP_HOST_AGENT_ADDR=http://localhost:50051

# Host agent
AGENT_LISTEN_ADDR=:50051
AGENT_FILES_ROOTDIR=/var/lib/wrenn

Run

# Apply database migrations
make migrate-up

# Start control plane
./builds/wrenn-cp

Control plane listens on CP_LISTEN_ADDR (default :8000).

Host registration

Hosts must be registered with the control plane before they can serve sandboxes.

  1. Create a host record (via API or dashboard):

    # As an admin (JWT auth)
    curl -X POST http://localhost:8000/v1/hosts \
      -H "Authorization: Bearer $JWT_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"type": "regular"}'
    

    This returns a registration_token (valid for 1 hour).

  2. Start the host agent with the registration token and its externally-reachable address:

    sudo AGENT_CP_URL=http://cp-host:8000 \
         ./builds/wrenn-agent \
         --register <token-from-step-1> \
         --address 10.0.1.5:50051
    

    On first startup the agent sends its specs (arch, CPU, memory, disk) to the control plane, receives a long-lived host JWT, and saves it to $AGENT_FILES_ROOTDIR/host-token.

  3. Subsequent startups don't need --register — the agent loads the saved JWT automatically:

    sudo AGENT_CP_URL=http://cp-host:8000 \
         ./builds/wrenn-agent --address 10.0.1.5:50051
    
  4. If registration fails (e.g., network error after token was consumed), regenerate a token:

    curl -X POST http://localhost:8000/v1/hosts/$HOST_ID/token \
      -H "Authorization: Bearer $JWT_TOKEN"
    

    Then restart the agent with the new token.

The agent sends heartbeats to the control plane every 30 seconds. Host agent listens on AGENT_LISTEN_ADDR (default :50051).

Rootfs images

envd must be baked into every rootfs image. After building:

make build-envd
bash scripts/update-debug-rootfs.sh /var/lib/wrenn/images/minimal.ext4

Development

make dev          # Start PostgreSQL (Docker), run migrations, start control plane
make dev-agent    # Start host agent (separate terminal, sudo)
make check        # fmt + vet + lint + test

See CLAUDE.md for full architecture documentation.

Description
Secure infrastructure for AI
Readme Apache-2.0 9.5 MiB
Languages
Go 44.1%
Svelte 39.8%
Rust 9.5%
TypeScript 2.3%
Python 1.5%
Other 2.8%