diff --git a/app/(main)/certificates/page.tsx b/app/(main)/certificates/page.tsx index 5363d6a9..d2b28d70 100644 --- a/app/(main)/certificates/page.tsx +++ b/app/(main)/certificates/page.tsx @@ -55,7 +55,7 @@ import { StepperSeparator, StepperTitle, StepperTrigger, -} from "@/components/reui/stepper" +} from "@/components/reui-kit/accessible-stepper" function mockToDto(cert: (typeof routerCertificates)[number]): CertificateDto { return { @@ -311,15 +311,16 @@ function CertPartIssueForm({

Trust store · www

Веб-интерфейс и HTTPS-сервисы

- +

Trust store · api

REST API и управление

- +
+

После импорта сертификат будет назначен сервисам www-ssl и api-ssl; оба сервиса будут включены. Переключатели выше задают trust store сертификата.

)} @@ -331,6 +332,8 @@ function CertPartIssueForm({
  • Имя: {issueCertName || "—"}
  • CN: {issueCommonName || "—"}
  • Trust www: {issueTrustWww ? "да" : "нет"} · api: {issueTrustApi ? "да" : "нет"}
  • +
  • Сервисы: www-ssl и api-ssl будут включены и получат этот сертификат.
  • +
  • DNS: приложение попробует синхронизировать A-записи доменов с IPv4 сервера; CNAME сохраняются.
  • )} diff --git a/app/(main)/servers/page.tsx b/app/(main)/servers/page.tsx index 9fee3600..0f195e59 100644 --- a/app/(main)/servers/page.tsx +++ b/app/(main)/servers/page.tsx @@ -53,7 +53,7 @@ import { StepperSeparator, StepperTitle, StepperTrigger, -} from "@/components/reui/stepper" +} from "@/components/reui-kit/accessible-stepper" import { RefreshCwIcon, PlusIcon, TrashIcon, EyeIcon, EyeOffIcon, diff --git a/components/backups/backup-create-sheet.tsx b/components/backups/backup-create-sheet.tsx index e81abe85..15d37ee5 100644 --- a/components/backups/backup-create-sheet.tsx +++ b/components/backups/backup-create-sheet.tsx @@ -25,7 +25,7 @@ import { StepperSeparator, StepperTitle, StepperTrigger, -} from "@/components/reui/stepper" +} from "@/components/reui-kit/accessible-stepper" import { Alert, AlertDescription, AlertTitle } from "@/components/reui/alert" import { cn } from "@/lib/utils" diff --git a/components/reui-kit/accessible-stepper.tsx b/components/reui-kit/accessible-stepper.tsx new file mode 100644 index 00000000..ea810718 --- /dev/null +++ b/components/reui-kit/accessible-stepper.tsx @@ -0,0 +1,49 @@ +"use client" + +import { createContext, useContext, useId, type ComponentProps } from "react" +import { + Stepper as RegistryStepper, + StepperNav as RegistryNav, + StepperContent as RegistryContent, + StepperTrigger as RegistryTrigger, + useStepItem, + type StepperProps, +} from "@/components/reui/stepper" + +export { StepperItem, StepperIndicator, StepperSeparator, StepperTitle, StepperPanel } from "@/components/reui/stepper" + +// The registry Nav/Content do not forward HTML attributes. Keep its layout, +// focus handling and styling; supply tab semantics in transparent wrappers. +const Context = createContext<{ prefix: string; orientation: "horizontal" | "vertical" } | null>(null) +function useScope() { + const context = useContext(Context) + if (!context) throw new Error("Шаги должны находиться внутри Stepper") + return context +} + +export function Stepper({ orientation = "horizontal", ...props }: StepperProps) { + const prefix = useId() + return + + +} + +export function StepperNav({ children, className }: Pick, "children" | "className">) { + const { orientation } = useScope() + return +
    {children}
    +
    +} + +export function StepperTrigger(props: ComponentProps) { + const { prefix } = useScope() + const { step } = useStepItem() + return +} + +export function StepperContent({ value, children, className }: Pick, "value" | "children" | "className">) { + const { prefix } = useScope() + return +
    {children}
    +
    +} diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index 2ca6e9b3..9e9f10d9 100644 --- a/docs/ux-ui-external-acceptance.md +++ b/docs/ux-ui-external-acceptance.md @@ -1,6 +1,6 @@ # UX/UI: протокол внешней приёмки 12.5 -Актуальное продолжение 2026-10-14: 250 — production ACME принят на точном mmt250-c22a9715.pngs.top/CHR104: Portal/UI один issue POST → done; DNS-01, native import/private key, trusted TLS/SAN и REST HTTPS200. Native services/certificates/files/export и ACME settings восстановлены, собственные job/A/TXT отсутствуют; оба CHR доступны. Backend249/frontend248 unchanged. Следующий251 — раскрыть в форме выпуска автоматическое назначение SSL-сервисам и DNS A-sync, затем проверить UI; renewal/CA revoke/multi-instance отдельно. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: 251 — форма выпуска раскрывает включение www-ssl/api-ssl и DNS A-sync, trust-store switches имеют доступные имена. Общий адаптер ReUI Stepper исправляет ARIA/уникальные ID в сертификатах, серверах и бэкапах без правок vendor/styles/motion. 69 unique E2E, TypeScript/lint/build passed; live PC/mobile keyboard/scoped axe4 violations0, writes0. Backend249/frontend ux-certificates251. Следующий252 — disabled/strict-ID guards сертификатов и достоверность результата renewal; реальное renewal ещё открыто. Этап12.5 открыт. IPsec78: реальный PSK responder established, mode-config198.18.78.10 и online=true подтверждены API; точные собственные объекты удалены. Сертификатный/DN online, late failure и history restore остаются открытыми. [Отчёт](ux-ui/acceptance/ipsec-mode-config-2026-10-09.json), [журнал](ux-ui-progress.md). @@ -18,6 +18,22 @@ OSPF84: real GRE Full adjacency/private routes/Ping3/3 и4 live PC/320px URL/bro BFD85: Up/Full/own route/Ping,4 live UI и loss/withdrawal/recovery приняты; exact own cleanup8 коллекций×2 passed. Withdrawal5,245ms не подтверждает sub-second BFD timing; этот вопрос открыт. Runtime routing83 без новой сборки. [Отчёт](ux-ui/acceptance/ospf-bfd-loss-2026-10-09.json). +## 12.5.251 — понятные последствия выпуска и доступные мастера ReUI (2026-10-14) + +После250 форма явно сообщает: импорт назначает сертификат обоим www-ssl/api-ssl и включает их; trust-store переключатели задают trust-store, не отменяют назначение. Итоговая сводка показывает DNS A-sync как попытку синхронизации с IPv4 сервера и сохранение CNAME. Сетевая логика/API не менялись. Оба trust-store switches получили доступные имена. + +Scoped axe live preview выявил прежние aria-required-children/parent и aria-valid-attr-value: установленный Stepper root role=tablist охватывал nav и контент, nav мешал родительской роли tabs, Content не передавал id/role/aria props. [API](https://reui.io/docs/components/base/stepper?ref=mcp), [preview](https://reui.io/components/stepper?ref=mcp) и примеры прочитаны через MCP; актуальный @reui/stepper прочитан shadcn view и имеет те же пропуски. Установка/переопределение vendor не решает их и не выполнена. + +Добавлен reui-kit/accessible-stepper: переиспользует установленные компоненты/keyboard/focus/styles, добавляет прозрачные display:contents обёртки с tablist/tabpanel, rootgroup без неподходящего aria-orientation, React useId для tab/panel namespace. Контент forceMount с штатным hidden сохраняет все IDREF. Vendor файл, shared theme и animation timings не менялись. Все три потребителя — сертификаты, создание/редактирование серверов, создание бэкапа — переведены на адаптер. + +69 уникальных E2E:57 existing certificates issue/layout + servers + backup operations и12 backup job + новые3 ARIA сценария. Первый набор57 прошёл2.1m, второй12 —32.1s; первоначальные7 issue повторяются в57 и не суммируются. Проверены операции/checkpoints/отказы/права/контекст, серверный wizard320/390/1440, certificate layout320/390/1440, связь каждой tab со своей существующей panel/unique IDs/одна видимая панель и4 ARIA rules во всех трёх формах. TypeScript и scoped ESLint passed. Не заявляем полного axe/WCAG аудита всех трёх страниц. + +Production frontend ux-certificates251 собран и развёрнут, source528 matched, backend ux-containers249 healthy сохранён, PostgreSQL/Portal не пересоздавались. До обнаружения ARIA дефекта выполнялись промежуточные сборки copy/labels; окончательный образ содержит adapter и все последние изменения. Это повтор из-за новых найденных ошибок, не дополнительные принятые сценарии. Для следующих сложных форм сначала локальный scoped axe, затем production build. [Deployment](ux-ui/acceptance/certificates251-deployment.json). + +Настоящий Portal/live preview1440/390: trust www переключается Space, step3/4 показывают назначение SSL независимо от trust toggle и DNS/CNAME; нет overflow/JS errors, четыре scoped axe WCAG2/2.1/2.2 scans violations0. Формы отменены Escape, API writes0/никаких выпусков/новых DNS/native objects. [Live UI](ux-ui/acceptance/certificates251-live-ui.json), [desktop](ux-ui/screens/certificates251-review-desktop.png), [mobile](ux-ui/screens/certificates251-review-mobile.png). Mobile screenshot просмотрен. ReUI checklist пройден в изменённом scope: reuse/семантика/security/scroll/typecheck/lint; неизменённые части не объявляются заново принятыми. + +Следующий252: чтение certificates-service поID всё ещё принимает numeric prefix и disabled row; renewal collector опрашивает его. Collector после runIssueJob прибавляет renewed без чтения terminal job status, хотя runner записывает failed и возвращается без throw; legacy parser подменяет неизвестный срок0. Исправить эти достоверные code-path дефекты и проверить соответствующие service/SQL случаи. Реальная повторная выдача/renewal/CA revoke/multi-instance остаются отдельными неподтверждёнными вариантами, первичный ACME250 уже принят. + ## 12.5.250 — production ACME / Cloudflare / TLS через реальный UI (2026-10-14) Пользователь предоставил pngs.top/Cloudflare и разрешил поддомены с префиксом mmt*. После уточнения звёздочки получено согласие на точное имя mmt250-c22a9715.pngs.top и временное назначение www-ssl/api-ssl с откатом. Cloudflare token verify и exact zone query200/success, token/zone active/account matched; оба собственных DNS имени до начала имели0 records. Ключ/почта/account ID только в ignored private fixture; на Debian ключ поступил через разрешённый временный API settings, отдельный secret файл туда не передавался. Native/private settings baseline снят до начала. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index dfb2f1de..f80c07c3 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,9 +1,25 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-14: 250 — production ACME принят на точном mmt250-c22a9715.pngs.top/CHR104: Portal/UI один issue POST → done; DNS-01, native import/private key, trusted TLS/SAN и REST HTTPS200. Native services/certificates/files/export и ACME settings восстановлены, собственные job/A/TXT отсутствуют; оба CHR доступны. Backend249/frontend248 unchanged. Следующий251 — раскрыть в форме выпуска автоматическое назначение SSL-сервисам и DNS A-sync, затем проверить UI; renewal/CA revoke/multi-instance отдельно. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: 251 — форма выпуска раскрывает включение www-ssl/api-ssl и DNS A-sync, trust-store switches имеют доступные имена. Общий адаптер ReUI Stepper исправляет ARIA/уникальные ID в сертификатах, серверах и бэкапах без правок vendor/styles/motion. 69 unique E2E, TypeScript/lint/build passed; live PC/mobile keyboard/scoped axe4 violations0, writes0. Backend249/frontend ux-certificates251. Следующий252 — disabled/strict-ID guards сертификатов и достоверность результата renewal; реальное renewal ещё открыто. Этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-14. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. +## 12.5.251 — понятные последствия выпуска и доступные мастера ReUI (2026-10-14) + +После250 форма явно сообщает: импорт назначает сертификат обоим www-ssl/api-ssl и включает их; trust-store переключатели задают trust-store, не отменяют назначение. Итоговая сводка показывает DNS A-sync как попытку синхронизации с IPv4 сервера и сохранение CNAME. Сетевая логика/API не менялись. Оба trust-store switches получили доступные имена. + +Scoped axe live preview выявил прежние aria-required-children/parent и aria-valid-attr-value: установленный Stepper root role=tablist охватывал nav и контент, nav мешал родительской роли tabs, Content не передавал id/role/aria props. [API](https://reui.io/docs/components/base/stepper?ref=mcp), [preview](https://reui.io/components/stepper?ref=mcp) и примеры прочитаны через MCP; актуальный @reui/stepper прочитан shadcn view и имеет те же пропуски. Установка/переопределение vendor не решает их и не выполнена. + +Добавлен reui-kit/accessible-stepper: переиспользует установленные компоненты/keyboard/focus/styles, добавляет прозрачные display:contents обёртки с tablist/tabpanel, rootgroup без неподходящего aria-orientation, React useId для tab/panel namespace. Контент forceMount с штатным hidden сохраняет все IDREF. Vendor файл, shared theme и animation timings не менялись. Все три потребителя — сертификаты, создание/редактирование серверов, создание бэкапа — переведены на адаптер. + +69 уникальных E2E:57 existing certificates issue/layout + servers + backup operations и12 backup job + новые3 ARIA сценария. Первый набор57 прошёл2.1m, второй12 —32.1s; первоначальные7 issue повторяются в57 и не суммируются. Проверены операции/checkpoints/отказы/права/контекст, серверный wizard320/390/1440, certificate layout320/390/1440, связь каждой tab со своей существующей panel/unique IDs/одна видимая панель и4 ARIA rules во всех трёх формах. TypeScript и scoped ESLint passed. Не заявляем полного axe/WCAG аудита всех трёх страниц. + +Production frontend ux-certificates251 собран и развёрнут, source528 matched, backend ux-containers249 healthy сохранён, PostgreSQL/Portal не пересоздавались. До обнаружения ARIA дефекта выполнялись промежуточные сборки copy/labels; окончательный образ содержит adapter и все последние изменения. Это повтор из-за новых найденных ошибок, не дополнительные принятые сценарии. Для следующих сложных форм сначала локальный scoped axe, затем production build. [Deployment](ux-ui/acceptance/certificates251-deployment.json). + +Настоящий Portal/live preview1440/390: trust www переключается Space, step3/4 показывают назначение SSL независимо от trust toggle и DNS/CNAME; нет overflow/JS errors, четыре scoped axe WCAG2/2.1/2.2 scans violations0. Формы отменены Escape, API writes0/никаких выпусков/новых DNS/native objects. [Live UI](ux-ui/acceptance/certificates251-live-ui.json), [desktop](ux-ui/screens/certificates251-review-desktop.png), [mobile](ux-ui/screens/certificates251-review-mobile.png). Mobile screenshot просмотрен. ReUI checklist пройден в изменённом scope: reuse/семантика/security/scroll/typecheck/lint; неизменённые части не объявляются заново принятыми. + +Следующий252: чтение certificates-service поID всё ещё принимает numeric prefix и disabled row; renewal collector опрашивает его. Collector после runIssueJob прибавляет renewed без чтения terminal job status, хотя runner записывает failed и возвращается без throw; legacy parser подменяет неизвестный срок0. Исправить эти достоверные code-path дефекты и проверить соответствующие service/SQL случаи. Реальная повторная выдача/renewal/CA revoke/multi-instance остаются отдельными неподтверждёнными вариантами, первичный ACME250 уже принят. + ## 12.5.250 — production ACME / Cloudflare / TLS через реальный UI (2026-10-14) Пользователь предоставил pngs.top/Cloudflare и разрешил поддомены с префиксом mmt*. После уточнения звёздочки получено согласие на точное имя mmt250-c22a9715.pngs.top и временное назначение www-ssl/api-ssl с откатом. Cloudflare token verify и exact zone query200/success, token/zone active/account matched; оба собственных DNS имени до начала имели0 records. Ключ/почта/account ID только в ignored private fixture; на Debian ключ поступил через разрешённый временный API settings, отдельный secret файл туда не передавался. Native/private settings baseline снят до начала. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index b89087de..ab57d587 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-14: 250 — production ACME принят на точном mmt250-c22a9715.pngs.top/CHR104: Portal/UI один issue POST → done; DNS-01, native import/private key, trusted TLS/SAN и REST HTTPS200. Native services/certificates/files/export и ACME settings восстановлены, собственные job/A/TXT отсутствуют; оба CHR доступны. Backend249/frontend248 unchanged. Следующий251 — раскрыть в форме выпуска автоматическое назначение SSL-сервисам и DNS A-sync, затем проверить UI; renewal/CA revoke/multi-instance отдельно. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: 251 — форма выпуска раскрывает включение www-ssl/api-ssl и DNS A-sync, trust-store switches имеют доступные имена. Общий адаптер ReUI Stepper исправляет ARIA/уникальные ID в сертификатах, серверах и бэкапах без правок vendor/styles/motion. 69 unique E2E, TypeScript/lint/build passed; live PC/mobile keyboard/scoped axe4 violations0, writes0. Backend249/frontend ux-certificates251. Следующий252 — disabled/strict-ID guards сертификатов и достоверность результата renewal; реальное renewal ещё открыто. Этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -38,6 +38,22 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка12.3.83 в границах журнала. Внешняя12.5: блоки1–236 завершены в записанных scopes, этап открыт. Runtime backend ux-backup234/frontend ux-routing218; backend25/UI52 и дополнительные SQL/UDP222 прошли. | +## 12.5.251 — понятные последствия выпуска и доступные мастера ReUI (2026-10-14) + +После250 форма явно сообщает: импорт назначает сертификат обоим www-ssl/api-ssl и включает их; trust-store переключатели задают trust-store, не отменяют назначение. Итоговая сводка показывает DNS A-sync как попытку синхронизации с IPv4 сервера и сохранение CNAME. Сетевая логика/API не менялись. Оба trust-store switches получили доступные имена. + +Scoped axe live preview выявил прежние aria-required-children/parent и aria-valid-attr-value: установленный Stepper root role=tablist охватывал nav и контент, nav мешал родительской роли tabs, Content не передавал id/role/aria props. [API](https://reui.io/docs/components/base/stepper?ref=mcp), [preview](https://reui.io/components/stepper?ref=mcp) и примеры прочитаны через MCP; актуальный @reui/stepper прочитан shadcn view и имеет те же пропуски. Установка/переопределение vendor не решает их и не выполнена. + +Добавлен reui-kit/accessible-stepper: переиспользует установленные компоненты/keyboard/focus/styles, добавляет прозрачные display:contents обёртки с tablist/tabpanel, rootgroup без неподходящего aria-orientation, React useId для tab/panel namespace. Контент forceMount с штатным hidden сохраняет все IDREF. Vendor файл, shared theme и animation timings не менялись. Все три потребителя — сертификаты, создание/редактирование серверов, создание бэкапа — переведены на адаптер. + +69 уникальных E2E:57 existing certificates issue/layout + servers + backup operations и12 backup job + новые3 ARIA сценария. Первый набор57 прошёл2.1m, второй12 —32.1s; первоначальные7 issue повторяются в57 и не суммируются. Проверены операции/checkpoints/отказы/права/контекст, серверный wizard320/390/1440, certificate layout320/390/1440, связь каждой tab со своей существующей panel/unique IDs/одна видимая панель и4 ARIA rules во всех трёх формах. TypeScript и scoped ESLint passed. Не заявляем полного axe/WCAG аудита всех трёх страниц. + +Production frontend ux-certificates251 собран и развёрнут, source528 matched, backend ux-containers249 healthy сохранён, PostgreSQL/Portal не пересоздавались. До обнаружения ARIA дефекта выполнялись промежуточные сборки copy/labels; окончательный образ содержит adapter и все последние изменения. Это повтор из-за новых найденных ошибок, не дополнительные принятые сценарии. Для следующих сложных форм сначала локальный scoped axe, затем production build. [Deployment](ux-ui/acceptance/certificates251-deployment.json). + +Настоящий Portal/live preview1440/390: trust www переключается Space, step3/4 показывают назначение SSL независимо от trust toggle и DNS/CNAME; нет overflow/JS errors, четыре scoped axe WCAG2/2.1/2.2 scans violations0. Формы отменены Escape, API writes0/никаких выпусков/новых DNS/native objects. [Live UI](ux-ui/acceptance/certificates251-live-ui.json), [desktop](ux-ui/screens/certificates251-review-desktop.png), [mobile](ux-ui/screens/certificates251-review-mobile.png). Mobile screenshot просмотрен. ReUI checklist пройден в изменённом scope: reuse/семантика/security/scroll/typecheck/lint; неизменённые части не объявляются заново принятыми. + +Следующий252: чтение certificates-service поID всё ещё принимает numeric prefix и disabled row; renewal collector опрашивает его. Collector после runIssueJob прибавляет renewed без чтения terminal job status, хотя runner записывает failed и возвращается без throw; legacy parser подменяет неизвестный срок0. Исправить эти достоверные code-path дефекты и проверить соответствующие service/SQL случаи. Реальная повторная выдача/renewal/CA revoke/multi-instance остаются отдельными неподтверждёнными вариантами, первичный ACME250 уже принят. + ## 12.5.250 — production ACME / Cloudflare / TLS через реальный UI (2026-10-14) Пользователь предоставил pngs.top/Cloudflare и разрешил поддомены с префиксом mmt*. После уточнения звёздочки получено согласие на точное имя mmt250-c22a9715.pngs.top и временное назначение www-ssl/api-ssl с откатом. Cloudflare token verify и exact zone query200/success, token/zone active/account matched; оба собственных DNS имени до начала имели0 records. Ключ/почта/account ID только в ignored private fixture; на Debian ключ поступил через разрешённый временный API settings, отдельный secret файл туда не передавался. Native/private settings baseline снят до начала. diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index 15448e2f..c5e54b5a 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,10 +1,26 @@ # Оставшаяся внешняя приёмка — 2026-10-14 -Актуальное продолжение 2026-10-14: 250 — production ACME принят на точном mmt250-c22a9715.pngs.top/CHR104: Portal/UI один issue POST → done; DNS-01, native import/private key, trusted TLS/SAN и REST HTTPS200. Native services/certificates/files/export и ACME settings восстановлены, собственные job/A/TXT отсутствуют; оба CHR доступны. Backend249/frontend248 unchanged. Следующий251 — раскрыть в форме выпуска автоматическое назначение SSL-сервисам и DNS A-sync, затем проверить UI; renewal/CA revoke/multi-instance отдельно. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: 251 — форма выпуска раскрывает включение www-ssl/api-ssl и DNS A-sync, trust-store switches имеют доступные имена. Общий адаптер ReUI Stepper исправляет ARIA/уникальные ID в сертификатах, серверах и бэкапах без правок vendor/styles/motion. 69 unique E2E, TypeScript/lint/build passed; live PC/mobile keyboard/scoped axe4 violations0, writes0. Backend249/frontend ux-certificates251. Следующий252 — disabled/strict-ID guards сертификатов и достоверность результата renewal; реальное renewal ещё открыто. Этап12.5 открыт. -Это актуальная матрица после 12.5.250. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.251. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-containers249`, frontend `ux-containers248`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-containers249`, frontend `ux-certificates251`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. + +## 12.5.251 — понятные последствия выпуска и доступные мастера ReUI (2026-10-14) + +После250 форма явно сообщает: импорт назначает сертификат обоим www-ssl/api-ssl и включает их; trust-store переключатели задают trust-store, не отменяют назначение. Итоговая сводка показывает DNS A-sync как попытку синхронизации с IPv4 сервера и сохранение CNAME. Сетевая логика/API не менялись. Оба trust-store switches получили доступные имена. + +Scoped axe live preview выявил прежние aria-required-children/parent и aria-valid-attr-value: установленный Stepper root role=tablist охватывал nav и контент, nav мешал родительской роли tabs, Content не передавал id/role/aria props. [API](https://reui.io/docs/components/base/stepper?ref=mcp), [preview](https://reui.io/components/stepper?ref=mcp) и примеры прочитаны через MCP; актуальный @reui/stepper прочитан shadcn view и имеет те же пропуски. Установка/переопределение vendor не решает их и не выполнена. + +Добавлен reui-kit/accessible-stepper: переиспользует установленные компоненты/keyboard/focus/styles, добавляет прозрачные display:contents обёртки с tablist/tabpanel, rootgroup без неподходящего aria-orientation, React useId для tab/panel namespace. Контент forceMount с штатным hidden сохраняет все IDREF. Vendor файл, shared theme и animation timings не менялись. Все три потребителя — сертификаты, создание/редактирование серверов, создание бэкапа — переведены на адаптер. + +69 уникальных E2E:57 existing certificates issue/layout + servers + backup operations и12 backup job + новые3 ARIA сценария. Первый набор57 прошёл2.1m, второй12 —32.1s; первоначальные7 issue повторяются в57 и не суммируются. Проверены операции/checkpoints/отказы/права/контекст, серверный wizard320/390/1440, certificate layout320/390/1440, связь каждой tab со своей существующей panel/unique IDs/одна видимая панель и4 ARIA rules во всех трёх формах. TypeScript и scoped ESLint passed. Не заявляем полного axe/WCAG аудита всех трёх страниц. + +Production frontend ux-certificates251 собран и развёрнут, source528 matched, backend ux-containers249 healthy сохранён, PostgreSQL/Portal не пересоздавались. До обнаружения ARIA дефекта выполнялись промежуточные сборки copy/labels; окончательный образ содержит adapter и все последние изменения. Это повтор из-за новых найденных ошибок, не дополнительные принятые сценарии. Для следующих сложных форм сначала локальный scoped axe, затем production build. [Deployment](ux-ui/acceptance/certificates251-deployment.json). + +Настоящий Portal/live preview1440/390: trust www переключается Space, step3/4 показывают назначение SSL независимо от trust toggle и DNS/CNAME; нет overflow/JS errors, четыре scoped axe WCAG2/2.1/2.2 scans violations0. Формы отменены Escape, API writes0/никаких выпусков/новых DNS/native objects. [Live UI](ux-ui/acceptance/certificates251-live-ui.json), [desktop](ux-ui/screens/certificates251-review-desktop.png), [mobile](ux-ui/screens/certificates251-review-mobile.png). Mobile screenshot просмотрен. ReUI checklist пройден в изменённом scope: reuse/семантика/security/scroll/typecheck/lint; неизменённые части не объявляются заново принятыми. + +Следующий252: чтение certificates-service поID всё ещё принимает numeric prefix и disabled row; renewal collector опрашивает его. Collector после runIssueJob прибавляет renewed без чтения terminal job status, хотя runner записывает failed и возвращается без throw; legacy parser подменяет неизвестный срок0. Исправить эти достоверные code-path дефекты и проверить соответствующие service/SQL случаи. Реальная повторная выдача/renewal/CA revoke/multi-instance остаются отдельными неподтверждёнными вариантами, первичный ACME250 уже принят. ## 12.5.250 — production ACME / Cloudflare / TLS через реальный UI (2026-10-14) @@ -226,7 +242,7 @@ Portal offline JWT действует доexp после logout/role change; э ## Следующая последовательность — 2026-10-14 -1. **Сертификаты251:** issuance250 принят; раскрыть в UI включение обоих SSL-сервисов и DNS A-sync. Затем определить scope для automatic renewal/CA revoke/remote publishing/multi-instance; эти сценарии текущим выпуском не доказаны. +1. **Сертификаты252:** issuance250 и UX/Stepper251 приняты. Исправить disabled/strict-ID и renewal result/unknown-expiry guards, затем профильная проверка. Реальное renewal/CA revoke/remote publishing/multi-instance остаются отдельными scope. 2. **Профильный контроль:** для новых изменений выполнять затронутые SQL/API/UI проверки. Общая регрессия192 выполнена; не повторять её без изменений общей основы или нового основания. 3. **Внешние зависимости:** Portal issuer/login/revoke, Telegram bot/chat/разрешённое сообщение, клиентские ОС, независимые WAN/public IPv6 и scale/multi-instance — отдельные группы по таблице выше. Ограничения текущего стенда не превращать в обещание приёмки всех конфигураций. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 61d2130e..4eb108f7 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-14: 250 — production ACME принят на точном mmt250-c22a9715.pngs.top/CHR104: Portal/UI один issue POST → done; DNS-01, native import/private key, trusted TLS/SAN и REST HTTPS200. Native services/certificates/files/export и ACME settings восстановлены, собственные job/A/TXT отсутствуют; оба CHR доступны. Backend249/frontend248 unchanged. Следующий251 — раскрыть в форме выпуска автоматическое назначение SSL-сервисам и DNS A-sync, затем проверить UI; renewal/CA revoke/multi-instance отдельно. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: 251 — форма выпуска раскрывает включение www-ssl/api-ssl и DNS A-sync, trust-store switches имеют доступные имена. Общий адаптер ReUI Stepper исправляет ARIA/уникальные ID в сертификатах, серверах и бэкапах без правок vendor/styles/motion. 69 unique E2E, TypeScript/lint/build passed; live PC/mobile keyboard/scoped axe4 violations0, writes0. Backend249/frontend ux-certificates251. Следующий252 — disabled/strict-ID guards сертификатов и достоверность результата renewal; реальное renewal ещё открыто. Этап12.5 открыт. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -4152,6 +4152,22 @@ Real Portal/browser API, provider local verified: создан один job ро Runtime backend ux-backup234/frontend ux-routing218 healthy; новое application image для volume-only fix не требовалось. Пароли CHR не менялись, S3 mutations0 в235, configs body/JWT не опубликованы, private local manifest удалён. Исходные10 missing local files не восстановлены и records не удалены. Force-recreate — не host reboot/power loss/fsync/DR приёмка. Далее236 — UX недоступных local files, затем version retention границы и оставшиеся7 группы матрицы; multi-instance guard не принимается. Этап12.5 открыт. +## 12.5.251 — понятные последствия выпуска и доступные мастера ReUI (2026-10-14) + +После250 форма явно сообщает: импорт назначает сертификат обоим www-ssl/api-ssl и включает их; trust-store переключатели задают trust-store, не отменяют назначение. Итоговая сводка показывает DNS A-sync как попытку синхронизации с IPv4 сервера и сохранение CNAME. Сетевая логика/API не менялись. Оба trust-store switches получили доступные имена. + +Scoped axe live preview выявил прежние aria-required-children/parent и aria-valid-attr-value: установленный Stepper root role=tablist охватывал nav и контент, nav мешал родительской роли tabs, Content не передавал id/role/aria props. [API](https://reui.io/docs/components/base/stepper?ref=mcp), [preview](https://reui.io/components/stepper?ref=mcp) и примеры прочитаны через MCP; актуальный @reui/stepper прочитан shadcn view и имеет те же пропуски. Установка/переопределение vendor не решает их и не выполнена. + +Добавлен reui-kit/accessible-stepper: переиспользует установленные компоненты/keyboard/focus/styles, добавляет прозрачные display:contents обёртки с tablist/tabpanel, rootgroup без неподходящего aria-orientation, React useId для tab/panel namespace. Контент forceMount с штатным hidden сохраняет все IDREF. Vendor файл, shared theme и animation timings не менялись. Все три потребителя — сертификаты, создание/редактирование серверов, создание бэкапа — переведены на адаптер. + +69 уникальных E2E:57 existing certificates issue/layout + servers + backup operations и12 backup job + новые3 ARIA сценария. Первый набор57 прошёл2.1m, второй12 —32.1s; первоначальные7 issue повторяются в57 и не суммируются. Проверены операции/checkpoints/отказы/права/контекст, серверный wizard320/390/1440, certificate layout320/390/1440, связь каждой tab со своей существующей panel/unique IDs/одна видимая панель и4 ARIA rules во всех трёх формах. TypeScript и scoped ESLint passed. Не заявляем полного axe/WCAG аудита всех трёх страниц. + +Production frontend ux-certificates251 собран и развёрнут, source528 matched, backend ux-containers249 healthy сохранён, PostgreSQL/Portal не пересоздавались. До обнаружения ARIA дефекта выполнялись промежуточные сборки copy/labels; окончательный образ содержит adapter и все последние изменения. Это повтор из-за новых найденных ошибок, не дополнительные принятые сценарии. Для следующих сложных форм сначала локальный scoped axe, затем production build. [Deployment](ux-ui/acceptance/certificates251-deployment.json). + +Настоящий Portal/live preview1440/390: trust www переключается Space, step3/4 показывают назначение SSL независимо от trust toggle и DNS/CNAME; нет overflow/JS errors, четыре scoped axe WCAG2/2.1/2.2 scans violations0. Формы отменены Escape, API writes0/никаких выпусков/новых DNS/native objects. [Live UI](ux-ui/acceptance/certificates251-live-ui.json), [desktop](ux-ui/screens/certificates251-review-desktop.png), [mobile](ux-ui/screens/certificates251-review-mobile.png). Mobile screenshot просмотрен. ReUI checklist пройден в изменённом scope: reuse/семантика/security/scroll/typecheck/lint; неизменённые части не объявляются заново принятыми. + +Следующий252: чтение certificates-service поID всё ещё принимает numeric prefix и disabled row; renewal collector опрашивает его. Collector после runIssueJob прибавляет renewed без чтения terminal job status, хотя runner записывает failed и возвращается без throw; legacy parser подменяет неизвестный срок0. Исправить эти достоверные code-path дефекты и проверить соответствующие service/SQL случаи. Реальная повторная выдача/renewal/CA revoke/multi-instance остаются отдельными неподтверждёнными вариантами, первичный ACME250 уже принят. + ## 12.5.250 — production ACME / Cloudflare / TLS через реальный UI (2026-10-14) Пользователь предоставил pngs.top/Cloudflare и разрешил поддомены с префиксом mmt*. После уточнения звёздочки получено согласие на точное имя mmt250-c22a9715.pngs.top и временное назначение www-ssl/api-ssl с откатом. Cloudflare token verify и exact zone query200/success, token/zone active/account matched; оба собственных DNS имени до начала имели0 records. Ключ/почта/account ID только в ignored private fixture; на Debian ключ поступил через разрешённый временный API settings, отдельный secret файл туда не передавался. Native/private settings baseline снят до начала. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index b7fb6c7f..a9898cdb 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-10 -Актуальное продолжение 2026-10-14: 250 — production ACME принят на точном mmt250-c22a9715.pngs.top/CHR104: Portal/UI один issue POST → done; DNS-01, native import/private key, trusted TLS/SAN и REST HTTPS200. Native services/certificates/files/export и ACME settings восстановлены, собственные job/A/TXT отсутствуют; оба CHR доступны. Backend249/frontend248 unchanged. Следующий251 — раскрыть в форме выпуска автоматическое назначение SSL-сервисам и DNS A-sync, затем проверить UI; renewal/CA revoke/multi-instance отдельно. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: 251 — форма выпуска раскрывает включение www-ssl/api-ssl и DNS A-sync, trust-store switches имеют доступные имена. Общий адаптер ReUI Stepper исправляет ARIA/уникальные ID в сертификатах, серверах и бэкапах без правок vendor/styles/motion. 69 unique E2E, TypeScript/lint/build passed; live PC/mobile keyboard/scoped axe4 violations0, writes0. Backend249/frontend ux-certificates251. Следующий252 — disabled/strict-ID guards сертификатов и достоверность результата renewal; реальное renewal ещё открыто. Этап12.5 открыт. | Параметр | Проверенное состояние | | --- | --- | @@ -34,6 +34,22 @@ OSPF84: real GRE Full adjacency/private routes/Ping3/3 и4 live PC/320px URL/bro BFD85: Up/Full/own route/Ping,4 live UI и loss/withdrawal/recovery приняты; exact own cleanup8 коллекций×2 passed. Withdrawal5,245ms не подтверждает sub-second BFD timing; этот вопрос открыт. Runtime routing83 без новой сборки. [Отчёт](ux-ui/acceptance/ospf-bfd-loss-2026-10-09.json). +## 12.5.251 — понятные последствия выпуска и доступные мастера ReUI (2026-10-14) + +После250 форма явно сообщает: импорт назначает сертификат обоим www-ssl/api-ssl и включает их; trust-store переключатели задают trust-store, не отменяют назначение. Итоговая сводка показывает DNS A-sync как попытку синхронизации с IPv4 сервера и сохранение CNAME. Сетевая логика/API не менялись. Оба trust-store switches получили доступные имена. + +Scoped axe live preview выявил прежние aria-required-children/parent и aria-valid-attr-value: установленный Stepper root role=tablist охватывал nav и контент, nav мешал родительской роли tabs, Content не передавал id/role/aria props. [API](https://reui.io/docs/components/base/stepper?ref=mcp), [preview](https://reui.io/components/stepper?ref=mcp) и примеры прочитаны через MCP; актуальный @reui/stepper прочитан shadcn view и имеет те же пропуски. Установка/переопределение vendor не решает их и не выполнена. + +Добавлен reui-kit/accessible-stepper: переиспользует установленные компоненты/keyboard/focus/styles, добавляет прозрачные display:contents обёртки с tablist/tabpanel, rootgroup без неподходящего aria-orientation, React useId для tab/panel namespace. Контент forceMount с штатным hidden сохраняет все IDREF. Vendor файл, shared theme и animation timings не менялись. Все три потребителя — сертификаты, создание/редактирование серверов, создание бэкапа — переведены на адаптер. + +69 уникальных E2E:57 existing certificates issue/layout + servers + backup operations и12 backup job + новые3 ARIA сценария. Первый набор57 прошёл2.1m, второй12 —32.1s; первоначальные7 issue повторяются в57 и не суммируются. Проверены операции/checkpoints/отказы/права/контекст, серверный wizard320/390/1440, certificate layout320/390/1440, связь каждой tab со своей существующей panel/unique IDs/одна видимая панель и4 ARIA rules во всех трёх формах. TypeScript и scoped ESLint passed. Не заявляем полного axe/WCAG аудита всех трёх страниц. + +Production frontend ux-certificates251 собран и развёрнут, source528 matched, backend ux-containers249 healthy сохранён, PostgreSQL/Portal не пересоздавались. До обнаружения ARIA дефекта выполнялись промежуточные сборки copy/labels; окончательный образ содержит adapter и все последние изменения. Это повтор из-за новых найденных ошибок, не дополнительные принятые сценарии. Для следующих сложных форм сначала локальный scoped axe, затем production build. [Deployment](ux-ui/acceptance/certificates251-deployment.json). + +Настоящий Portal/live preview1440/390: trust www переключается Space, step3/4 показывают назначение SSL независимо от trust toggle и DNS/CNAME; нет overflow/JS errors, четыре scoped axe WCAG2/2.1/2.2 scans violations0. Формы отменены Escape, API writes0/никаких выпусков/новых DNS/native objects. [Live UI](ux-ui/acceptance/certificates251-live-ui.json), [desktop](ux-ui/screens/certificates251-review-desktop.png), [mobile](ux-ui/screens/certificates251-review-mobile.png). Mobile screenshot просмотрен. ReUI checklist пройден в изменённом scope: reuse/семантика/security/scroll/typecheck/lint; неизменённые части не объявляются заново принятыми. + +Следующий252: чтение certificates-service поID всё ещё принимает numeric prefix и disabled row; renewal collector опрашивает его. Collector после runIssueJob прибавляет renewed без чтения terminal job status, хотя runner записывает failed и возвращается без throw; legacy parser подменяет неизвестный срок0. Исправить эти достоверные code-path дефекты и проверить соответствующие service/SQL случаи. Реальная повторная выдача/renewal/CA revoke/multi-instance остаются отдельными неподтверждёнными вариантами, первичный ACME250 уже принят. + ## 12.5.250 — production ACME / Cloudflare / TLS через реальный UI (2026-10-14) Пользователь предоставил pngs.top/Cloudflare и разрешил поддомены с префиксом mmt*. После уточнения звёздочки получено согласие на точное имя mmt250-c22a9715.pngs.top и временное назначение www-ssl/api-ssl с откатом. Cloudflare token verify и exact zone query200/success, token/zone active/account matched; оба собственных DNS имени до начала имели0 records. Ключ/почта/account ID только в ignored private fixture; на Debian ключ поступил через разрешённый временный API settings, отдельный secret файл туда не передавался. Native/private settings baseline снят до начала. diff --git a/docs/ux-ui/acceptance/certificates251-deployment.json b/docs/ux-ui/acceptance/certificates251-deployment.json new file mode 100644 index 00000000..47d5ff1e --- /dev/null +++ b/docs/ux-ui/acceptance/certificates251-deployment.json @@ -0,0 +1,29 @@ +{ + "date": "2026-10-14", + "block": "12.5.251", + "containers": [ + { + "name": "mmapp-test-backend", + "image": "mmapp-test/backend:ux-containers249", + "imageId": "sha256:b0d1526c683c0ce02dcac89087e13a917e27f743af192d2fda4fe26e4f11f056", + "running": true, + "health": "healthy" + }, + { + "name": "mmapp-test-frontend", + "image": "mmapp-test/frontend:ux-certificates251", + "imageId": "sha256:efe3023ec776516fd372417def52f4c59ed4d025bc9f7acf43eefdcec2c9e544", + "running": true, + "health": "not-configured" + } + ], + "frontendSourceAudit": [ + { + "kind": "frontend", + "matched": 528 + } + ], + "frontendBuildExit": 0, + "backendChanged": false, + "gitImagePush": false +} diff --git a/docs/ux-ui/acceptance/certificates251-live-ui.json b/docs/ux-ui/acceptance/certificates251-live-ui.json new file mode 100644 index 00000000..d7ec7bf6 --- /dev/null +++ b/docs/ux-ui/acceptance/certificates251-live-ui.json @@ -0,0 +1,27 @@ +{ + "date": "2026-10-14", + "block": "12.5.251", + "realPortalLogin": true, + "noMocks": true, + "views": [ + { + "width": 1440, + "keyboardToggle": true, + "sslAndDnsDisclosed": true, + "step3Violations": [], + "step4Violations": [], + "overflow": false + }, + { + "width": 390, + "keyboardToggle": true, + "sslAndDnsDisclosed": true, + "step3Violations": [], + "step4Violations": [], + "overflow": false + } + ], + "writes": [], + "pageErrors": [], + "step3Audit": [] +} diff --git a/docs/ux-ui/screens/certificates251-review-desktop.png b/docs/ux-ui/screens/certificates251-review-desktop.png new file mode 100644 index 00000000..39ab618e Binary files /dev/null and b/docs/ux-ui/screens/certificates251-review-desktop.png differ diff --git a/docs/ux-ui/screens/certificates251-review-mobile.png b/docs/ux-ui/screens/certificates251-review-mobile.png new file mode 100644 index 00000000..6d612380 Binary files /dev/null and b/docs/ux-ui/screens/certificates251-review-mobile.png differ diff --git a/tests/e2e/stepper-accessibility.spec.ts b/tests/e2e/stepper-accessibility.spec.ts new file mode 100644 index 00000000..dd230b59 --- /dev/null +++ b/tests/e2e/stepper-accessibility.spec.ts @@ -0,0 +1,41 @@ +import { test, expect, type Locator, type Page } from "@playwright/test" +import axe from "axe-core" +import { certificateRoutes, openIssue } from "./fixtures/certificate-issue" +import { setupBackups } from "./fixtures/backups" +import { openBackup } from "./fixtures/backup-job" + +async function check(page: Page, dialog: Locator) { + const tabs = dialog.getByRole("tablist", { name: "Шаги формы" }).getByRole("tab") + const ids: string[] = [] + for (const tab of await tabs.all()) { + const id = await tab.getAttribute("id"), panelId = await tab.getAttribute("aria-controls") + expect(id).toBeTruthy(); expect(panelId).toBeTruthy(); ids.push(id!, panelId!) + expect(await page.evaluate(id => document.getElementById(id!)?.getAttribute("aria-labelledby"), panelId)).toBe(id) + } + expect(new Set(ids).size).toBe(ids.length) + for (const tab of await tabs.all()) { + await tab.click() + await expect(tab).toHaveAttribute("aria-selected", "true") + await expect(dialog.getByRole("tabpanel")).toHaveCount(1) + expect(await dialog.getByRole("tabpanel").getAttribute("id")).toBe(await tab.getAttribute("aria-controls")) + } + await page.addScriptTag({ content: axe.source }) + const violations = await dialog.evaluate(async element => { + const result = await (window as unknown as { axe: typeof axe }).axe.run(element, { runOnly: { type: "rule", values: ["aria-required-children", "aria-required-parent", "aria-valid-attr-value", "aria-valid-attr"] } }) + return result.violations.map(v => v.id) + }) + expect(violations).toEqual([]) +} + +test("Stepper: выпуск — панели связаны со всеми вкладками", async ({ page }) => { + await certificateRoutes(page); await check(page, await openIssue(page)) +}) +test("Stepper: backup — панели связаны со всеми вкладками", async ({ page }) => { + await setupBackups(page); await check(page, await openBackup(page)) +}) +test("Stepper: создание сервера — панели связаны со всеми вкладками", async ({ page }) => { + await page.route("**/health", r => r.fulfill({ json: { ok: true } })) + await page.route("**/api/**", r => r.fulfill({ json: new URL(r.request().url()).pathname === "/api/auth/config" ? { required: false } : new URL(r.request().url()).pathname === "/api/servers" ? [] : {} })) + await page.goto("/servers"); await page.getByRole("button", { name: "Добавить сервер", exact: true }).click() + await check(page, page.getByRole("dialog")) +})