Skip to main content
Glama
README.md
# 1confdb-knw (confdb)

Экстрактор конфигурации 1С:Предприятие 8 в базу данных SQLite.

Назначение: распаковать бинарный файл конфигурации (`.cf`, `.cfe`, `.epf`)
без технологической платформы 1С и разложить его содержимое в реляционную базу,
пригодную для генерации кода 1С (LLM/RAG и скрипты).

Алгоритм распаковки портирован из проекта [v8unpack](https://github.com/saby-integration/v8unpack)
(MIT, см. NOTICE.md) — только в одну сторону: распаковка и разбор, без обратной сборки.

## Использование

```bat
:: установка в venv (один раз)
.venv\Scripts\python.exe -m pip install -e .

:: распаковка cf в базу данных (+ дерево распакованных файлов для отладки)
confdb extract file.cf --db out.db --dump _out\file

:: то же через confdb.bat
confdb.bat extract file.cf --db out.db

:: текстовый консольный интерфейс (меню с обновлением экрана:
:: извлечение, запросы, проверка СКД, запуск MCP-сервера
:: с одной базой, несколькими базами или несколькими группами баз, опции)
confdb-ui.bat

:: проверка корректности запросов СКД в готовой базе (пункт 5 в confdb-ui)
confdb check out.db

:: бенчмарк: подбор числа процессов под железо
:: (в confdb-ui — внутри пункта 3 «Опции извлечения»)
confdb bench file.cf
```

По умолчанию любая ошибка декодирования объекта прерывает извлечение.
Флаг `--skip-errors` (в консольном интерфейсе — опция 6 «Пропускать
ошибки объектов») пропускает сбойные объекты и продолжает разбор:
каждый пропуск печатается с внутренней причиной, в конце — итоговое
число. Дамп и база при этом неполные (пропущенные объекты и их
подобъекты отсутствуют) — режим для больших конфигураций, где единичный
сбойный объект не должен блокировать всю выгрузку.

Повторное извлечение одного и того же файла отсекается до распаковки: `extract`
считает SHA-256 исходного `.cf/.cfe/.epf` (885 МБ — 1,7 с) и сравнивает его
с отпечатком в таблице `source` целевой базы. Совпало — база уже содержит ровно
эту конфигурацию, извлечение не запускается (код возврата 0), а сообщение
называет отпечаток и дату сборки; `--force` пересобирает принудительно. Если
база собрана из другого файла, печатается предупреждение о перезаписи. Сам
отпечаток и размер исходника видны в `configuration_info` (полностью) и в
`db_list` (первые 16 символов) — по ним две базы сравниваются на происхождение
без повторной выгрузки. В консольном интерфейсе вместо `--force` задаётся
вопрос «Пересобрать базу всё равно?».

## Проверка запросов СКД

`confdb check <база>` (и пункт 5 консольного интерфейса) прогоняет все запросы
таблицы `skd_query` через встроенный разборщик языка запросов 1С
(`src/confdb/query_lang.py`):

- синтаксис: ПОМЕСТИТЬ/УНИЧТОЖИТЬ, ОБЪЕДИНИТЬ [ВСЕ], соединения (включая вложенные
  и перечислением), вложенные запросы, ВЫБОР/ВЫРАЗИТЬ, виртуальные таблицы
  с аргументами, параметры `&…`, необязательные области СКД `{…}`, `ДЛЯ ИЗМЕНЕНИЯ`;
- семантика по метаданным: существование таблиц (`Справочник.Х`, `РегистрНакопления.Х.Обороты`
  и т.п.), существование полей первого уровня (meta_attribute + стандартные поля +
  общие реквизиты, без учёта регистра), цепочки разыменования ссылок через
  `attribute_ref` (второй и далее уровни — мягко: составные/абстрактные типы
  не всегда раскрываются).

Код возврата 1 и список сообщений — если какой-то запрос не прошёл.

## 1confdb-knw — MCP-сервер для внешних LLM

```bat
:: сервер знаний по конфигурации 1С и BSL; stdio (JSON-RPC, read-only)
1confdb-knw.bat out.db
:: то же через CLI: confdb 1confdb-knw out.db
:: несколько баз сразу: основная конфигурация + расширения/обработки
1confdb-knw.bat main.db extension.db processor.db
:: несколько групп конфигураций одновременно — повтор флага добавляет базу
:: в ту же группу, а группы остаются раздельными (запрос к одной — group=<имя>)
1confdb-knw.bat --group УНФ=unf.db --group УНФ=unf_ext.cfe.db --group БП=bp.db
```

Путь к базе можно не указывать: `1confdb-knw.bat` без аргумента берёт
`last_db` из `~/.confdb/config.json`, а при его отсутствии сам ищет
`*.db`/`*.sqlite` — в текущем каталоге, `db/` и `_out/` (и в корне
установки при запуске из venv). Одна база — запускается; несколько —
сервер печатает список и просит указать путь явно. С флагом `--group`
автопоиск не срабатывает: нужные базы названы в группах. Несуществующий путь —
сразу «Файл базы не найден» (код 2), без падения на первом запросе.
Свежая установка с базой, привезённой с другого компьютера, работает
без ручной правки конфига: достаточно положить файл в `db/` рядом
с `1confdb-knw.bat`.

32 инструмента: `find_objects`, `object_card` (паспорт объекта: реквизиты,
табличные части, модули, формы и команды, ссылки; у регистров — измерения,
ресурсы и реквизиты отдельными группами плюс периодичность и режим записи),
`object_tree`, `find_field`, `refs_of`, `role_rights` (явные права одной роли:
по строке на цель — объект, его реквизит/поле табличной части или его табличная
часть, — с текстом ограничения доступа на уровне записей и шаблонами RLS роли;
право показывается первыми знаками своего uuid, потому что имён прав в
конфигурации нет), `object_rights` (какие роли несут явные права на объект,
включая права на его реквизиты и табличные части; параметр `role` сужает ответ
до одной роли), `module_outline`, `get_method`,
`find_method_context` (окно строк вокруг нужного вызова с номерами строк
модуля и маркерами точки вставки), `method_dependencies` (что использует
метод: общие модули и их экспортные методы, метаданные, таблицы и поля
запросов, параметры; если рядом открыта основная конфигурация, её объекты и
общие модули находятся там, а не объявляются отсутствующими),
`method_result_schema` (из чего состоит возвращаемая методом таблица
значений/структура — эвристика по тексту), `find_methods` (поиск по имени,
сигнатуре и описанию, а параметр `text` — по текстам тел методов: все места
обращения к объекту с номером строки модуля, без полнотекстового `sql`),
`skd_of`, `find_skd`, `xdto_of` (состав пакета XDTO: целевое пространство
имён, импорты, типы с базовым типом, ограничениями и значениями перечислений,
свойства с обязательностью, признаком списка и формой — атрибут или элемент,
вложенные анонимные типы; параметр `type` показывает один тип),
`find_xdto` (поиск имён типов и свойств по всем пакетам XDTO базы),
`check_query` (валидатор запроса 1С), `sql` (только
SELECT), `compare_object` (различия одного объекта в двух базах),
`extension_diff` (что делает расширение относительно основной конфигурации),
`configuration_info` (тип загруженного файла — конфигурация `.cf`, расширение
`.cfe`, внешняя обработка `.epf`, внешний отчёт `.erf`; имя и версия, режим
совместимости, источник и дата выгрузки) и управление базами
`db_list` / `db_open` / `db_use` / `db_close` плюс управление группами
конфигураций `group_create` / `group_add_db` / `group_remove_db` /
`group_list` / `group_use` / `group_close`. Инструкции протокола
(`initialize.instructions`)
и описания инструментов содержат справочник по схеме базы, глоссарий 1С
и рекомендуемый рабочий процесс — любая модель пользуется сервером без
контекста этого проекта.

**Пагинация поиска.** `find_objects`, `find_field`, `find_methods`, `find_skd`,
`find_xdto` и `refs_of` отдают одну страницу совпадений: `limit` задаёт её
размер (1..200), `offset` — сколько совпадений того же поиска пропустить.
Последняя строка ответа сообщает итог и продолжение —
`… всего найдено 317; показано 1–20; есть ещё 297 — следующий вызов с offset=20`
(когда страница последняя — «это все результаты»). Порядок совпадений строгий,
поэтому страницы не пересекаются и не теряют строки. У `find_xdto` типы и
свойства считаются одним списком (сначала типы, потом свойства), у `refs_of`
свой итог у каждой из двух секций, а `offset` у них общий.

Синтаксис текстов модулей этот сервер **не** проверяет: полный разбор BSL
(блок-конструкции, препроцессор, типы, область видимости) делает BSL
Language Server, который поднимает вариант `1confdb-knw-lsp`. Ошибки
инструментов возвращаются с кодом категории — `BAD_ARGS`, `BAD_REQUEST`,
`DB_LOCKED`, `DB_SCHEMA`, `DB_ERROR`, `IO_ERROR`, `INTERNAL`; при занятой
базе (`SQLITE_BUSY`) вызов повторяется автоматически.

#### Несколько баз одновременно (расширения и обработки)

Сервер держит несколько баз сразу: перечислите их при запуске либо
открывайте на ходу инструментом `db_open` (без перезапуска сервера).
Каждая база получает алиас (по умолчанию — имя файла без расширения;
при совпадении — с суффиксом `_2`, `_3`…). Все инструменты по умолчанию
работают с активной базой (при запуске — первая указанная); чтобы
запросить другую базу без переключения, передайте её алиас параметром
`db` (есть у всех инструментов). Переключение активной базы — `db_use`,
список открытых баз со статистикой — `db_list`, закрытие — `db_close`.

Типовой сценарий: извлечь основную конфигурацию, расширение и обработку
в отдельные базы и запустить сервер со всеми тремя —

```bat
confdb extract main.cf --db main.db
confdb extract ext.cfe --db ext.db
confdb extract proc.epf --db proc.db
1confdb-knw.bat main.db ext.db proc.db
```

— после чего LLM видит метаданные и код всех трёх и может, например,
искать методы расширения (`find_methods` с `db='ext'`) поверх основной
конфигурации. Специальное значение `db='*'` выполняет инструмент сразу
по всем открытым базам (ответ приходит секциями по базам) — один вызов,
чтобы сравнить основную конфигурацию с расширениями. Если база
пересобрана (повторный `extract`), её достаточно закрыть и открыть
заново: `db_close` + `db_open`.

**Идентификатор базы в ответах:** каждый ответ инструмента данных начинается
с заголовка `=== база <алиас> (<путь>) ===`, идентифицирующего источник данных.
Если база входит в группу, заголовок называет и её —
`=== группа <имя> / база <алиас> (<путь>) ===`, а при вхождении в несколько
групп — `=== группы A, B / база …`.
Это позволяет LLM сравнивать конфигурации (типовая vs доработанная, основная vs
расширение) и понимать, в какой базе находится метод или объект. Например:

```
=== база основная (C:\path\main.db) ===
Справочник.Контрагенты: 150 объектов

=== база расширение (C:\path\ext.db) ===
Справочник.Контрагенты: 155 объектов
```

Инструменты управления базами (`db_list`, `db_open`, `db_use`, `db_close`) не
содержат заголовок — они сами управляют базами.

#### Группы конфигураций: несколько наборов баз одновременно

Группа объединяет связанные базы (основная конфигурация + расширения +
обработки) под одним именем. Групп может быть открыто **несколько
одновременно** — например две разные конфигурации или две версии одной, —
и деление при этом сохраняется: сервер знает, какая база в какой группе,
и печатает это в `db_list`, в `group_list` и в заголовке каждого ответа.

- запуск с группами: `1confdb-knw.bat --group УНФ=unf.db --group УНФ=unf_ext.db
  --group БП=bp.db` — повтор флага добавляет базу в ту же группу, несколько
  путей можно перечислить через `;`. Первая группа становится активной, а её
  первая база — активной базой;
- запрос к ОДНОЙ группе: параметр `group='БП'` у инструмента данных — он
  выполнится по всем базам группы и вернёт ответ секциями
  `=== группа БП / база <алиас> (<путь>) ===`;
- запрос сразу ко всем группам: `group='*'` — секции по группам, каждая со
  своими базами (в отличие от `db='*'`, который смешивает все открытые базы);
- **без `group` выполняется только активная база**, а не вся активная группа:
  при нескольких открытых группах группу нужно называть явно. `group_use`
  переключает активную группу и делает её первую базу активной;
- отказ одной базы не рвёт групповой вызов (`group=<имя>`, `group='*'`,
  `db='*'`): её секция несёт `ошибка [КАТЕГОРИЯ]: …` (`DB_LOCKED` —
  транзитная, тот же вызов может пройти повторно), остальные базы отвечают
  штатно, а ответ заканчивается строкой `баз с ошибкой N из M: <алиасы>`,
  чтобы частичный ответ не читался как полный. `isError` вызов получает
  только когда отказали **все** базы — их секции при этом остаются видны;
- на ходу: `group_create`, `group_add_db`, `group_remove_db`, `group_list`,
  `group_use`, `group_close` (удаление группы базы не закрывает).

`compare_object` и `extension_diff` групп не знают: они принимают явные
алиасы баз (`db_left`/`db_right`, `extension_db`/`base_db`), которые
берутся из `db_list` или `group_list`.

В консольном интерфейсе наборы баз сохраняются в **именованные группы**
(пункт 6 главного меню): одна база может входить в несколько групп. Пункт 1
запускает сервер с **несколькими группами сразу** — номер отмечает или
снимает группу, `*N` делает N-ю выбранной первой (её база станет активной),
`m` добавляет отдельные базы вне групп. В сетевом режиме панель после
запуска позволяет подключать/закрывать базы и работать с группами из
конфига без перезапуска сервера: добавить группу (остальные группы и базы
останутся открытыми), заменить весь набор одной группой, убрать группу (её
базы закроются, если не нужны другим группам) и сделать группу активной.

Пример конфигурации MCP-клиента, в т.ч. через SSH:

```json
{
  "mcpServers": {
    "1confdb-knw": {
      "command": "ssh",
      "args": ["user@host", "python", "-m", "confdb.mcp_server", "/path/out.db"]
    }
  }
}
```

### Сетевой режим (когда stdio не подходит)

Сервер слушает порт и отдаёт MCP по HTTP (Streamable HTTP: `POST /mcp`;
legacy SSE для старых клиентов: `GET /sse` + `POST /messages`):

```bat
1confdb-knw.bat out.db --port 8765
```

С другой машины подключение — через SSH-туннель:

```bat
ssh -L 8765:127.0.0.1:8765 user@host
```

```json
{
  "mcpServers": {
    "1confdb-knw": { "url": "http://127.0.0.1:8765/mcp" }
  }
}
```

По умолчанию слушает `127.0.0.1` (без аутентификации, база read-only);
`--host 0.0.0.0` открывает порт наружу — используйте только в доверенной сети.
В консольном интерфейсе — пункт 1 → «Сеть (HTTP-порт)».

Запросы выполняются по одному за раз: соединения баз и приставных шардов FTS на
сервер общие, поэтому вызовы инструмента сериализованы — в stdio, в HTTP и когда
консольный интерфейс обращается к работающему серверу. Долгий запрос (`sql` по
большой таблице, поиск по телам в базе без индекса) задерживает остальных
клиентов; параллельные подключения работу не ускоряют.

Опции `extract`:

- `--db FILE` — записать результат в SQLite;
- `--dump DIR` — сохранить распакованное дерево файлов (нужен хотя бы один из `--db`/`--dump`);
- `--temp-dir DIR`, `--keep-temp` — рабочий каталог стадий 0–1 и его сохранение.
  Без `--temp-dir` он создаётся рядом с базой (`--db`) или дампом (`--dump`), а не
  в `%TEMP%`: на системном томе удаление ~125 тысяч файлов рабочего каталога стоит
  ~30 с и почти не распараллеливается, на несистемном — ~10 с, и прогон УНФ целиком
  занимает 70 с вместо 97 с. Если каталог результата недоступен — откат на `%TEMP%`;
- `--prefix STR` — снять префикс с имён объектов;
- `--store-blobs` — хранить бинарные файлы (картинки, макеты) в БД как BLOB;
- `--workers N` — число процессов стадии 3 и записи БД (по умолчанию — результат
  `confdb bench` или 1; на многоядерной машине несколько процессов ускоряют разбор
  в несколько раз). В консольном интерфейсе — меню «Опции извлечения». При вызове
  `extract()` из собственного скрипта на Windows с `workers > 1` вызов должен быть
  обёрнут в `if __name__ == '__main__':` (требование multiprocessing spawn).
- `--no-fts` — не строить FTS-индекс по телам методов. Индекс — приставные файлы
  `<база>.fts\0.db…`, по одному на процесс (на УНФ 7.5 с в 8 шардов, ~1.1 ГБ); сама
  база остаётся одним файлом и без индекса работоспособна — поиск по телам идёт
  полным проходом (~0.3 с на запрос). Достраивается позже командой
  `confdb fts <база> [--workers N]`, каталог `.fts` можно удалить в любой момент.
- `--dump-indent` — писать JSON дампа с отступами, как это делает v8unpack. Нужно
  только для побайтового сравнения дампов при проверке эквивалентности декодера:
  по умолчанию вывод компактный, с ним стадия 3 быстрее (28.0 с против 30.8 с на УНФ),
  а дерево дампа примерно втрое меньше. На содержимое базы флаг не влияет.
- `--force` — пересобрать базу, даже если она уже собрана из этого же файла.
  Без флага `extract` сравнивает SHA-256 исходника с `source.file_sha256` целевой
  базы и при совпадении не запускает распаковку вовсе (~70 с на УНФ против 1,7 с
  на отпечаток).

## Бенчмарк и автонастройка

`confdb bench <file>` один раз прогоняет стадии 0/1, затем нелинейный сэмпл
объектов верхнего уровня (шаг по всему списку + покрытие всех типов объектов,
чтобы задеть и лёгкие справочники, и тяжёлые формы/отчёты) через стадию 3 и
запись БД при 1/2/4/8/CPU процессах. Лучшее число процессов сохраняется в
`~/.confdb/config.json` и подставляется по умолчанию в `extract` и в консольный
интерфейс; `--workers N` переопределяет вручную.

Стадии конвейера (повторяют v8unpack, только распаковка):

0. чтение внешних V8-контейнеров (32/64-бит) в файлы как есть;
1. inflate (raw deflate) + рекурсивные вложенные контейнеры;
3. декодирование метаданных: скобкофайлы `{}` → JSON, тексты модулей → `.bsl`.

## Схема базы данных

Ревизия схемы штампуется в сам файл базы: `PRAGMA user_version = writer.SCHEMA_VERSION`
(с 2026-10-08). MCP-сервер отвечает только на базы своей ревизии, а на устаревшую
возвращает просьбу пересобрать её (`confdb extract <файл> --db <база> --force`) — вместо
ошибки схемы посреди запроса. Совместимого режима чтения старых схем нет: новые колонки
(например `role_right.target_flags`) заполняются только из исходника, миграции не
существует. У баз, собранных до появления штампа, `user_version = 0` — они считаются
устаревшими. Ревизию открытых баз показывают `db_list`, `db_open` и список баз в TUI.

- `source` — исходный файл: путь, дата, тип/имя/uuid корневого объекта;
- `meta_object` — объект метаданных: `path` (например `Catalog/Контрагенты/CatalogForm/ФормаЭлемента`),
  `type` (Catalog, Document, CommonModule, …), `type_ru` (русское имя «как в конфигураторе»:
  Справочник, Документ, Общий модуль, …), `name`, `uuid`, `comment`, `obj_version`,
  `header_json` (полный разобранный заголовок), `parent_id` + `ord` (иерархия и порядок
  братьев — как в дереве конфигуратора);
- `meta_attribute` — реквизиты объекта: `ord`, `name`, `type_str` в порядке объявления.
  Примитивы — Строка(50)/Число/Дата/Булево; ссылки — `Ссылка: <путь>` (таблица ссылочных
  uuid из потока `.10` корневого объекта, коллизии имён дизамбигуируются по типу объекта);
  определяемые типы — `ОпределяемыйТип: <путь> (<состав>)` (состав раскрывается);
  составные типы — члены через ` | `; обобщённые типы платформы («ЛюбаяСсылка» и т.п.),
  чей uuid не соответствует ни одному объекту конфигурации, — `Ссылка` (это не ошибка
  извлечения, у такого типа нет конкретной цели); `Ссылка: <имя> (объект не найден
  в базе)` — имя цели известно из таблицы `.10`, но самого объекта в этой базе нет
  (типично для ссылки из расширения на объект основной конфигурации); `NULL` —
  в заголовке объекта описание типа этого реквизита отсутствует; `uuid` — собственный
  идентификатор поля в метаданных: по нему цель права роли (`role_right.target_uuid`)
  разрешается в конкретный реквизит, `NULL`, когда в заголовке поля uuid нет;
- `attribute_ref` — связи реквизитов с объектами метаданных: `uuid` (ссылочный uuid
  из дескриптора типа, для составных/определяемых типов — по строке на член) и
  `object_id` — объект, на который ведёт ссылка (NULL для абстрактных типов);
  зависимость «реквизит ↔ объекты» строится join'ом без разбора строк `type_str`;
- `enum_value` — значения перечислений (`ord`, `name`) в порядке объявления;
- `predefined` — предопределённые элементы из «Предустановленные данные.bin»: `ord`
  (номер в обходе в глубину), `parent_ord` (ord родителя; NULL только у корневого узла
  «Счета»/«Элементы», который элементом не является), `uuid` элемента, `name`, `code`,
  `display`;
- `predefined_subconto` — виды субконто предопределённого счёта плана счетов:
  `predefined_id`, `ord`, `uuid` вида субконто, `kind_id` — предопределённый элемент
  плана видов характеристик, которым он разрешается, `flags` — включённые флаги через
  «;» («Суммовой», «Валютный», «Количественный»);
- `common_target` — привязка общих реквизитов к объектам метаданных;
- `meta_tabular` — табличные части объекта (`ord`, `name`, `uuid`) в порядке объявления;
  поля табличных частей лежат в `meta_attribute` с заполненной колонкой
  `tabular` (имя секции) — цепочки вида `Т.Товары.Наименование` в запросах
  проверяются по этим данным; `uuid` секции разрешает право роли, заданное на
  табличной части.
- `module` — паспорт модуля: `code_name` (obj, mgr, mod, con, app …) и для общих
  модулей `context` (Сервер/Клиент/Вызов сервера/…), плюс `body` — текст модуля как есть
  без кода методов: комментарии, препроцессор `#Если…`, `#Область…`, директивы и сигнатуры
  вида `Процедура Имя(п1, п2) Экспорт` сохранены; подстановка `method.body` вместо каждой
  сигнатуры восстанавливает исходный модуль;
- `method` — только процедуры/функции: вид, имя, сигнатура, `is_export`, `directives`
  (строка `&НаКлиенте, &НаСервере` без скобок), `description` (блок комментариев
  непосредственно над методом, как есть с `//`), `line_start/line_end`, `body` — строго
  с `Процедура/Функция` по `КонецПроцедуры/КонецФункции`; `#…` и комментарии вне тела
  в метод не попадают;
- `subsystem_content` — состав подсистем (ссылки на объекты в порядке объявления) —
  для обхода дерева подсистем, как в конфигураторе;
- `skd_query` — запросы, извлечённые из макетов СКД объекта (`ord`, `query`), —
  для проверки корректности запросов 1С;
- `role_right` — объектные права ролей из файла `Role/<имя>/Role.0.c1brace`. Хранятся
  только ЯВНЫЕ записи (sparse): отсутствие строки означает «право не задано», а не
  «запрещено». Цель права — объект, его реквизит/поле табличной части или его
  табличная часть: `target_object_id` — объект-владелец (заполнен и для подобъекта,
  поэтому все права, затрагивающие объект, выбираются одним условием),
  `target_attr_id`/`target_tabular_id` — сам подобъект, `target_uuid` — uuid цели как
  он записан в роли (подобъект, которого проект не извлекает, остаётся только с ним);
  `right_uuid` — идентификатор права платформы (русского имени права в конфигурации
  нет, словарь «uuid → имя» из неё не извлекается), `value` — значение права,
  `sub_index`/`collection_uuid` — адресация «подобъект №-K внутри коллекции»,
  `target_flags` — флаги записи цели дословно, без толкования (их смысл не
  подтверждён; без них две цели с одним uuid слились бы в одну),
  `rls_text` — ограничение доступа на уровне записей для этой цели и права;
- `role_rls_template` — именованные шаблоны RLS роли (`name`, `text`);
- `role_rights_state` — состояние извлечения прав каждой роли: `parsed=0` — данные
  недоступны (файла прав нет или формат не распознан, причина в `error`),
  `parsed=1` при `rights=0` — права роли действительно не заданы;
- `xdto_type`, `xdto_property`, `xdto_import` — содержимое пакетов XDTO
  (файл `XDTOPackage.bin` — это открытый XML, реверс бинарного формата не
  потребовался): типы `objectType`/`valueType`/`typeDef` с базовым типом,
  ограничениями и значениями перечислений, их свойства (обязательность,
  признак списка, форма — атрибут или элемент, вложенные анонимные типы) и
  импортируемые пространства имён; `type_id IS NULL` означает свойство,
  объявленное самим пакетом вне типов; целевое пространство имён пакета
  берётся из его `header_json`. Инструменты `xdto_of` и `find_xdto`;
- `file` — прочие файлы дампа (help.html, инфо-JSON, картинки): путь, тип, размер,
  содержимое для текстовых (BLOB — только при `--store-blobs`).

Пример запроса:

```sql
-- реквизиты справочника с типами
SELECT a.name, a.type_str
FROM meta_attribute a JOIN meta_object o ON o.id = a.object_id
WHERE o.path = 'Catalog/Контрагенты' ORDER BY a.ord;

-- краткое представление модуля (текст без кода методов)
SELECT m.body FROM module m JOIN meta_object o ON o.id = m.object_id
WHERE o.path = 'Catalog/Контрагенты' AND m.code_name = 'obj';

-- тело конкретного метода
SELECT mt.body FROM method mt JOIN module m ON m.id = mt.module_id
JOIN meta_object o ON o.id = m.object_id
WHERE o.path = 'Document/Заказ' AND m.code_name = 'obj'
  AND mt.name = 'ПриПроведении';
```

## Состав

- `src/confdb/v8` — ядро распаковки (контейнеры 1С, inflate, скобкофайлы, метаданные);
- `src/confdb/extract.py` — конвейер стадий 0/1/3 (контейнеры → inflate → разбор). Рабочий
  каталог по умолчанию создаётся на томе результата (`make_temp_dir`), а не в `%TEMP%`, и
  удаляется параллельно (`remove_tree`): удаление ~125 тыс. файлов стоит ~30 с на системном
  томе против ~10 с на другом. Здесь же отпечаток источника — `file_sha256` (1.7 с для
  885 МБ) пишется в `source.file_sha256`, а `check_same_source(src, db, force)` позволяет
  CLI и TUI не распаковывать тот же файл повторно; в старых базах отпечатка нет, и это
  читается как «неизвестно», а не как «файл другой»;
- `src/confdb/__main__.py` — CLI: `extract`, `check`, `fts`, `bench`, `1confdb-knw`;
- `src/confdb/db/writer.py` — схема SQLite и запись результата: пакетные вставки, разбор BSL
  в несколько процессов (`workers`); права ролей пишутся после объектов и разрешаются по
  uuid объектов, реквизитов и табличных частей (`_write_role_rights`, `_right_targets`);
  ревизия схемы (`SCHEMA_VERSION`) штампуется в файл базы (`PRAGMA user_version`);
- `src/confdb/query_lang.py` — разбор и семантический контроль языка запросов 1С
  (подкоманда `confdb check`);
- `src/confdb/mcp_server.py` — MCP-сервер `1confdb-knw <база…>`: read-only инструменты,
  самомописываемый (схема, глоссарий и порядок работы отдаются в `initialize.instructions`).
  Несколько баз (алиас на базу, необязательный параметр `db`, `db='*'` — по всем сразу) и
  ГРУППЫ конфигураций: `--group ИМЯ=ПУТЬ` (повторяемый) открывает несколько групп,
  `group=<имя>` опрашивает одну, `group='*'` — все, а без `group` работает только активная
  база (`group_use` переключает активную). Шесть поисковых инструментов страничные
  (`limit` 1..200 и `offset`, последняя строка ответа называет общее число совпадений и
  следующий `offset`); кросс-базовые инструменты принимают явные алиасы (`compare_object`,
  `extension_diff`); ошибки категоризованы (`error_text`), `SQLITE_BUSY` повторяется
  (`call_with_retry`). Транспорт — stdio, `--port N` включает HTTP/SSE; вызовы
  инструментов сериализованы общей блокировкой (`_synchronized`): соединения баз и
  приставных шардов FTS на сервер общие, а потоков несколько — HTTP-обработчик
  создаётся на запрос, панель работающего сервера в TUI дёргает тот же объект;
- `src/confdb/tui.py` — консольный интерфейс (выбор пользователя: консоль, а не GUI).
  В списках файлов и баз число выбирает элемент, а любой другой текст читается как введённый
  путь. Запуск MCP выбирает несколько групп баз сразу (в сервер они попадают как `--group`
  в stdio-режиме и как `McpServer(groups=…)` в сетевом), а панель работающего сервера
  добавляет, заменяет все, удаляет и активирует группу без перезапуска;
- `src/confdb/bsl_parser.py` — разбиение модулей BSL на процедуры и функции;
- `src/confdb/bsl_analyzer.py` — лексический анализ BSL для `method_dependencies` и
  `method_result_schema`: маскирование строк и комментариев с пониманием многострочных
  литералов 1С с `|`, извлечение и проверка запросов через `query_lang`, разрешение общих
  модулей и метаданных, клиентский и серверный контекст. Синтаксис модулей он намеренно
  **не** проверяет — это делает BSL Language Server, который есть только в варианте
  `1confdb-knw-lsp`;
- `src/confdb/header_props.py` — читает `meta_object.header_json` без повторной распаковки:
  версию конфигурации, синоним, режим совместимости и префикс расширения; коллекции
  измерений, ресурсов и реквизитов регистра с периодичностью и флагами режима записи;
  целевое пространство имён XDTO-пакета; вид загруженного файла — по расширению
  `source.file`, а не по типу корневого объекта (`.erf` и `.epf` раскрываются в
  `ExternalDataProcessor`);
- `src/confdb/xdto.py` — разбор `XDTOPackage.bin` (обычный UTF-8 XML с BOM) в таблицы
  `xdto_*`; проверено на всех 334 пакетах тестовой конфигурации;
- `src/confdb/compare.py` — снимки объектов и сравнение двух баз (`compare_object`,
  `extension_diff`); тела методов и модулей сравниваются по sha1;
- `src/confdb/rights.py` — разбор файла прав роли `Role/<имя>/Role.0.c1brace` (объектные
  права, RLS по объектам, шаблоны RLS) для записи в базу; нераспознанный формат бросает
  `ValueError`, поэтому одна «чужая» роль не останавливает запись;
- `src/confdb/bench.py` — бенчмарк железа, сохраняет лучшее число `workers` в
  `~/.confdb/config.json` (`src/confdb/config.py` — общий конфиг пользователя, его же
  читает TUI);
- `tests` — тесты на малых фикстурах (`test.bat`); `_tmp` — одноразовые пробники
  (игнорируются git).

## Требования

- Python 3.9+, только стандартная библиотека.