Перейти к основному содержимому

Политика совместимости

Начиная с версии 1.0.0, Canopy принимает задокументированные обязательства по обратной совместимости в рамках мажорной версии. Эта страница является контрактом: она описывает, что остаётся стабильным, что может меняться и как происходит процесс объявления устаревания, чтобы операторы могли планировать обновления без неожиданностей.

Политика применяется к версиям 1.x. Будущая ветка 2.x может пересмотреть её; в этом случае руководство по миграции будет поставляться вместе с примечаниями к выпуску 2.0.0.


Что охватывается

Схема базы данных (миграции Alembic)

В рамках 1.x:

  • Миграции являются аддитивными или обратно-совместимыми при обновлении.
  • Новые столбцы могут добавляться в любое время.
  • Существующие столбцы не будут удалены без прохождения цикла объявления устаревания.
  • Существующие столбцы не будут переименованы без цикла объявления устаревания (переименование реализуется как добавление нового столбца → заполнение → объявление устаревания старого → удаление в следующей мажорной версии).
  • Изменения типов ограничены расширением (например, varchar(80)varchar(255)); сужающие изменения проходят через объявление устаревания.
  • Ограничения внешнего ключа не станут более строгими (например, ON DELETE SET NULL не превратится в ON DELETE CASCADE) без цикла объявления устаревания.

Операторы могут обновляться с уверенностью; автоматическая миграция при запуске бэкенда безопасна для выполнения на производственных данных.

Встроенная метамодель

В рамках 1.x метамодель, поставляемая в backend/app/services/seed.py, является стабильной:

  • Ключи встроенных типов карточек (Application, Initiative, BusinessCapability и т. д.) не будут переименованы или удалены.
  • Ключи встроенных полей для этих типов не будут удалены без цикла объявления устаревания.
  • Ключи встроенных типов связей не будут переименованы или удалены без цикла объявления устаревания.
  • Подтипы по умолчанию, поставляемые со встроенными типами, стабильны.

Собственные настройки операторов (пользовательские типы карточек, пользовательские поля, добавленные через административный интерфейс, пользовательские типы связей) являются собственностью оператора и не подпадают под действие этой политики.

REST API (/api/v1/)

В рамках 1.x:

  • Эндпоинты под /api/v1/ не будут удалены без цикла объявления устаревания.
  • Существующие имена полей запроса и ответа не будут переименованы без цикла объявления устаревания.
  • Типы полей не будут изменяться несовместимым образом (например, строка → массив).
  • Новые необязательные поля запроса и новые поля ответа являются неразрушающими и могут появляться в любом минорном выпуске.
  • Новые эндпоинты являются неразрушающими и могут появляться в любом минорном выпуске.
  • Семантика аутентификации (JWT типа Bearer, форма полезной нагрузки /auth/login) стабильна.
  • Семантика HTTP-статусов стабильна для задокументированных путей успеха и ошибок.

Поведение, выходящее за рамки задокументированной поверхности (недокументированные заголовки, текст внутренних сообщений об ошибках, порядок при отсутствии sort_by), не охватывается.

Ключи разрешений

Ключи разрешений, определённые в backend/app/core/permissions.py, стабильны в рамках 1.x. Новые ключи могут добавляться; существующие ключи не будут переименовываться или удаляться без цикла объявления устаревания.

Набор разрешений, предоставляемых по умолчанию встроенным ролям (admin, bpm_admin, member, viewer), может изменяться между минорными выпусками с соответствующим примечанием в CHANGELOG. Операторы, настроившие разрешения ролей в своём развёртывании, не затрагиваются.

Конфигурация (переменные окружения)

Существующие переменные окружения, задокументированные в CLAUDE.md и README.md, стабильны в рамках 1.x. Новые переменные могут добавляться с разумными значениями по умолчанию. Значения по умолчанию могут изменяться с примечанием в CHANGELOG, когда изменение актуально для оператора (например, новый порт по умолчанию).

Зашифрованные в покое секреты

Маркер префикса enc: и ключ, производный от Fernet, в backend/app/core/encryption.py стабильны в рамках 1.x. Операторам не нужно повторно шифровать секреты при минорных обновлениях.


Цикл объявления устаревания

Когда что-то, охваченное этой политикой, требует удаления:

  1. Объявляется устаревшим в минорном выпуске N. Запись в CHANGELOG включает раздел Deprecated с описанием изменения. Для API-эндпоинтов устаревший маршрут возвращает заголовок ответа Deprecation: true (RFC 8594) и заголовок Sunset, указывающий наиболее ранний целевой срок удаления.
  2. Поддержка продолжается в минорном выпуске N+1. Удаление не может произойти в том же минорном выпуске, что и объявление устаревания. Устаревшая форма продолжает работать.
  3. Наиболее раннее удаление — в минорном выпуске N+2 или в 2.0 (в зависимости от того, что наступит раньше). Удаление сопровождается разделом Removed в CHANGELOG и примечанием по миграции.

Для изменений формы данных (миграций Alembic) применяется та же последовательность N → N+1, выраженная как добавление нового → заполнение → удаление старого.


Что не охватывается

Следующее явно выходит за рамки и может изменяться в любое время:

  • Внутренняя структура модулей Python под backend/app/. Импорты app.models, app.services и т. д. не являются частью публичного API. Плагины или скрипты, зависящие от внутренних импортов, должны закреплять конкретную версию Canopy.
  • Структура JSONB-блобов, хранящихся во встроенных таблицах (fields_schema, section_config, attributes, lifecycle), кроме того, что читается задокументированным REST API. Структура JSON на диске может изменяться для поддержки новых функций.
  • Внутренние компоненты фронтенда: пути к файлам компонентов, сигнатуры свойств компонентов в frontend/src/, содержимое frontend/src/types/index.ts и стилизация компонентов MUI. Операторы, использующие встроенный фронтенд, защищены; те, кто встраивает компоненты из исходного дерева, делают это на свой страх и риск.
  • Пользовательские настройки метамодели оператора. Если вы добавляете пользовательский тип карточки или поле через административный интерфейс, вы самостоятельно несёте ответственность за миграцию при изменении.
  • Демонстрационные и начальные данные (SEED_DEMO=true). Демонстрационный набор данных может свободно изменяться между выпусками.
  • Встроенные сторонние сервисы: версия DrawIO, встроенный образ Ollama, встроенная версия swagger-ui-dist. Они могут обновляться в любое время.
  • Поведение при нестандартных конфигурациях, явно помеченных как экспериментальные в записях CHANGELOG.

Что реально меняет «1.0.0»

По сравнению с серией 0.x, 1.0.0 сам по себе не является функциональным выпуском — это точка, с которой начинают применяться перечисленные выше обязательства. Код, поставляемый в 1.0.0, — это тот же код, что и в 0.71.0, плюс улучшения цепочки поставок и изменения рабочего процесса для участников, задокументированные в записи CHANGELOG для 1.0.0.

Выпуски до 1.0 не подпадали под действие этой политики. Миграции между версиями 0.x могли включать и включали удаление схем, переименования и критические изменения метамодели. Начиная с 1.0.0, всё это проходит через цикл объявления устаревания.