HISTORY: сохранить Q&A с Sonnet по email-идентичности

This commit is contained in:
“Naeel”
2026-08-14 09:36:14 +04:00
parent dc1aaa6652
commit 87ecf3b5ca
+27
View File
@@ -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-сессией.