Files
llm/docs/1c-sql-protocol/objects/report-object-module.md
T
2026-08-14 09:40:51 +03:00

116 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Модуль объекта отчёта в расширении
Статус: чтение, точное разрешение владельца и контролируемая запись короткого
фрагмента поддержаны для доказанного 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.