Files
storkit/README.md

5.7 KiB
Raw Blame History

Story Kit

This app runs as a single Rust web server binary that serves the Vite/React frontend and exposes APIs. The frontend lives in the frontend/ directory.

You can also run the frontend and backend separately in development (Vite dev server + Rust API).

Running it in development

# Build the frontend
cd frontend
npm install
npm run dev

# In another terminal - run the server (serves embedded frontend/dist/)
cargo run

Production

# Build the release binary (also builds the frontend via build.rs)
cargo build --release

# Run the server (serves embedded frontend/dist/)
./target/release/storkit

Cross-Platform Distribution

Story Kit ships as a single self-contained binary with the React frontend embedded via rust-embed. No Rust toolchain, Node.js, or extra libraries are required on the target machine.

macOS

# Native build  no extra tools required beyond Rust + npm
make build-macos
# Output: target/release/storkit

# Verify only system frameworks are linked (Security.framework, libSystem.B.dylib, etc.)
otool -L target/release/storkit

Linux (static x86_64, zero dynamic deps)

The Linux build uses the x86_64-unknown-linux-musl target to produce a fully static binary.

Prerequisites:

# Install cross  a Rust cross-compilation tool backed by Docker
cargo install cross

# Ensure Docker Desktop (or Docker Engine) is running

Build:

make build-linux
# Output: target/x86_64-unknown-linux-musl/release/storkit

# Verify the binary is statically linked
file target/x86_64-unknown-linux-musl/release/storkit
# Expected: ELF 64-bit LSB executable, x86-64, statically linked

ldd target/x86_64-unknown-linux-musl/release/storkit
# Expected: not a dynamic executable

Running on any Linux x86_64 machine:

# No Rust, Node, glibc, or any other library needed  just copy and run
./storkit

Running in Docker (with gVisor sandboxing)

The docker/docker-compose.yml runs the container under gVisor (runtime: runsc). gVisor intercepts all container syscalls in userspace, providing an extra layer of isolation so that even a compromised workload cannot make raw syscalls to the host kernel.

Host setup (Linux only)

gVisor is a Linux technology. On macOS (OrbStack, Docker Desktop) you must remove runtime: runsc from docker/docker-compose.yml — gVisor is not available there.

1. Install gVisor (Debian/Ubuntu):

curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] \
  https://storage.googleapis.com/gvisor/releases release main" \
  | sudo tee /etc/apt/sources.list.d/gvisor.list
sudo apt-get update && sudo apt-get install -y runsc

2. Register runsc with Docker (/etc/docker/daemon.json):

{
  "runtimes": {
    "runsc": { "path": "/usr/bin/runsc" }
  }
}

3. Restart Docker and verify:

sudo systemctl restart docker
docker run --runtime=runsc hello-world

4. Launch storkit:

GIT_USER_NAME="Your Name" GIT_USER_EMAIL="you@example.com" \
PROJECT_PATH=/path/to/your/repo \
docker compose -f docker/docker-compose.yml up

gVisor compatibility notes

The following storkit subsystems have been verified to work under runsc:

  • PTY-based agent spawning (portable_pty / openpty) gVisor implements the full POSIX PTY interface (/dev/ptmx, TIOCGWINSZ, etc.).
  • rebuild_and_restart uses execve() to replace the server process, which gVisor fully supports.
  • Rust compilation cargo build inside the container invokes standard fork/exec primitives, all of which gVisor implements.

Releasing

Builds both macOS and Linux binaries locally, tags the repo, and publishes a Gitea release with a changelog.

One-time setup:

  1. Create a Gitea API token at https://code.crashlabs.io/user/settings/applications (needs repository read/write)
  2. Add it to .env (gitignored): GITEA_TOKEN=your_token
  3. Ensure cross is installed (cargo install cross) and Docker is running

To release:

make release V=0.2.0

This will:

  • Build macOS arm64 (native) and Linux amd64 (static musl via cross/Docker)
  • Generate a changelog from commits since the last tag
  • Tag the repo as v0.2.0 and push the tag
  • Create a Gitea release with both binaries and the changelog attached

Testing

Frontend Tests

The frontend uses Vitest for unit tests and Playwright for end-to-end tests.

cd frontend

# Run unit tests
npm test

# Run end-to-end tests
npm run test:e2e

Backend Tests

This project uses nextest for running tests and cargo-llvm-cov for code coverage.

Install Tools

cargo install cargo-nextest cargo-llvm-cov

Run Tests

# Run all tests
cargo nextest run

# Run specific module
cargo nextest run search_files

# Run with verbose output
cargo nextest run --no-capture

Generate Coverage

# HTML report (opens in browser)
cargo llvm-cov nextest --html --open

# Terminal output
cargo llvm-cov nextest

# LCOV format (for CI)
cargo llvm-cov nextest --lcov --output-path lcov.info

# Clean coverage data
cargo llvm-cov clean

Configuration

  • Nextest config: .config/nextest.toml
  • Coverage output: target/llvm-cov/html/index.html

Current Coverage (search_files module)

Module: commands/search.rs
├── Region Coverage:   75.36%
├── Function Coverage: 69.05%
└── Line Coverage:     72.55%

Available Test Profiles

# Development (default)
cargo nextest run

# CI with retries
cargo nextest run --profile ci

# Coverage optimized
cargo nextest run --profile coverage