diff --git a/HISTORY/2026-08-14-session-log.md b/HISTORY/2026-08-14-session-log.md index c68df88..e3608db 100644 --- a/HISTORY/2026-08-14-session-log.md +++ b/HISTORY/2026-08-14-session-log.md @@ -173,3 +173,30 @@ digest `sha256:b4d1dccda75a67e1a5db3887576e1112993d6485504e683d0fa82a2374bca99b` `admin auth billing conf gosqs interfaces metrics models persistence router tenant ui utils`. `app/` не тронут (проверено: rootHandler на месте, app/ui/static и info.html целы). Оставлено: app, cmd, doc, Dockerfile, go.mod, go.sum, HISTORY, Makefile, README.md, secrets. + +--- + +## Архитектурный разбор (Claude Sonnet) — переход идентичности на email (14.08.2026) + +**Запрос к Sonnet**: файлы только `app/auth/jwt.go`, `app/tenant/tenant_store.go`, `app/admin/admin.go`, +`app/gosqs/tenant_helpers.go`, `app/persistence/redis.go`, `app/cmd/goaws.go`, +`app/auth/auth_middleware.go`, `app/ui/index.html`. + +**Ответ Sonnet (выводы)**: +1. Сломается: `TenantIDFromSub()` в jwt.go; вызов в `jwtAuth` (admin.go ~236); `access_key/secret_key` + в ответе jwtAuth; `GetBySub` в `jwtMiddleware` (~288); `bySub` → `byEmail` в TenantStore + (NewTenantStore, CreateFromJWT, Delete, LoadTenant, GetBySub). +2. Пересчёт легаси при 0 очередях безопасен, но ОБЯЗАТЕЛЬНО: удалить старый тенант из Redis + (`ssq:tenants` по старому ID) и сохранить новый — иначе после рестарта старые рандомные ключи оживут. + Весь пересчёт — под `s.mu.Lock()`. +3. Детерминированные функции — в jwt.go; byEmail-индекс — в tenant_store.go; LoadTenant индексирует + по Email только при `Email != ""` (защита от коллизии `byEmail[""]` с демо-тенантом CreateFixed). +4. Дыра — orphan AccessKey в byAccessKey: при пересчёте удалять из byAccessKey ДО добавления нового. +5. Критичное неучтённое: (a) email может быть пустым → проверка в jwtAuth (400), не в ParseJWTClaims; + (b) QueueUrl содержит TenantID — при смене ID URL меняется, у клиентов захардкоженные URL сломаются + (сейчас очередей нет — не критично); (c) демо-тенант без Email не должен попадать в byEmail. + +**Решение (принято)**: все пункты включаем в v0.1.28. Токен — только аутентификация; +email из JWT детерминированно задаёт TenantID/AccessKey/SecretKey; рандома нет; +ключи на экране не светятся — только по кнопке в модалке с подсказкой; +`POST /ui/api/auth` перестаёт отдавать ключи; новый `GET /ui/api/credentials` под JWT-сессией.