# Песочница

Приложение пишет пользователь, а открывают его другие люди. Поэтому оно выполняется в песочнице: отдельный веб-процесс без сети, без доступа к Pairx, к другим приложениям и к телефону. Наружу ведёт только [мост](https://dev.pairx.org/reference/bridge) — набор вызовов, которые Pairx проверяет сам.

Песочница одинакова на iPhone и Android; [эмулятор](https://dev.pairx.org/tools#pairx-dev) воспроизводит её в браузере.

## Чего нет

- Сеть: fetch, XMLHttpRequest, WebSocket, EventSource и внешние адреса
- WebGL
- WebAudio
- IndexedDB
- WebAssembly
- WebRTC
- Камера, микрофон, геолокация, датчики
- Всплывающие окна и переходы по ссылкам наружу

Это не временные ограничения версии, а свойства песочницы: так приложение не может отправить данные чата на чужой сервер, следить за человеком или выдать себя за Pairx.

## Чем заменить

| Нужно | Как в Pairx |
| --- | --- |
| Сохранить общие данные чата | [Хранилища Pairx](https://dev.pairx.org/guides/storage): журнал, значение на человека, документ, счётчики |
| Сохранить личное | Обычный `localStorage` — Pairx хранит его сам, см. [Личные данные](https://dev.pairx.org/guides/private) |
| Картинки, иконки | SVG в коде, `data:` URL или файлы пакета |
| Шрифты | Системные (`-apple-system, system-ui, sans-serif`). Свои шрифты (`@font-face` с `data:` URL) на iPhone может не показать защищённый режим — оставляйте системный шрифт запасным |
| Библиотеки (React, Vue, Chart.js…) | Встроить в файл при сборке — например, `vite-plugin-singlefile` |
| Кнопка «Отправить», окно подтверждения | `ui.mainButton`, `ui.popup` — нативные, Pairx рисует их сам, см. [Интерфейс](https://dev.pairx.org/guides/interface) |
| Звук | `<audio>` с `data:` URL или файлом пакета; WebAudio нет |
| Анимация, игры | Canvas 2D, CSS-анимации, SVG; WebGL нет |
| Данные из интернета | Пока никак: сети в приложениях нет |

## Политика безопасности

Страница получает такую CSP — на iPhone, на Android и в эмуляторе одну и ту же:

```text
default-src 'none';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob:;
font-src 'self' data:;
media-src 'self' data: blob:;
connect-src 'self';
frame-src 'none';
child-src 'none';
worker-src 'none';
form-action 'none';
base-uri 'none'
```

Встроенные `<script>` и `<style>`, `eval` и `new Function` разрешены: приложение из одного файла иначе не работает. Всё остальное — только из самого приложения.

## Ссылки и окна

- Ссылки наружу не открываются: Pairx отменяет переход ещё до того, как страница увидит нажатие. Переход по якорю внутри страницы (`href="#part"`) работает.
- `window.open`, фреймы и воркеры не работают.
- `alert`, `confirm` и `prompt` работают, но Pairx показывает их своими окнами с названием приложения и пометкой «код пользователя» — так окно приложения нельзя выдать за окно Pairx. Удобнее `ui.popup` и `ui.toast`.
- Формы работают: событие `submit` приходит, но сама отправка формы куда-либо запрещена — обрабатывайте её в скрипте и вызывайте `event.preventDefault()`.

## Что видит приложение

- Только своё: ID человека внутри этого приложения (в другом приложении у того же человека другой ID), язык, тему, вид контекста и данные своих хранилищ.
- Не видит: имя, аккаунт и телефон человека, список чатов, сообщения, других приложений. Имена участников чата появятся позже — по разрешению `chat.members`, на которое человек соглашается сам.

## Проверки при отправке

Сервис ищет в коде признаки обхода песочницы — WebRTC, адреса STUN/TURN, обращение к окнам фреймов, нажатие ссылок из кода, обфускацию, майнеры. Такая версия не отклоняется, а уходит на ручную проверку. Использование того, чего в песочнице просто нет (сеть, WebGL, IndexedDB…), — только предупреждение автору. Подробнее — в разделе [Публикация и версии](https://dev.pairx.org/guides/publishing).
