{
  "profile": "bulk/1",
  "controlProfile": "open-alert-draft/0.20",
  "header": {
    "bytes": 20,
    "magicHex": "4f414231",
    "byteOrder": "big-endian",
    "types": {
      "DATA": 1,
      "ACK": 2,
      "ERROR": 3
    }
  },
  "budgets": [
    {
      "bytes": 1048576,
      "blockBytes": 4096,
      "windowBlocks": 4,
      "windowRoundTripMaxMs": 100,
      "blocks": 256,
      "windows": 64,
      "budgetMs": 606400
    },
    {
      "bytes": 33554432,
      "blockBytes": 4096,
      "windowBlocks": 4,
      "windowRoundTripMaxMs": 100,
      "blocks": 8192,
      "windows": 2048,
      "budgetMs": 804800
    },
    {
      "bytes": 33554432,
      "blockBytes": 4096,
      "windowBlocks": 4,
      "windowRoundTripMaxMs": 600,
      "blocks": 8192,
      "windows": 2048,
      "budgetMs": 1828800
    },
    {
      "bytes": 33554432,
      "blockBytes": 65536,
      "windowBlocks": 64,
      "windowRoundTripMaxMs": 100,
      "blocks": 512,
      "windows": 8,
      "budgetMs": 600800
    }
  ],
  "frames": [
    {
      "name": "single-tail",
      "type": "DATA",
      "offset": 0,
      "payloadHex": "616263",
      "hex": "4f41423101000000000000030000000000000000616263"
    },
    {
      "name": "tail-after-block",
      "type": "DATA",
      "offset": 4096,
      "payloadHex": "010203",
      "hex": "4f41423101000000000000030000000000001000010203"
    },
    {
      "name": "prefix-ack",
      "type": "ACK",
      "offset": 4096,
      "payloadHex": "",
      "hex": "4f41423102000000000000000000000000001000"
    },
    {
      "name": "stale-epoch",
      "type": "ERROR",
      "offset": 4096,
      "payloadHex": "0004",
      "hex": "4f414231030000000000000200000000000010000004"
    }
  ],
  "acceptanceTraces": [
    {
      "id": "bulk-window",
      "input": "S=4096,W=4,receivedBytes=0; четыре DATA без ACK",
      "expected": "Допущены 16384 байта; пятый DATA до ACK запрещен. ACK 4096 разрешает следующий полный блок."
    },
    {
      "id": "bulk-power-cut",
      "input": "ACK=8192, приняты еще 4096 без долговременной фиксации; потеря питания",
      "expected": "Новый hello возвращает 8192 и новый контекст; подтвержденные байты сохранены, незафиксированный хвост не считается принятым."
    },
    {
      "id": "bulk-lost-ack",
      "input": "Сохранено 12288; клиент видел ACK 8192; разрыв",
      "expected": "Новый hello возвращает 12288; отправка начинается с 12288 без повторной записи подтвержденного префикса."
    },
    {
      "id": "bulk-preemption",
      "input": "maintenance передает окно; допущенный real требует владение",
      "expected": "Сервисный шаг не более 100 мс, новая эпоха/ответ не позднее 500 мс; старое соединение не фиксирует новый префикс после отзыва."
    },
    {
      "id": "bulk-binding",
      "input": "Чужой principalId с верным transfer id, второй hello либо поздний close старого канала",
      "expected": "Действующая привязка и устойчивый префикс не изменяются."
    },
    {
      "id": "bulk-slow-peer",
      "input": "Неполный DATA либо заблокированная отправка ACK одновременно с heartbeat/отменой",
      "expected": "Ограниченные буферы и порционное обслуживание; сроки управления сохраняются, просроченное файловое соединение закрывается."
    },
    {
      "id": "bulk-final-state",
      "input": "ACK полного файла; ошибочный хеш или config-ссылка; гонка cancel/commit",
      "expected": "ACK не дает verified/staged/committed. Проверка отклоняет файл, старый объект сохранен; cancel/commit имеют единственный сохраненный исход."
    },
    {
      "id": "bulk-verification-long",
      "input": "Полный файл, действующая maintenance-эпоха; проверка длится 20000 мс, heartbeat через 5000 мс.",
      "expected": "config получает staged, firmware — verified, content — committed; прежний idle-срок 10000 мс не прерывает работу. После завершения idle не более 10000 мс."
    },
    {
      "id": "bulk-verification-deadline",
      "input": "Проверка не завершилась за 60000 мс; heartbeat, чтения, повторы и progressBytes продолжаются.",
      "expected": "failed/resultExpired в установленный срок; эти события не сдвигают срок проверки. Завершение на самой границе срока уже опоздало."
    },
    {
      "id": "bulk-verification-lease",
      "input": "Проверка дольше 30000 мс без допустимого продления lease владельцем.",
      "expected": "Истечение lease прекращает проверку на границе шага; файл возвращается в complete, старый обработчик не фиксирует результат."
    },
    {
      "id": "bulk-verification-real",
      "input": "Допущенный acquire real при t=15000 мс незавершенной проверки.",
      "expected": "Сервис прекращается до t=15100, новая эпоха и ответ до t=15500; старое завершение не дает staged/verified/committed."
    },
    {
      "id": "bulk-verification-restart",
      "input": "Отзыв эпохи в проверке; повтор под новым maintenance-владением, до общего срока остается 12000 мс.",
      "expected": "Повторная проверка получает не более оставшихся 12000 мс, не новые общие 600000 мс. Повтор в той же попытке не меняет ее срок."
    }
  ],
  "maintenanceTiming": {
    "idleMs": 10000,
    "verificationMs": 60000,
    "controlLeaseMs": 30000,
    "heartbeatIntervalMs": 5000,
    "serviceStepMs": 100,
    "realResponseMs": 500,
    "afterReceiveMs": 600000
  }
}
