# 320px Site Audit browser CLI

This optional owner-run continuation executes the audited public page in a new,
temporary pinned Chromium context. It does not receive WordPress, SSH or browser
profile credentials and does not upload its result. Unlike plugin-only Rendered,
the page's JavaScript and ordinary resources—including declared third parties—
can run, so review the boundary printed by the command before confirming it.

Run this as a non-root site owner. Node.js 20 or newer is required. The CLI
enables the Chromium sandbox and stops if that sandbox cannot start.
Start in the WordPress root. The first four commands create a private working
copy outside the public web root; do not install dependencies in the plugin
directory.

```bash
px320_browser_cli="$(mktemp -d /tmp/px320-browser-cli-XXXXXX)"
px320_plugin_dir="$(wp plugin path 320px-site-audit --dir)"
cp -a "$px320_plugin_dir/cli/browser/." "$px320_browser_cli/"
chmod 700 "$px320_browser_cli"
cd "$px320_browser_cli"
npm config get registry
npm ci --ignore-scripts
npm run install-browser -- --dry-run
npm run install-browser
npm run audit -- --url=https://example.test/ --language=en
```

The first command prints the configured package registry without contacting it.
After `npm ci`, the browser `--dry-run` prints the exact download URLs without
downloading them. The last command is the zero-page-request audit preview: it
prints the full boundary and stops. Run each following network command only
after reviewing its preceding preview; repeat the audit with
`--confirm-network` only after reviewing its boundary.

The private working copy and its `node_modules` may be discarded when no longer
needed; the installed browser is kept in Playwright's per-user cache. `npm ci`
contacts the configured npm registry; `install-browser` downloads the
Chromium revision pinned by Playwright 1.62.1. These installation calls do not
receive the audited URL or report. The audit itself performs one public browser
load for each explicit, queryless `--url` (maximum five). The target URL, the
runner's network address, normal request metadata, resource URLs, data that the
page's own JavaScript places in permitted request URLs/headers and transient
cookies set by the page can reach the first- and third-party origins used by
that page. JavaScript runs. Follow-up main-frame navigation, nested-frame
navigation, popups, downloaded-file retention, WebSockets, WebRTC,
WebTransport, dedicated/shared workers and non-GET/HEAD/OPTIONS requests are
blocked. Service workers are disabled.

The output uses an unpredictable name in the operating system's temporary
directory by default, is created with mode `0600` and is never overwritten. A
custom `--output` must name a private location outside the plugin/public web
root; paths inside this CLI package are rejected. The file contains only
counts, numeric measurements, fixed rule IDs and run-keyed page/origin
references—no URL, visible text, console message, field value, cookie/storage
key or value, HTML, selector, DOM excerpt or screenshot. Cookie count is
`not_tested`, because reading it would expose cookie values to the CLI process.
Keep the JSON private. Plugin association/import is a separate future contract;
this command makes no callback to WordPress.

If you need local visual evidence, first add `--capture-private-evidence` to the
unconfirmed preview and review the added warning. Then repeat with both that
flag and `--confirm-network`. This creates a separate random mode-`0700`
directory in the operating system's temporary directory. It contains a closed
mode-`0600` manifest and up to five mode-`0600` viewport PNG files per target;
it is never included in the JSON above.

These are masked layout captures, not raw screenshots. Before capture, visible
text and native field rendering are made transparent, field values/placeholders
are cleared in the temporary page, background/generated images and content are
neutralized, and media, image, SVG, canvas, iframe and custom/shadow surfaces
are hidden. The manifest's structural excerpts contain only allowlisted tags,
roles and ancestor tags, bounded rectangles, fixed overflow reasons and HMAC
node references—no text, selector, class/id, attribute value or URL. A failed
or over-limit redaction removes the whole partial bundle. Each PNG is capped at
5 MiB and the bundle at 128 MiB.

Masking reduces accidental disclosure but cannot prove a deliberately hostile
page safe. Treat the directory as sensitive: inspect every PNG and the manifest
before sharing, and delete it when it is no longer needed. The CLI does not
upload or import it.

This is cooperative automated inspection, not an adversarial-page verifier. A
page deliberately designed to replace browser-visible JavaScript APIs may
distort DOM/layout/accessibility measurements; treat unexpected results as a
reason for manual verification, never as a clean compliance verdict.

`--allow-insecure-http` exists only for an intentionally selected HTTP target,
normally a local or development site. The browser installer does not install OS
packages or request elevated privileges.

## Русская инструкция

Этот необязательный CLI-контур запускает публичную страницу в новом временном
Chromium за пределами `wp-admin`. Он не получает логины WordPress/SSH и не
загружает результат команде 320px. JavaScript и обычные ресурсы страницы,
включая сторонние, могут выполняться — до запуска команда показывает границы и
требует флаг `--confirm-network`.

Запускайте CLI от непривилегированного пользователя-владельца сайта. Нужен
Node.js 20 или новее. Песочница Chromium обязательна: если она недоступна,
аудит безопасно остановится. Начните из корня WordPress. Первые четыре команды
создают приватную рабочую копию вне публичного web root; не устанавливайте
зависимости в каталог плагина.

```bash
px320_browser_cli="$(mktemp -d /tmp/px320-browser-cli-XXXXXX)"
px320_plugin_dir="$(wp plugin path 320px-site-audit --dir)"
cp -a "$px320_plugin_dir/cli/browser/." "$px320_browser_cli/"
chmod 700 "$px320_browser_cli"
cd "$px320_browser_cli"
npm config get registry
npm ci --ignore-scripts
npm run install-browser -- --dry-run
npm run install-browser
npm run audit -- --url=https://example.test/ --language=ru
```

Первая команда показывает настроенный registry без обращения к нему. После
`npm ci` команда установки с `--dry-run` показывает точные адреса загрузки
браузера, но ничего не скачивает. Последняя команда показывает границы аудита и
завершается без запросов к странице. Каждую следующую сетевую команду запускайте
только после проверки предыдущего preview; аудит повторяйте с флагом
`--confirm-network` только после проверки его границ.

Приватную рабочую копию вместе с `node_modules` можно удалить, когда она больше
не нужна; браузер остаётся в пользовательском кеше Playwright. Установка
обращается к npm и CDN браузера, но не передаёт им адрес проверяемого
сайта или отчёт. Во время аудита адрес цели, сетевой адрес запускающего сервера,
обычные метаданные запросов, адреса ресурсов, данные, которые JavaScript самой
страницы помещает в разрешённые адреса/заголовки запросов, и временные cookie
могут получить её собственные и сторонние хосты. Основной документ после
начальной загрузки, вложенные документы, pop-up, сохранение скачанных файлов,
WebSocket, WebRTC, WebTransport, отдельные/shared workers и методы кроме
GET/HEAD/OPTIONS блокируются; service worker отключён.

По умолчанию JSON получает непредсказуемое имя в системном временном каталоге.
Он создаётся с правами `0600`, не перезаписывается и не может быть записан внутрь
каталога CLI. Явный `--output` должен находиться вне plugin/public web root.
Файл содержит только агрегаты и ключованные ссылки. Cookie не подсчитываются,
потому что безопасный подсчёт
потребовал бы передать их значения процессу CLI. Импорт в WordPress будет
отдельным контрактом; CLI не делает callback в плагин. Флаг
`--allow-insecure-http` нужен только для осознанно выбранного HTTP-адреса,
обычно локального или тестового сайта. Установщик браузера не ставит системные
пакеты и не запрашивает повышение привилегий.

Если нужны локальные визуальные evidence, сначала добавьте
`--capture-private-evidence` к preview без подтверждения и прочитайте новое
предупреждение. Затем повторите команду с этим флагом и `--confirm-network`.
CLI создаст отдельный случайный каталог `0700` в системном temp: закрытый
manifest и до пяти PNG на каждый адрес создаются с mode `0600` и не входят в
обычный JSON.

Это маскированная схема страницы, а не raw screenshot. Перед снимком текст и
native-отображение полей делаются прозрачными, значения/placeholder полей
очищаются во временном DOM, background/generated images/content
нейтрализуются, а media/image/SVG/canvas/iframe/custom/shadow surfaces
скрываются. Structural excerpts содержат только allowlisted tags/roles,
ancestor tags, ограниченную геометрию, фиксированный тип overflow и HMAC node
ref — без текста, selector, class/id, значений атрибутов или URL. Ошибка либо
превышение лимита удаляет весь неполный bundle; PNG ограничен 5 МиБ, bundle —
128 МиБ.

Masking снижает риск случайного раскрытия, но не доказывает безопасность
намеренно враждебной страницы. Считайте каталог чувствительным: просмотрите
каждый PNG и manifest перед передачей и удалите их после использования. CLI их
не загружает и не импортирует.

Это кооперативная автоматическая диагностика, а не проверка враждебной страницы.
Страница, намеренно подменяющая доступные JavaScript API, может исказить DOM,
layout или accessibility-измерения. Неожиданный результат требует ручной
проверки и не считается доказательством соответствия.
