Сайт kshana.dev
web/ — это дерево, которое GitHub Pages отдаёт как https://kshana.dev: страницы (index.html, missions.html, capabilities.html, evidence.html, developers.html, editions.html), документация в docs/ и Kshana Studio в studio/ (доступна по адресу https://kshana.dev/studio/) — приложение, которое запускает движок в браузере как WebAssembly (WASM) без серверных вычислений и без загрузки чего-либо на сервер. У Studio два представления одного движка: простое (studio/index.html, сначала ответ простыми словами) и расширенное (studio/advanced/index.html, полная панель), которое использует тот же движок, рабочий поток, модули и данные, что и простое, через <base href="../">.
Начиная с 0.35.0, у Studio есть ещё четыре представления, каждое — отдельная страница с <base href="../">, без индексации поисковыми системами и с папкой синтетических образцов, которую читает её тест:
studio/trust/: морское представление доверия, оценка доверия к приёмнику для потока положений судна, с демонстрационным треком вtrust/demo/.studio/training/: разбор тренировки экипажа, воспроизводящий синтетический NMEA с событием подавления, увода, подмены времени или повтора (training/demo/).studio/interference/: карта помех и воздействие на маршрут (interference/demo/).studio/tools/: одна страница карточек инструментов с примерами (tools/examples/,tools/samples/), включая подписанные пакеты доказательств (#evidence), экспорт для испытательного стенда (bench) (#bench), сопоставление compliance (#compliance), проверку Galileo OSNMA (#osnma) и каналы ИИ-ассистента (#ai).
Откуда берутся файлы#
Здесь живут три вида файлов, и меняются они тремя разными способами.
Перенесённые файлы. Страницы,
docs/,css/,js/,assets/, данные сайта вdata/(land.json,search.json,series.json) и всё вstudio/записываются скриптомweb/tools/port_site.pyиз сборки сайта и исходников Studio.PORT-MANIFEST.jsonперечисляет каждый из них с контрольной суммой SHA-256 (безопасный алгоритм хеширования, 256 бит). Не редактируйте их здесь:site.test.mjsзавершается ошибкой при правке вручную. Измените источник и заново запустите перенос:python3 web/tools/port_site.py --site <built site folder> --studio <Studio folder> python3 web/tools/port_site.py --site <built site folder> --studio <Studio folder> --checkПеренос детерминирован: второй запуск ничего не записывает, а
--checkзавершается с кодом 1, еслиweb/не то, что записал бы перенос. Он без изменений переносит файлы для обхода из сборки сайта (канонические теги, теги социальной карточки и schema.org каждой страницы,robots.txt,sitemap.xml,llms.txt,llms-full.txt), проверяет их, записываетlegacy-redirects.js,404.htmlи страницу переадресации по старому адресу Studio (playground/index.html, на/studio/) и направляет каждую страницу на локальные шрифты и библиотеки скриптов (ниже).Файлы, которыми владеет
web/. Это самостоятельные исходники, и перенос их никогда не затрагивает:capabilities.json— структурированный источник для карточек возможностей и сетки стандартов. Правьте его, а не HTML.data/verification-matrix.jsonпорождается (cargo run --bin gen_validation_artifacts) и закреплён тестомtests/verification_artifacts_doc_sync.rs; не правьте его вручную.data/card-matrix-map.json,data/oracle-references.jsonиdata/standards-matrix-map.json— сопоставления, поддерживаемые вручную, которые тот же тест сверяет с порождённой матрицей. Копии Studio вstudio/data/— это эти же файлы, байт в байт.og-card.svg,og-card.pngиog-card.rendered-from.json— социальная карточка (python3 tools/gen_og_card.py).CNAME,.well-known/security.txt,favicon.svg.fonts/иvendor/: файлы шрифтов и библиотека скриптов, которые используют страницы, загруженные один раз скриптомtools/fetch_third_party.pyи зафиксированные в репозитории (см. «Нет запросов к сторонним ресурсам»).build.sh,smoke.mjs,site.test.mjs,legacy-urls.test.mjsиtools/.
Результаты сборки, исключённые из git и порождаемые
build.sh:pkg/(пакетwasm-pack, из которого собран и пакет npm),studio/pkg/(тот же пакет там, где его импортирует Studio) иscenarios/(каждый эталонный сценарий по адресу, с которого их отдавал прежний одностраничный сайт).
Сборка и локальный запуск#
./web/build.sh # compiles the WASM module and stages it for the Studio
python3 -m http.server -d web 8000 # serve over HTTP (required for WASM)
# open http://localhost:8000/
Без инструментария WASM KSHANA_WASM_PKG=<a built pkg folder> ./web/build.sh подставляет готовый пакет вместо его компиляции. Рабочий процесс Pages этого никогда не использует.
Тесты#
node web/smoke.mjs # the WASM bindings (needs web/pkg)
node web/site.test.mjs # the ported tree: manifest, version, counts, links, inline JSON
node web/tools/inline-json.test.mjs # the guard for corrupt inline page data (an unescaped version bump)
node web/legacy-urls.test.mjs # every old kshana.dev address still resolves
for f in web/studio/lib/*.test.mjs; do node "$f"; done # the Studio's modules
Каждый модуль в studio/lib/ — чистая логика с соответствующим *.test.mjs; драйверы DOM (Document Object Model, дерево элементов страницы) Studio — это studio/app.js (простое представление) и studio/advanced.js (расширенное представление). Непрерывная интеграция запускает каждый из них отдельным шагом и завершается ошибкой, если у тестового файла в web/ нет шага.
Нет запросов к сторонним ресурсам#
kshana.dev отдаёт собственные шрифты, стили и скрипты. Страница не делает запросов к хосту шрифтов или хосту скриптов, поэтому адрес посетителя никому не передаётся.
Сайт и Studio написаны под Google Fonts и хост скриптов. Перенос заменяет ссылку Google Fonts на каждой странице соответствующей таблицей стилей в fonts/ (те же правила @font-face и те же файлы шрифтов, все подмножества, поэтому текст отображается как прежде), а каждый адрес хоста скриптов — файлом в vendor/. fonts/FONTS.json и vendor/VENDOR.json фиксируют, откуда взят каждый файл, и его контрольную сумму; шрифты распространяются по SIL Open Font License (fonts/OFL-*.txt), а three.js — по лицензии MIT (vendor/three@…/LICENSE).
tools/fetch_third_party.py --from <site folder> --from <Studio folder> — единственный шаг, использующий сеть. Запускайте его снова только тогда, когда страница запрашивает набор шрифтов или версию библиотеки, которых здесь нет: перенос откажет и сообщит об этом. site.test.mjs завершается ошибкой, если какая-либо перенесённая страница, таблица стилей или скрипт называет хост шрифтов или загружает что-либо с другого хоста.
Страница 404#
GitHub Pages отвечает на отсутствующий адрес страницей /404.html и статусом 404. Перенос создаёт эту страницу из собственной оболочки главной страницы (навигация, подвал, поиск) вокруг короткого сообщения со ссылками на главную страницу, документацию и Studio. Каждый адрес на ней пишется от корня сайта, потому что она отдаётся на любой глубине.
Старые адреса#
До v0.28.0 сайт был одной страницей, и всё находилось за фрагментом на / (/#playground, /#ledger, ссылки для публикации вида /#s=…, встраиваемые — /?embed=1&…; прежнее название вкладки во встраиваемой ссылке, например tab=fom, открывает вкладку Studio, которая её заменила). tools/legacy-urls.json перечисляет каждый такой адрес, который использует опубликованный материал, и куда он ведёт теперь; главная страница загружает legacy-redirects.js, порождаемый из этого списка, чтобы направлять их туда. Добавьте случай в список, прежде чем выводить из обращения какой-либо адрес.
Развёртывание#
Рабочий процесс GitHub Actions pages развёртывает тег релиза, а не main: release.yml запускает его, как только релиз опубликован, а ручной запуск повторно развёртывает указанный тег. Он выполняет build.sh, подготавливает web/ без тестов, скрипта сборки, tools/, манифеста и этого файла и публикует результат в GitHub Pages.