Browser Studio

0.4 NEW — Monaco-редактор прямо в админке. Пишешь плагин, жмёшь Build → Install → Run, не выходя из браузера.

WASM Studio — это wwwroot/wasm_studio.html, страница с редактором кода на основе Monaco (тот же движок, что в VS Code) и тремя REST-эндпоинтами на бэкенде, которые компилируют исходник серверным tinygo / cargo / asc.

Открытие

http://<lampac-host>/wasm_studio.html

(в production оборачивайте за admin-auth — handler сам по себе её не требует)

Интерфейс

┌──────────┬─────────────────────────────────┬───────────────────┐
│ ID       │ [Шаблон] [Build] [Install] [Run]│                   │
│ Язык     │ ┌─────────────────────────────┐ │ ┌───────────────┐ │
│ Цель     │ │ // Monaco editor (source)   │ │ │ Output panel  │ │
│          │ │                             │ │ │               │ │
│ manifest │ │ //export handle             │ │ │ ✓ build ok    │ │
│ {…}      │ │ func handle(ptr, len) {…}   │ │ │ took: 2.4s    │ │
│          │ │                             │ │ │ size: 412 KB  │ │
│          │ │                             │ │ │ sha256: abc.. │ │
│          │ └─────────────────────────────┘ │ └───────────────┘ │
└──────────┴─────────────────────────────────┴───────────────────┘
  • Левая панель — ID, язык (TinyGo / Rust / AssemblyScript), target (server / client / both / middleware), manifest.json в textarea.
  • Центр — Monaco-редактор; подсветка синтаксиса меняется при смене языка.
  • Правая панель — stdout / stderr компилятора, метаданные собранного .wasm, либо JSON-ответ от /lite/{id} после Run.

Workflow

  1. Шаблон — кладёт boilerplate для выбранного языка. Включает manifest, sample handle и нужные импорты SDK.
  2. Build — POST /admin/api/wasm-studio/build с {id, language, manifest, source}. Сервер раскладывает файлы в wasm_studio/<id>/, дёргает tinygo build / cargo build / npx asc, ловит вывод. Артефакт — wasm_studio/<id>/plugin.wasm.
  3. Install — POST /admin/api/wasm-studio/install с {id}. Копирует plugin.wasm + manifest.json в wasm_modules/<id>/. fsnotify watcher подхватывает мгновенно.
  4. RunGET /lite/<id>?rjson=true&id=<random> и показывает ответ.

REST API

POST /admin/api/wasm-studio/build

{
  "id": "my_plugin",
  "language": "tinygo",
  "manifest": { "id":"my_plugin", "target":"server", "abi_version":1 },
  "source":   "package main\n…"
}

Ответ:

{
  "ok": true,
  "stdout": "",
  "stderr": "warning: …",
  "wasm_path": "/lampac/wasm_studio/my_plugin/plugin.wasm",
  "wasm_size": 412345,
  "wasm_hash": "fa3e9c…",
  "build_id": "20260427-001234.567",
  "took": "2.341s"
}

При ошибке ok: false, stderr содержит вывод компилятора.

POST /admin/api/wasm-studio/install

{ "id": "my_plugin" }

Ответ: {"ok": true} или {"error": "no plugin.wasm in staging — build first"}.

GET /admin/api/wasm-studio/template?lang=tinygo

{
  "language": "tinygo",
  "manifest": "{ … }",
  "source":   "package main\n…"
}

lang принимает tinygo, rust, as. Все три шаблона лежат в internal/wasmmodules/studio_handler.go.

Требования к серверу

Compiler subprocess запускается на хосте lampac-go, поэтому соответствующий тулчейн должен быть установлен там:

Язык Зависимость Установка
TinyGo tinygo 0.41+ brew tap tinygo-org/tools && brew install tinygo (macOS), tinygo.org/getting-started (Linux)
Rust cargo + wasm32-wasip1 target rustup target add wasm32-wasip1
AssemblyScript npm npm install -g assemblyscript (или npx -y asc — Studio дёргает через npx)

Если тулчейн отсутствует, build вернёт ok: false со стероидной ошибкой toolchain not installed: <bin> — install it on the lampac host first.

Безопасность

Studio compiler subprocess не sandboxed. Это нормально для self-hosted lampac (админ уже имеет shell-доступ), но не используйте этот endpoint в публичном доступе — оборачивайте admin-auth, либо запускайте на отдельном хосте.

Что мы не делаем (и почему):

  • Не запускаем в Docker — Browser Studio для self-hosted режима, докерная sandboxing будет на hub.alcopa.cc.
  • Не ограничиваем cpu/mem — то же. Если нужно — запустите lampac-go под systemd с MemoryMax=/CPUQuota=.
  • Не ловим panic’и компилятора — они летят в stderr, который виден в UI; bash-injection невозможна (нет shell — exec.CommandContext напрямую).

В hub.alcopa.cc плагины из Studio автоматически прогоняются через permissions — даже если кто-то закинет malicious .wasm, без permissions: ["http:*"] он не сможет ходить в сеть.

Limitations

  • 90 секунд timeout на сборку. Crates с большим cargo-tree могут не успеть на холодном кеше; повторите запуск, кеш сохраняется в ~/.cargo.
  • Один файл на язык: main.go / src/lib.rs / index.ts. Для многофайловых проектов разворачивайте ZIP через admin_panel_jsmodules-style endpoint (TODO).
  • Компиляторы не sandboxed — hub.alcopa.cc будет делать это в Docker.

Что дальше

  • TinyGo SDK — пример, который Studio предлагает по умолчанию для Go
  • Rust SDK — то же для Rust
  • Permissions — что прописать в манифесте, чтобы плагин был “правильный”