fix(rc5): harden frontend runtime and diagnostics
This commit is contained in:
@@ -85,6 +85,12 @@
|
||||
сборку — vue-i18n молча отдаёт сам ключ, и оператор видит `error.code.min_length`
|
||||
вместо фразы.
|
||||
|
||||
Совпадения ключей недостаточно: строки компилируются как Vue I18n message
|
||||
format только при переводе. Специальные символы (`@`, `$`, `{}`, `|`) нельзя
|
||||
вставлять в текст как произвольные данные. Динамический набор знаков передаётся
|
||||
через named interpolation, а builder переводит каждую leaf-строку RU/EN и
|
||||
считает ошибкой как исключение, так и compiler diagnostics в `console.error`.
|
||||
|
||||
**Состояние сессии** сообщается кодами `unauthorized`, `session_expired`,
|
||||
`token_invalid`, `account_disabled` при `code = 50401`. Панель по ним
|
||||
показывает диалог и возвращает на форму входа.
|
||||
@@ -132,6 +138,11 @@
|
||||
продукт: в таблицу пиров ведут две двери, и они не имеют права требовать
|
||||
разного.
|
||||
|
||||
Frontend-зеркало границ, regex и человекочитаемого набора находится в одном
|
||||
модуле `constants/peer.ts` и сверяется с Go-контрактом тестом. Пунктуация
|
||||
`!@#$%^&*()_+-=` попадает в подсказку как значение `{punctuation}`, а не как
|
||||
часть синтаксиса message format.
|
||||
|
||||
---
|
||||
|
||||
## 4. Таблицы журнала
|
||||
|
||||
+15
-8
@@ -136,7 +136,7 @@ Bun обновляется отдельно от остальных: оркес
|
||||
полного прохода `bun test → tsc → compile → приёмка на Debian`, а не строки в
|
||||
общем патче.
|
||||
|
||||
### Проверка типов frontend — обязательный шаг релиза
|
||||
### Runtime-компиляция локализации и типы frontend — обязательные шаги релиза
|
||||
|
||||
```text
|
||||
pnpm run typecheck → vue-tsc --noEmit → ОБЯЗАН пройти
|
||||
@@ -144,9 +144,13 @@ pnpm run build:prod → vite build
|
||||
pnpm run verify → typecheck, затем build
|
||||
```
|
||||
|
||||
`bundle_ui()` запускает `typecheck` **до** сборки bundle: собирать production
|
||||
bundle из кода, который не проходит проверку типов, незачем. Порядок и сам факт
|
||||
наличия шага проверяются приёмкой.
|
||||
После `pnpm install --frozen-lockfile` функция `bundle_ui()` сначала запускает
|
||||
`bun test test/i18n-runtime.test.ts`, затем `typecheck` и только потом сборку
|
||||
bundle. Словари заданы TypeScript-объектами, поэтому Vite и `vue-tsc` не
|
||||
компилируют message format и не ловят специальные символы `@`, `$`, `{}`, `|`.
|
||||
Runtime-gate использует реальный `vue-i18n` из lock-графа, обходит все строки
|
||||
RU/EN и перехватывает также `console.error`: один лишь `try/catch` недостаточен,
|
||||
поскольку компилятор может сообщить об ошибке без исключения из `t()`.
|
||||
|
||||
До v1 этой гарантии не было. `build:prod` означал `vite build && vue-tsc
|
||||
--noEmit`, но `vue-tsc` был версии `0.35.0` (2022 год) и шаблоны Vue
|
||||
@@ -222,7 +226,9 @@ bundle из кода, который не проходит проверку ти
|
||||
|
||||
Уязвимость обычно приходит не из прямой зависимости, а из чужого поддерева, и
|
||||
поднимать ради неё весь frontend-граф не нужно. Такие случаи закрываются
|
||||
списком `pnpm.overrides` в `apps/frontend/package.json`:
|
||||
списком `overrides` в `apps/frontend/pnpm-workspace.yaml`. Настройки pnpm не
|
||||
хранятся в поле `pnpm` package manifest: современные версии его игнорируют, и
|
||||
правило осталось бы только случайно замороженным в старом lock-файле.
|
||||
|
||||
| override | зачем |
|
||||
| --- | --- |
|
||||
@@ -253,14 +259,15 @@ bundle из кода, который не проходит проверку ти
|
||||
| Шаг сборки | Что запускается |
|
||||
| --- | --- |
|
||||
| `run_orchestrator_tests` | `bun x tsc --noEmit`, `bun test` |
|
||||
| `bundle_ui` | `pnpm run typecheck` (`vue-tsc --noEmit`) до сборки bundle |
|
||||
| `run_frontend_tests` | dependency-free контракты панели |
|
||||
| `bundle_ui` | frozen install → runtime-компиляция всех RU/EN-сообщений → `pnpm run typecheck` → production bundle |
|
||||
| `run_admin_tests` | `go vet ./...`, `go test ./...` |
|
||||
|
||||
Готовый пакет объявляет об этом полем `tests_gate=true` в
|
||||
`metadata/package.env` — так же, как `dependency_security_gate` и
|
||||
`hysteria_compat_gate`. Значение у поля ровно одно, потому что не бывает
|
||||
пакета, собранного с пропущенными тестами: обе функции прогона выставляют свой
|
||||
флаг **после** успешного завершения, а `write_metadata` отказывается писать
|
||||
пакета, собранного с пропущенными тестами: функции прогона выставляют свои
|
||||
флаги **после** успешного завершения, а `write_metadata` отказывается писать
|
||||
метаданные, если хотя бы один из них не выставлен. То есть поле остаётся
|
||||
утверждением о результате, а не переключателем.
|
||||
|
||||
|
||||
@@ -346,6 +346,8 @@ hy2xs-orchestrator redact-config --config /etc/hysteria/config.yaml --out /root/
|
||||
редакцию, а результат остаётся валидным YAML;
|
||||
- в env-файлах секрет вырезается и из URL-значения, даже если имя ключа
|
||||
несекретное — например, `HY2_AUTH_URL` в `post-install.env`.
|
||||
- `HY2XS_FORCE_PASSWORD_CHANGE=true|false` сохраняется как диагностический
|
||||
boolean; это точное исключение, остальные ключи с `PASSWORD` редактируются.
|
||||
|
||||
Та же редакция применяется к diagnostics-бандлу
|
||||
(`hy2xs-orchestrator diagnostics collect`), который собирается автоматически при
|
||||
|
||||
@@ -144,6 +144,13 @@ anycast. Отсутствие A-записи фатально при любом
|
||||
- `HY2XS_FORCE_PASSWORD_CHANGE` в production baseline установлен в `false` (forced UX-flow пока не реализован);
|
||||
- после первичного seed перезапуски `hy2xs-admin` не должны переопределять пароль admin и `con_pass`.
|
||||
|
||||
В санитизированной диагностике корректное значение `true`/`false` у
|
||||
`HY2XS_FORCE_PASSWORD_CHANGE` остаётся видимым: это boolean состояния, а не
|
||||
пароль. Исключение применяется только к точному имени ключа и допустимому
|
||||
boolean; неизвестное значение скрывается fail-closed.
|
||||
`HY2XS_ADMIN_INITIAL_PASSWORD`, `HY2XS_ADMIN_CON_PASS`, пароль obfs,
|
||||
traffic-stats secret и похожие ключи продолжают редактироваться.
|
||||
|
||||
### Учётные данные администратора проверяются при разборе окружения
|
||||
|
||||
`HY2XS_ADMIN_USER` и `HY2XS_ADMIN_INITIAL_PASSWORD` — это значения, которые
|
||||
|
||||
@@ -18,9 +18,12 @@ cd apps && go vet ./... && go test ./...
|
||||
# Проверка типов и сборка frontend
|
||||
cd apps/frontend && pnpm install --frozen-lockfile && pnpm run verify
|
||||
|
||||
# Контракты панели: спрайт иконок, словари локализации, коды ошибок, атрибуция
|
||||
# Dependency-free контракты панели
|
||||
bun test tools/test/frontend-sprite.test.ts tools/test/frontend-contract.test.ts
|
||||
|
||||
# Runtime-компиляция всех RU/EN-сообщений реальным vue-i18n
|
||||
cd apps/frontend && bun test test/i18n-runtime.test.ts
|
||||
|
||||
# Сверка среды разработки с versions.env (ничего не меняет)
|
||||
./tools/dev/doctor.sh
|
||||
|
||||
@@ -36,9 +39,12 @@ HYSTERIA_BIN=/usr/local/bin/hysteria ./tools/test/e2e-hysteria.sh
|
||||
|
||||
## Почему контракты панели проверяет Bun, а не vitest
|
||||
|
||||
Проверяемые модули (`SvgIcon/symbol.ts`, `constants/branding.ts`, словари
|
||||
локализации) намеренно чистые: ни Vite, ни DOM в них нет, поэтому их можно
|
||||
выполнить вне браузера уже закреплённым в `versions.env` Bun.
|
||||
Dependency-free модули (`SvgIcon/symbol.ts`, frontend constants и словари
|
||||
локализации) намеренно чистые: ни Vite, ни DOM в них нет. Отдельный
|
||||
`i18n-runtime.test.ts` запускается после `pnpm install`, потому что обязан
|
||||
использовать именно `vue-i18n` из frozen lock-графа. Он обходит каждую строку
|
||||
обоих словарей и считает отказом и исключение, и compiler diagnostics в
|
||||
`console.error`.
|
||||
|
||||
Vitest с jsdom не вычисляет `currentColor` и визуальной корректности всё равно
|
||||
не доказал бы, зато привёл бы в граф `pnpm audit` — а его порог считается по
|
||||
|
||||
@@ -918,7 +918,8 @@ build tooling исполняется на build-машине и порождае
|
||||
| Шаг сборки | Что запускается |
|
||||
| --- | --- |
|
||||
| `run_orchestrator_tests` | `bun x tsc --noEmit`, `bun test` |
|
||||
| `bundle_ui` | `pnpm run typecheck` до сборки bundle |
|
||||
| `run_frontend_tests` | dependency-free контракты панели |
|
||||
| `bundle_ui` | после frozen install: `bun test test/i18n-runtime.test.ts`, затем `pnpm run typecheck` и bundle |
|
||||
| `run_admin_tests` | `go vet ./...`, `go test ./...` |
|
||||
|
||||
Приёмка проверяет:
|
||||
@@ -926,9 +927,13 @@ build tooling исполняется на build-машине и порождае
|
||||
- отключающей тесты переменной нет ни в одном модуле сборки, ни в README/docs
|
||||
(место для истории — `CHANGELOG.md`);
|
||||
- `metadata/package.env` содержит `tests_gate=true`;
|
||||
- общий frontend-флаг выставляется только после ранних контрактов и
|
||||
runtime-компиляции всех сообщений RU/EN;
|
||||
- runtime-gate стоит между frozen install и typecheck/build, использует
|
||||
`vue-i18n` из lock-графа и считает ошибкой compiler diagnostics;
|
||||
- утверждение о прогоне выставляется **после** самого прогона, а не до него;
|
||||
- `write_metadata` отказывается писать метаданные, если хотя бы один из двух
|
||||
прогонов не подтверждён.
|
||||
- `write_metadata` отказывается писать метаданные, если хотя бы одна из
|
||||
обязательных групп проверок не подтверждена.
|
||||
|
||||
## A12. Приёмка проверяет код, а не упоминания
|
||||
|
||||
|
||||
Reference in New Issue
Block a user