# Уточнения к архитектуре модификаторов — расхождения с фактическим кодом Не принимаю предыдущие ответы за истину. Сверка с реальным кодом выявила расхождения. Прошу пересмотреть/уточнить. ## Факт №1: `OperationSpec` — это алиас `lib.OperationSpec`, не локальный тип В `TOOLS/resource-generator/internal/types/types.go`: ```go type OperationSpec = lib.OperationSpec type ParamSpec = lib.ParamSpec ``` Канонический YAML-контракт лежит в `TOOLS/lib/types.go` (пакет `tf-tools/lib`), где уже определены `OperationSpec` (Name/ID/Kind/Action/Modifier/Subresource/Man/Params) и `ParamSpec`. Ошибка в прошлом ответе: «добавить в types.go:39» — НЕ указано, что это `lib`. Новые поля `delete_strategy` / `idempotency` / `delete_params` должны быть в `TOOLS/lib/types.go`, иначе yaml-generator (который тоже импортирует lib) и resource-generator разойдутся. Вопрос: подтверждаешь, что новый контракт добавляется в `lib/types.go\` (OperationSpec), а `resource-generator` получает его через алиас? Или нужно отдельное resource-generator-специфичное поле (не в lib, а в GenModifier)? Где граница: что в lib, что локально в GenModifier? ## Факт №2: `normalizeUniversalValueV6` — приватная, живёт в core, принимает core-структуру Прошлый ответ: «сравнивать desired vs current после normalizeUniversalValueV6». Но: - `normalizeUniversalValueV6(val string, param universalCfsParam)` — **приватная** (маленькая буква); - принимает `universalCfsParam` (структуру пакета `core`); - сравнение pre-check «desired == current» предполагалось в `resources_core` (там `RunOperationByCodeWithTimeout`) или в шаблоне модификатора. Вопрос: ГДЕ правильно делать pre-check и нормализованное сравнение? - вариант A: в `core` (там доступны и cfsParams, и normalize), экспортировать сравнение; - вариант B: в `resources_core` — тогда нужен экспортированный компаратор (`JSONStringsEquivalent` там уже есть), но `universalCfsParam` недоступен; - вариант C: сравнение только через `JSONStringsEquivalent` по JSON-строкам, без `normalizeUniversalValueV6`? (но тогда `" 5"` vs `"5"`, `true` vs `1` дадут ложный diff). Как совместить нормализацию типов (bool→"true", int→"5") с местом, где сравнение происходит? Конкретный файл+функция. ## Дополнительные сомнения (прошу подтвердить/опровергнуть) 1. **Idempotency pre-check и «полный payload» конфликтуют?** Если desired==current → skip. Но при этом «полный payload» не шлётся вообще (skip). Это согласуется? Или при расхождении одного поля всё равно слать полный payload (и это нормализует всё)? 2. **`delete_strategy: inverse` + параметр, у которого НЕЛЬЗЯ обнулить** (напр. `virtualServicesCount` integer>0): прошлый ответ — «inverse недопустим, fail-fast». Но что если inverse-стратегия нужна только для ЧАСТИ полей, а не для всех? Т.е. `delete_params` покрывает `needEnableAVI:false`, а `virtualServicesCount` просто остаётся как есть. Допустимо ли «частичный inverse» (обратить только обратимое, остальное не трогать)? Или inverse обязан покрывать все поля? 3. **`noop_warn` (дефолт) — всегда ли безопасен?** Удаление модификатора из state при оставшемся эффекте на платформе — это drift. Допустимо ли вообще иметь `noop_warn` как ДЕФОЛТ, или для необратимых (ip_space) правильнее дефолт `error` (запретить destroy, пока не разберутся)? Что каноничнее? Ответ — кратко, по пунктам.