From fe8591840728dc16661d7db202e9054e1d50968a Mon Sep 17 00:00:00 2001 From: Vassiliy Yegorov Date: Fri, 3 Jul 2026 16:40:22 +0700 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=B4=D0=B5=D1=82=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=A4=D0=B0=D0=B7=D1=8B=201C=20(React=20SPA)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-07-03-dns-autoresolver-design.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/docs/superpowers/specs/2026-07-03-dns-autoresolver-design.md b/docs/superpowers/specs/2026-07-03-dns-autoresolver-design.md index 41a3d80..2473f02 100644 --- a/docs/superpowers/specs/2026-07-03-dns-autoresolver-design.md +++ b/docs/superpowers/specs/2026-07-03-dns-autoresolver-design.md @@ -233,3 +233,80 @@ check_runs(id uuid pk, domain_id uuid fk→domains, result jsonb /*сводка ### Разбивка Реализуется **одним планом** `phase1b-persistence-api` (по решению — без под-планов). + +## Фаза 1C — детализация (React SPA) + +Строится поверх готового REST API (Фаза 1B). Полный UI на весь API. + +### Стек + +- **Vite + React + TypeScript**, **react-router** (v6+), **TanStack Query v5** (server-state). +- **Tailwind CSS + shadcn/ui** (компоненты копируются в проект, `components.json`, alias `@`). +- Формы: **react-hook-form + zod**. +- Тесты: **Vitest + React Testing Library**. +- В dev — Vite `server.proxy` `/api` → `http://localhost:8080`. В prod — `vite build` → `dist/` + вшивается в Go-бинарь (`embed.FS`) и отдаётся тем же сервером (same-origin, CORS не нужен). + +### Эстетическое направление + +**Refined technical console.** Тёмная тема по умолчанию, плотная точная сетка, инженерный тон. +- Типографика: характерный UI-гротеск (НЕ Inter/Roboto/system) + **моноширинный** для DNS-записей, + зон и дифов (например IBM Plex Mono / JetBrains Mono). Пары: display для заголовков, mono для данных. +- Семантическое цветовое кодирование дифа: **add** (emerald), **update** (amber), **delete/prune** + (rose), **in-sync** (muted/slate), **read-only NS/SOA** (dimmed). Единая палитра через CSS-переменные. +- Атмосфера: тонкие текстуры/границы, аккуратные тени, без generic purple-on-white. Диф — центральный, + самый выразительный экран. + +### Структура (`web/`) + +``` +web/ + vite.config.ts — alias @, proxy /api → :8080, build outDir dist + components.json — shadcn + src/ + main.tsx, App.tsx — QueryClientProvider + router + lib/ — utils, константа DEFAULT_PROJECT_ID = seed …0002 + api/ + client.ts — типизированная fetch-обёртка (base /api/v1/projects/{pid}) + types.ts — зеркало Go DTO (Account, Template, Domain, Changeset, RecordView …) + hooks/ — TanStack Query: useAccounts/useTemplates/useDomains/useCheck/useApply/useImport + components/ + ui/ — shadcn-компоненты + Layout.tsx, DiffView.tsx, RecordEditor.tsx + pages/ + DomainsPage, DomainDiffPage, AccountsPage, TemplatesPage +``` + +### Экраны + +- **Domains** — список доменов, импорт зон по учётке (`POST /domains/import`), привязка шаблона + (`PATCH /domains/{id}`), переход к дифу. +- **DomainDiff** (`/domains/:id`) — `GET .../check` → **DiffView**: секции Updates / Prunes / ReadOnly + + счётчик in-sync. Кнопка **Apply**: чекбокс «применить удаления (prune)» — **по умолчанию выключен**, + требует явного подтверждения (визуально акцентированное предупреждение). `POST .../apply`. +- **Accounts** — CRUD учёток. Форма создания: поле API-ключа (secret, только на вход), **инструкция + + ссылка**, где получить ключ в панели Selectel. Секрет никогда не показывается обратно. +- **Templates** — CRUD шаблонов + **RecordEditor** (редактор набора записей `doc.records`: type/name/ttl/values, + включая SRV для почтового автодискавера). + +### Мультитенантность + +Фаза 1C — без логина: `DEFAULT_PROJECT_ID` (seed `…0002`) зашит в клиенте. Логин и переключение +проектов — Фаза 2 (тогда pid берётся из сессии). + +### Подача в prod (Go) + +- `internal/web/web.go` — `embed.FS` каталога `web/dist` + handler со **SPA-fallback** на `index.html`. +- `cmd/server` монтирует статику на `/`, API остаётся на `/api/v1` (роутинг chi: API-роуты имеют приоритет, + всё прочее → SPA). + +### Тестирование 1C + +- `api/client` — юниты на мок `fetch` (пути, сериализация, обработка ошибок). +- `DiffView` — рендер секций Updates/Prunes/ReadOnly, цветовое кодирование. +- Apply-guard — по умолчанию prune выключен; включается только явным действием. +- Go `internal/web` — статика отдаётся, `/api/*` не перехватывается, SPA-fallback на неизвестный путь. + +### Разбивка + +Один план `phase1c-react-spa`.