10 KiB
Модуль объекта отчёта в расширении
Статус: чтение, точное разрешение владельца и контролируемая запись короткого фрагмента поддержаны для доказанного hash-keyed saved-state маршрута.
Наблюдение в upo_test, расширение test2, отчёт tt_Отчет: сохранённый файл
<extension-guid>__<report-guid>.0 является raw_deflate контейнером из пяти
потоков. BSL-модуль расположен в потоке 4.
Поток начинается читаемым UTF-8-комментарием, но последующий текст содержит нулевые байты и смешанное представление символов. Общий потоковый декодер позволяет найти комментарий, однако его обратное кодирование меняет байты неизменённого хвоста BSL. Экспериментальная запись показала это в Конфигураторе и была немедленно восстановлена из парной резервной копии.
Правило: наличие читаемого BSL-фрагмента не доказывает возможность записи.
Для потока с NUL адаптер возвращает
mixed_encoding_module_stream_unsupported и не создаёт SQL-изменений.
Это не означает, что для каждого отчёта нужен свой кодер: один доказанный
кодек может обслуживать все модули с одинаковым физическим носителем.
Два ручных образца определили безопасную границу записи: редактируется только
объявленный UTF-8-префикс, а непрозрачный хвост и остальные потоки сохраняются
побайтно. Для hash-keyed overlay рабочий слой создаётся доказанным копированием
подтверждённых ключей ConfigCAS → ConfigCASSave; __configinfo для него не
создаётся и не предполагается.
Текущая реализация parser.cas_payload.stream_blocks_with_data ищет похожие
заголовки регулярным выражением по всему распакованному буферу. В потоке
отчёта такие последовательности встречаются и внутри данных, поэтому это
эвристика для чтения, а не структурный декодер. Нельзя использовать её индекс
потока как основание для обратной записи.
Структурный read-only декодер decode_declared_utf8_bsl_prefix подтверждён на
этом образце: пять последовательных блоков; пятый имеет declared_1 = 68 и
declared_2 = 512. Первые 68 байт — UTF-8 BOM и точный BSL-текст, оставшиеся
444 байта — непрозрачный служебный хвост. Декодер вернул только:
// protocol-report-baseline-1 и // protocol-report-manual-change-4.
Пара ручных образцов 2 → 3
Образцы samples/manual-change-2.json и samples/manual-change-3.json
содержат raw-deflate байты, сохранённые человеком в Конфигураторе. В
распакованном контейнере длиной 1283 байта замена цифры 2 на 3 изменила
BSL ровно в смещении 838 (0x32 → 0x33). Одновременно платформа изменила
шесть служебных диапазонов: 110..113, 230..252, 437..464, 590..593,
598..601, 716..719. Трёхбайтовое значение повторяется в нескольких
местах, а два диапазона содержат связанные Base64-представления.
Это доказывает, что нельзя перепаковывать поток общим writer'ом. Отдельный
fixed-width кодек меняет только первые declared_1 байт: короткий текст
дополняется пробелами внутри этого поля, хвост и размер члена не меняются.
Рост префикса или структурная правка процедуры явно отклоняются.
Полный объявленный поток: переменная длина
Нельзя переносить ограничение fixed-width с описанного выше носителя на все
объектные BSL-модули. На рабочем маршруте upo / фс_Отчеты / Report.УОП_ПечатьЦенниковАссортимента / .2 / stream:4 подтверждён другой
контейнер: у выбранного BSL-потока declared_1 == declared_2 == 36101 и
opaque_tail_bytes == 0. Это полный UTF-8 поток, а не префикс перед
непрозрачными данными.
Для такого носителя адаптер использует обычный структурный stream writer:
он меняет текст, пересобирает оба объявленных размера в заголовке и сдвигает
только последующие байты контейнера. Локальная обратная проверка целевой
замены НоваяСтрока.Выбран = Истина; на более длинный фрагмент дала размер
потока 36101 → 36198, новый заголовок 36198/36198, одно новое вхождение и
нулевое старое. Все байты до заголовка выбранного потока сохранились.
Правило выбора кодека: fixed-width применяется только если доказан
ненулевой непрозрачный хвост; если declared_1 == declared_2 и хвоста нет,
безопасна контролируемая замена переменной длины через структурный writer.
Неизвестный или частично декодированный контейнер остаётся заблокированным,
а не переводится в переменную длину по предположению.
Правило публичного маршрута
Если объектный модуль состоит только из комментариев, это всё равно BSL-модуль:
у него нет маркеров Процедура/Функция, но его наличие подтверждает
структурный UTF-8-префикс в потоке. Адаптер обязан вернуть владельца и точный
селектор чтения, не заставляя клиента искать поток. При записи он обязан
использовать только fixed-width кодек, а не общий stream writer, который
перезаписывает непрозрачный хвост. Парное обновление __configinfo допустимо
только в отдельно подтверждённом каноническом layout.
Повтор code.write после успешной записи
Повтор одного и того же публичного code.write не является новой операцией.
До автоматической подготовки ConfigCASSave адаптер читает указанную
процедуру в effective_working. Если старого фрагмента уже нет, а точный
новый фрагмент присутствует ровно один раз в этой же процедуре, результат —
status: already_applied, applied: false. В этом случае запрещены и
подготовка saved-state, и новая SQL-запись.
Это правило предотвращает опасный путь: повторный запрос нельзя начинать с
активного ConfigCAS, потому что его копирование способно заново построить
рабочую копию из доизменённого источника и скрыть факт уже выполненной
операции. Если оба фрагмента отсутствуют, новый фрагмент встречается
несколько раз либо процедура не подтверждена, идемпотентность не
предполагается: применяется обычная безопасная ошибка not_found/
ambiguous или диагностика маршрута.
Цепочка версий 2 → 3 → 4
Третий live-SQL образец подтвердил повторяемую часть протокола. 20-байтовое
Base64-поле в каждой новой версии равно SHA-1 сырого файла предыдущей версии:
запись 3 хранит SHA-1 записи 2, а запись 4 — SHA-1 записи 3. Это
доказанная ссылка версии, а не случайный текст. Его контрольный SHA-1:
fc84f0a9ef17034f8d82f44c5f9b07064864b524.
Рядом расположен 16-байтовый токен, который меняется при каждом сохранении и
дублируется фрагментами в трёх служебных местах. Алгоритм его создания не
декодирован: адаптер его не генерирует и не изменяет. Его нельзя считать
основанием для создания или изменения __configinfo в hash-keyed overlay.