# Автоматическое сохранение при деплое

Платформа сохраняет снимок исходников сама, при каждом успешном развёртывании. Здесь — что попадает в снапшот автоматически, как прочитать результат в ответе деплоя, когда сохранение пропускается и в каких трёх случаях снапшот всё ещё сохраняют вручную.

Обзор хранилища и справочник эндпоинтов — [Хранилище исходного кода](/docs/source-storage).

## Сохранение исходников

С версии 2026-05-23 платформа **автоматически** сохраняет байты исходников в хранилище при каждом успешном развёртывании. Это касается:

- `POST /v1/infra/servers/:id/deploy { source: { content: <base64> } }` — встроенные байты сохраняются как новая версия
- `POST /v1/infra/servers/:id/deploy { source: { url: <signed URL из хранилища> } }` — существующая версия привязывается к идентификатору развёртывания
- `POST /v1/infra/servers/:id/deploy { source: { versionId: 'vN' } }` — то же

**У galaxy-приложения ссылка и сохранённая версия — за отдельным включением.** На отдельных виртуальных машинах (`kind` равен `STANDALONE`) работают все варианты из списка выше. Для galaxy-приложения (`kind` равен `GALAXY_APP`) встроенный `source.content` работает всегда, а `source.url` и `source.versionId` — там, где платформа включила для вас выкладку по ссылке. Иначе запрос отклоняется с `400 GALAXY_DEPLOY_CONTENT_ONLY`. Сама ссылка на galaxy-приложении обязана вести в это хранилище — сторонний адрес отклоняется с `400 GALAXY_SOURCE_URL_NOT_ALLOWED`. Подробнее — [Galaxy-приложения](/docs/infra/galaxy).

**Исключение**: развёртывание с внешним URL (не из хранилища Вайбкод) возвращает **409 SNAPSHOT_REQUIRED**. Чтобы обойти — либо сначала загрузите архив через `POST /v1/apps/:id/sources` и разверните через `{source: {versionId: 'vN'}}`, либо передайте заголовок `X-Skip-Source-Snapshot: <reason>` для явного отказа.

### Ответ деплоя: блок `source`

Ответ `POST /v1/infra/servers/:id/deploy` содержит блок `data.source` — результат автосохранения. По нему AI-агент или клиент понимает, попал ли код в депо:

```json
{
  "success": true,
  "data": {
    "status": "running",
    "appUrl": "https://app-b7c1e2a4.vibecode.bitrix24.tech",
    "source": {
      "autoSaved": true,
      "savedVersionId": "v4",
      "sha256": "a3f5d8b2c1e9f4...",
      "linkedDeployId": "deploy:2026-05-21T10:15:30.000Z",
      "skippedReason": null
    }
  }
}
```

| Поле | Тип | Описание |
|------|-----|----------|
| `source.autoSaved` | boolean | `true` — снимок сохранён, `false` — пропущен (причина в `skippedReason`) |
| `source.savedVersionId` | string \| отсутствует | Идентификатор созданной версии (`vN`) при `autoSaved: true` |
| `source.sha256` | string \| отсутствует | SHA-256 сохранённого архива |
| `source.linkedDeployId` | string \| отсутствует | Идентификатор развёртывания, к которому привязан снимок |
| `source.skippedReason` | string \| null | `null` при успехе, иначе причина пропуска (см. ниже) |

Деплой завершается успешно (`200`) независимо от блока `source` — автосохранение работает по принципу «лучшее усилие» и никогда не валит развёртывание. Значения `skippedReason`:

| `skippedReason` | Когда |
|-----------------|-------|
| `feature-disabled-platform` | Депонирование выключено на уровне платформы |
| `feature-disabled-portal` | Владелец портала отключил депонирование для своего портала |
| `external-url-or-toggles-off` | Источник — внешний URL (не из хранилища Вайбкод) |
| `save-failed` | Временная ошибка хранилища — повторите деплой или сохраните вручную через `POST /v1/apps/:id/sources` |
| `<значение заголовка>` | Был передан `X-Skip-Source-Snapshot: <reason>` — снимок пропущен намеренно |

Чтобы убедиться, что код задепонирован, проверьте `data.source.autoSaved === true` и сохраните `savedVersionId` для последующего отката или передачи.

### Когда снапшот не создаётся

Если сохранение исходников отключено на портале или источник — внешний URL (не хранилище Вайбкод), снапшот не создаётся, а развёртывание завершается штатно. Чтобы сохранить версию явно, загрузите архив через `POST /v1/apps/:id/sources`.

### Когда `POST /sources` всё ещё нужен явно

Только три сценария:

1. **Пометить версию** — поставить тег `manual` или `published`, чтобы версия хранилась бессрочно.
2. **Сохранить без развёртывания** — зафиксировать промежуточный результат для передачи другому разработчику.
3. **Подготовка к откату** — снимок исходного состояния перед рискованным изменением.

## Когда вызывать

Типовой сценарий для AI-агента (с 2026-05-23 явный вызов `POST /sources` перед деплоем не требуется — платформа сохраняет автоматически):

1. Изменил код → `POST /v1/infra/servers/:id/deploy` — исходники сохраняются автоматически.
2. `POST /v1/apps/:id/publish` — публикует приложение в каталоге Битрикс24. Тег `published` добавляется к снапшоту автоматически.
3. Повторил цикл при следующем изменении.

Сценарий передачи проекта новому разработчику или новой AI-сессии:

1. `GET /v1/apps/:id/sources` — список доступных версий.
2. `GET /v1/apps/:id/sources/:versionId/download` — подписанная ссылка на архив.
3. Скачать архив, распаковать и продолжить работу.

Для MCP-клиентов: инструмент `save_sources` упаковывает файловое дерево в tar.gz на стороне клиента и отправляет одним запросом. Инструмент `load_sources` загружает последнюю версию и распаковывает обратно в дерево файлов. Прямой вызов HTTP-эндпоинта доступен для клиентов, которые самостоятельно упаковывают архив.

## Деплой из снапшота

`POST /v1/infra/servers/:id/deploy` принимает поле `source.versionId` — альтернатива `source.url` и `source.content`. Позволяет развернуть на сервере ровно ту версию, которая была сохранена через `save_sources`, без отдельной загрузки файла.

```json
{
  "source": {
    "versionId": "v3"
  },
  "start": "node server.js"
}
```

Сервер разрешает `versionId` в подписанную ссылку на архив и выполняет деплой. После успешного или неуспешного деплоя поле `linkedDeployId` у снапшота обновляется автоматически.

**На galaxy-приложении — за отдельным включением.** Деплой по `source.versionId` работает на серверах, у которых `kind` равен `STANDALONE`. Galaxy-приложение (`kind` равен `GALAXY_APP`) принимает `source.versionId` и `source.url` там, где платформа включила для вас выкладку по ссылке. Иначе запрос отклоняется с `400 GALAXY_DEPLOY_CONTENT_ONLY`, и остаётся встроенный `source.content`. Ссылка на galaxy-приложении обязана вести в это хранилище — сторонний адрес отклоняется с `400 GALAXY_SOURCE_URL_NOT_ALLOWED`. Подробнее — [Galaxy-приложения](/docs/infra/galaxy).

**Как ищется версия.** Если сервер принадлежит тому же ключу, которым идёт вызов, версия ищется в контексте этого сервера — так работает связка «сохранил через `POST /v1/infra/servers/:id/sources` → выложил по `versionId`», в том числе на личном ключе (`vibe_api_*`). Если на сервере такой версии нет, а ключ-владелец привязан к приложению, поиск повторяется в контексте приложения — этим и выкладывается версия, сохранённая до замены сервера. Версия не найдена ни там, ни там — `404 SOURCE_VERSION_NOT_FOUND`.

**Ограничение:** оно сузилось и осталось только для случаев, когда сервер принадлежит НЕ вызывающему ключу — менеджмент-ключ и доступ через карточку приложения. Там версия по-прежнему ищется только в контексте приложения, и если ключ-владелец сервера не привязан к приложению, вернётся `400 SOURCE_VERSION_REQUIRES_APP`.

## Поведение для AI-моделей

MCP-инструмент `save_sources` обёртывает `POST /v1/apps/:id/sources`. Инструмент `load_sources` скачивает и распаковывает последний снапшот в дерево файлов.

С 2026-05-23 явный вызов `save_sources` перед развёртыванием не требуется — платформа сохраняет байты автоматически. `save_sources` остаётся нужным только для трёх явных сценариев (раздел «Сохранение исходников» выше).

Каналы, через которые модель узнаёт о сохранении исходников:

- Описание MCP-инструментов `save_sources` и `load_sources` — видно при первом обращении.
- Подсказка в ответе `409 SNAPSHOT_REQUIRED` (развёртывание с внешним URL) — предлагает загрузить через `POST /sources` или передать `X-Skip-Source-Snapshot`.
- Подсказка в ответе `409 SNAPSHOT_REQUIRED` (публикация без сохранённого снапшота) — направляет в цикл `publish → save_sources → publish` (актуально, если источник — внешний URL и автосохранение было пропущено).
- Блок `capabilities.apps.sourceStorage` в ответе `GET /v1/me` — программная проверка состояния.

## Смотрите также

- [Хранилище исходного кода](/docs/source-storage)
- [Сохранить снапшот](/docs/source-storage/save)
- [Снапшот перед публикацией](/docs/source-storage/publish)
- [Список версий и скачивание](/docs/source-storage/versions)
- [Деплой приложения](/docs/infra/deploy)
- [MCP для AI](/docs/mcp)
