# Задачи после code review (2026-04-19) Приоритет: **критично** → сделать до merge в master. --- ## КРИТИЧНО ### 1. k8s ошибки протекают как 502 — нужны правильные HTTP коды **Файл:** `console/main.go` **Проблема:** `apierrors.IsAlreadyExists` и `apierrors.IsInvalid` не перехватываются → клиент получает 502 вместо 409/400. **Что сделать:** - В `handleCreateFunction`: перехватить `apierrors.IsAlreadyExists` → HTTP 409 - В `handleCreateFunction`: перехватить `apierrors.IsInvalid` → HTTP 400 - Аналогично проверить `handleUpdateFunction` **Пример:** ```go if apierrors.IsAlreadyExists(err) { writeJSONError(w, http.StatusConflict, fmt.Sprintf("function %q already exists", req.Name)) return } if apierrors.IsInvalid(err) { writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("invalid function spec: %v", err)) return } ``` --- ### 2. Валидация имени функции на уровне API **Файл:** `console/main.go` **Проблема:** имя с пробелами/спецсимволами уходит в k8s и возвращается 502. **Что сделать:** добавить regex-валидацию сразу после парсинга запроса в `handleCreateFunction` и `handleUpdateFunction`. **Пример:** ```go var validName = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]*[a-z0-9])?$`) if !validName.MatchString(req.Name) || len(req.Name) > 63 { writeJSONError(w, http.StatusBadRequest, "invalid function name: must match ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ and be <= 63 chars") return } ``` --- ## ВАЖНО (не блокирует merge) ### 3. Reaper: сканирование orphan packages **Файл:** `console/main.go` **Проблема:** если под упал в момент удаления функции, Package может остаться без matching Function. **Что сделать:** в цикле reaper дополнительно итерироваться по packages и удалять те, у которых нет соответствующей function с тем же именем (по конвенции `{fn-name}-pkg`). --- ### 4. Лимит размера кода **Файл:** `console/main.go` **Проблема:** нет ограничения на размер `req.Code` — можно залить мегабайты. **Что сделать:** после парсинга тела запроса добавить: ```go const maxCodeSize = 1 << 20 // 1 MB if len(req.Code) > maxCodeSize { writeJSONError(w, http.StatusBadRequest, "code exceeds 1MB limit") return } ``` --- ### 5. Namespace race condition **Файл:** `console/main.go` **Проблема:** при одновременных первых запросах одного пользователя `Create(namespace)` может вернуть `AlreadyExists`. **Что сделать:** убедиться что в `ensureNamespace` (или аналогичной функции) ошибка `AlreadyExists` при создании namespace игнорируется: ```go if err != nil && !apierrors.IsAlreadyExists(err) { return err } ``` --- ## НЕ СРОЧНО ### 6. Тест-скрипт: RUN_ID уникальность **Файл:** `tests_v2.sh` **Проблема:** два параллельных запуска с одинаковым timestamp дают одинаковый RUN_ID → Block D FAIL. **Что сделать:** добавить случайный суффикс: ```bash RUN_ID=$(date +%s%N | sha256sum | head -c 8) ``` --- ## Документировать (без кода) - Python env: `def main():` без аргументов — задокументировать в README/examples - Версионирование функций — не делать сейчас, отложить