# Анализ coupling кода (console/) — 2026-05-01

## Граф зависимостей (DAG)

```
model  runtime
  │      │
  └──────┴── fission ─── cloud ─── api (handlers, server, auth...)
                                     │
                                    ui
```

Цикличных зависимостей нет. Направление правильное.

---

## Проблемы coupling (по приоритету)

### 🔴 HIGH — api/handlers.go — смешение HTTP-слоя и оркестрации Fission

Файл выполняет одновременно:
- HTTP-роутинг и валидацию запросов
- Построение `map[string]any{}` манифестов для Package, Function, HTTPTrigger прямо в handler-е
- Логику отката (Delete при ошибке) — транзакционная оркестрация
- Логику смены Package при обновлении кода (cache-bust через новое имя)

**Правильно:** всё что ниже `json.Decode(&req)` в `handleCreateFunction` — задача пакета `fission`.
Handler должен вызывать `fission.CreateFunction(ctx, dyn, ns, params)`, а не строить K8s-схемы вручную.
Fission-специфичная схема сейчас размазана между `handlers.go` и `fission/`.

### 🟡 MEDIUM — api/package.go берёт *Server вместо http.Client

    func extractPackageSourceCode(ctx context.Context, s *Server, ...) string
    func fetchPackageArchive(ctx context.Context, s *Server, ...) ([]byte, error)

Обе функции используют только `s.http`. Зависимость от всего `*Server` — излишняя.
Делает функции нетестируемыми без создания полного Server.

### 🟡 MEDIUM — Кэш токенов живёт на Server

`tokenMu`, `cachedJWT`, `tokenExpAt`, `tokenCache` — auth-сервис встроен в транспортный объект.
При росте логики авторизации потребует правки Server.

### 🟢 LOW — Конфиг линтеров inline в ai_check.go

Карта `langs := map[string]linterCfg{...}` пересоздаётся при каждом вызове handler-а.

### 🟢 LOW — Legacy-роуты без auth-middleware в server.go

    mux.HandleFunc("/api/functions", s.handleFunctionsRoot)                // без auth!
    mux.HandleFunc("/console/api/functions", auth(s.handleFunctionsRoot))  // с auth

Одни и те же handlers зарегистрированы дважды — легко пропустить при добавлении нового роута.

---

## Что работает хорошо (не трогать)

| Пакет | Оценка |
|---|---|
| model/types.go | Чистый leaf-пакет, нет внутренних импортов |
| runtime/ | Pure функции, нет зависимостей на api/cloud/fission — идеально |
| fission/environment.go | Хорошая инкапсуляция EnsureEnvironment + Cleanup |
| cloud/tenant.go | Singleflight + semaphore + cache — правильно изолировано |
| cloud/quota.go, network.go | Атомарные, читаемые, независимые |

---

## Вывод

Глобального рефакторинга не нужно — структура пакетов правильная.
Основная боль: handlers.go (~700 строк) делает слишком много.
Решение: добавить в пакет fission функции CreateFunction / UpdateFunction / DeleteFunction,
которые инкапсулируют построение K8s-манифестов.
Handlers превратятся в тонкий HTTP-слой (~200 строк).
Остальное — мелочи.
~~~блока есть вложенные ` ``` ` — они его разрывают. Вот вариант с `~~~` снаружи:

~~~markdown
# Анализ coupling кода (console/) — 2026-05-01

## Граф зависимостей (DAG)

```
model  runtime
  │      │
  └──────┴── fission ─── cloud ─── api (handlers, server, auth...)
                                     │
                                    ui
```

Цикличных зависимостей нет. Направление правильное.

---

## Проблемы coupling (по приоритету)

### 🔴 HIGH — api/handlers.go — смешение HTTP-слоя и оркестрации Fission

Файл выполняет одновременно:
- HTTP-роутинг и валидацию запросов
- Построение `map[string]any{}` манифестов для Package, Function, HTTPTrigger прямо в handler-е
- Логику отката (Delete при ошибке) — транзакционная оркестрация
- Логику смены Package при обновлении кода (cache-bust через новое имя)

**Правильно:** всё что ниже `json.Decode(&req)` в `handleCreateFunction` — задача пакета `fission`.
Handler должен вызывать `fission.CreateFunction(ctx, dyn, ns, params)`, а не строить K8s-схемы вручную.
Fission-специфичная схема сейчас размазана между `handlers.go` и `fission/`.

### 🟡 MEDIUM — api/package.go берёт *Server вместо http.Client

    func extractPackageSourceCode(ctx context.Context, s *Server, ...) string
    func fetchPackageArchive(ctx context.Context, s *Server, ...) ([]byte, error)

Обе функции используют только `s.http`. Зависимость от всего `*Server` — излишняя.
Делает функции нетестируемыми без создания полного Server.

### 🟡 MEDIUM — Кэш токенов живёт на Server

`tokenMu`, `cachedJWT`, `tokenExpAt`, `tokenCache` — auth-сервис встроен в транспортный объект.
При росте логики авторизации потребует правки Server.

### 🟢 LOW — Конфиг линтеров inline в ai_check.go

Карта `langs := map[string]linterCfg{...}` пересоздаётся при каждом вызове handler-а.

### 🟢 LOW — Legacy-роуты без auth-middleware в server.go

    mux.HandleFunc("/api/functions", s.handleFunctionsRoot)                // без auth!
    mux.HandleFunc("/console/api/functions", auth(s.handleFunctionsRoot))  // с auth

Одни и те же handlers зарегистрированы дважды — легко пропустить при добавлении нового роута.

---

## Что работает хорошо (не трогать)

| Пакет | Оценка |
|---|---|
| model/types.go | Чистый leaf-пакет, нет внутренних импортов |
| runtime/ | Pure функции, нет зависимостей на api/cloud/fission — идеально |
| fission/environment.go | Хорошая инкапсуляция EnsureEnvironment + Cleanup |
| cloud/tenant.go | Singleflight + semaphore + cache — правильно изолировано |
| cloud/quota.go, network.go | Атомарные, читаемые, независимые |

---

## Вывод

Глобального рефакторинга не нужно — структура пакетов правильная.
Основная боль: handlers.go (~700 строк) делает слишком много.
Решение: добавить в пакет fission функции CreateFunction / UpdateFunction / DeleteFunction,
которые инкапсулируют построение K8s-манифестов.
Handlers превратятся в тонкий HTTP-слой (~200 строк).
Остальное — мелочи.

----------- «один блок, тильды снаружи» — я пойму.
И кстати, Plan может писать в файл — но только в /memories/session/plan.md (session memory).
