FSP 1.0

FSP / Чейнджлог

Чейнджлог

Версии модулей независимы: правка в одном не поднимает версию остальных. Здесь фиксируется, что менялось и что это ломает.

Приложение пересобрано — 27.07.2026

Приложение отвечает на вопрос «как стандарт проверялся», а не ведёт список «дыр».

  • Реестр residual_gaps переосмыслен как находки проверки: конструкции, которых стандарту не хватало на реальных прайсах, и правки модулей, которыми они закрыты. Все восемь строк закрыты, реестр это показывает.
  • Строки про качество исходных прайс-листов конкретных операторов (пустые цены, непокрытые интервалы, режим НДС) и про внутренний конвейер нормализации из канона убраны: это разговор с владельцем прайса и рабочие задачи разметки, а не пробелы стандарта. Они ведутся с данными разбора, которые и так не публикуются.
  • Сводка 00_overview удалена из канона: перечень «сколько шкал, сколько областей, сколько правил» не помогает ни одному решению читателя, а каждое такое число — обязательство его обновлять. Числа остаются только там, где за ними стоит утверждение: проверено на 166 вариантах, 43 блокирующие проверки, реестры говорят сами за себя.

Правки документации — 26.07.2026

Версии модулей не менялись: нормативное содержимое не тронуто.

  • Документация разошлась с реестрами: «59 услуг» при 61, «92 поля условий» при 97, «21 код непокрытия» при 22, версии 1.0 в заголовках README и преамбулах реестров при фактических 2.0/1.3/2.0/1.4. Числа исправлены, версия модуля из прозы убрана совсем — она живёт в module.json и подставляется витриной.
  • Новая блокирующая проверка валидатора «Документация не расходится с реестрами»: версии в заголовках и преамбулах, таблицы модулей в README против module.json, числовые заявления против реестров. Заявление, не найденное по шаблону, — тоже ошибка, иначе переформулировка молча отключает проверку. Всего проверок 43.
  • Из нормативных материалов убраны упоминания ведущего вендора: пример согласования манифестов — про нейтральную площадку «Биржа», пример-манифест агрегатора переименован в aggregator.json, servers в OpenAPI заменён на operator.example с отсылкой к манифесту. Кто ведёт стандарт, по-прежнему прямо сказано в ABOUT.md.
  • Примеры манифестов объявляют текущие версии модулей, а не только 1.0.
  • Заголовок раздела CONTRIBUTING противоречил его телу («без новой версии» против «это MINOR») — переименован в «Что попадает в MINOR».

core 2.0 — 25.07.2026

Стандарт перестал быть российским по умолчанию.

  • Страна у пункта назначения и у склада оператора, код ISO 3166-1 alpha-2. В реестре пунктов уже лежала 31 точка Казахстана, Беларуси, Армении и Киргизии — и все они были неотличимы от российских: ни юрисдикции, ни валюты, ни режима НДС по ним определить было нельзя.
  • Пять новых площадок: Ламода, М.Видео, Леруа, Kaspi и Uzum. Последние две — Казахстан и Узбекистан; список площадок больше не подразумевает Россию.
  • Валидатор проверяет формат кода страны.

Несовместимость: country — новое обязательное поле у склада оператора и у пункта назначения. По правилам версионирования это MAJOR, поэтому 2.0, хотя правка маленькая.

capacity 2.0, quote 1.4 — 25.07.2026

Ломающая правка модуля мощностей. Свободная мощность объявлялась только площадью, а из площади ёмкость не выводится: сто квадратных метров напольного хранения и сто квадратных метров стеллажей в шесть ярусов различаются кратно. Заявка при этом приходит с объёмом товара, то есть заявка и мощность жили в несравнимых величинах, и каждое сопоставление опиралось на невидимый коэффициент.

capacity 2.0

  • Три равноправные величины вместо одной обязательной площади: free_m3, free_pallet_places, free_m2. Заполнить нужно хотя бы одну — ту, которой оператор реально оперирует.
  • Паллето-места перестали быть производной от площади. Оператор паллетного склада знает именно места; требовать от него метры значило просить менее точное число. Коэффициент пересчёта из справочника типов убран: универсального не существует, он так и стоял незаполненным.
  • usable_height_m — полезная высота. Обязательна, если заполнена только площадь (CAP-006).
  • CAP-001 переписано: базовой единицы мощности больше нет.

Несовместимость: free_m2 больше не обязательна, поля pallet_places больше нет — вместо него free_pallet_places.

quote 1.4

  • Код непокрытия capacity_not_comparable: мощность объявлена только площадью и без высоты, ёмкость невыводима. Оператор попадает в выдачу с этим кодом, а не с придуманным объёмом. Причин непокрытия стало 22.

core 1.4, pricing 1.3, quote 1.3 — 25.07.2026

Пачка правок, найденных на живых прайсах и в разборе сценариев работы склада.

Каталог: две новые услуги

  • Выдача товара при самовывозе (pickup_handover). Самовывоз выпадал из каталога: отгрузка описывает передачу груза перевозчику, а когда получатель приезжает сам, ни перевозчика, ни маршрута нет. Работа заканчивается идентификацией получателя и передачей из рук в руки. Обязательный параметр — получатель: покупатель, селлер, курьер или иной.
  • Погрузка (outbound_loading). Разгрузка была отдельной услугой с параметром способа, а погрузка молча сидела внутри отгрузки. Работа одна и та же в разные стороны, в прайсах обе идут отдельной строкой. Параметр loading_method переименован в «Способ погрузочных работ» и привязан к обеим услугам; код не менялся.

Отгрузка после этого описана точнее: формирование отправления и передача перевозчику. Загрузка транспорта и сопроводительные документы — отдельные услуги.

pallet_wrapping переименована в «Стрейчевание»; код неизменяем (CAT-001).

Хранение: тип и стадия

Паллетное и полочное хранение — не варианты одной цены, а разные сценарии: паллетами товар стоит на длительном хранении, за объём его берут на полках в обработке. Развести их было нечем: справочник типов жил в модуле мощностей и полем условия не был, а зона хранения — внутренний идентификатор оператора, между операторами несравнимый.

  • Поле условия storage_type — из того же закрытого справочника, что в мощностях.
  • Поле условия и параметр stock_state — стадия товара на складе: приёмка, хранение, обработка, ожидание отгрузки, отгрузка. Товар на столах упаковщиков и собранный под отгрузку физически на складе, но не на хранении.
  • STORAGE-004: стадии тарифицируются независимо, у каждой может быть своя ставка. Если правило не ограничено стадией, оно применяется ко всему товару на складе; освобождение задаётся явным нулём, а не отсутствием правила.
  • STORAGE-005: паллетное и полочное — одна услуга, разведённая условием, а не две услуги и не взаимоисключающие варианты цены.

Индивидуальные цены

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

  • Поля audience (public / private) и client_ref у тарифного плана. Схема требует client_ref у адресного плана и запрещает у публичного.
  • PRICE-022: адресный план не участвует в публичных выдачах и применяется только к контрагенту, которого оператор опознал. По анонимному запросу смета считается исключительно по публичному плану — иначе через открытый запрос можно выведать чужие условия.
  • PRICE-023: скидка за объём, оборот или срок договора выражается условиями и ступенями публичного плана, а не адресным планом. Такая цена остаётся сравнимой.
  • QUOTE-009 и поле pricing_audience: смета обязана сообщать, по публичному или адресному плану посчитана. Иначе две сметы одного оператора выглядят как противоречие.

Наследования у планов нет: адресный план — самостоятельный набор правил.

core 1.3, pricing 1.2 — 25.07.2026

Две дыры, которые видно на живом прайсе: маркировка тарифицировалась за заказ, а стандарт разрешал ей только товар, этикетку и час; отгрузка считалась за литр, а литра в единицах начисления не было вовсе.

core 1.3

  • Новые единицы начисления: литр и литро-день. Логистика маркетплейсов считается в литрах, и пересчитывать её в кубометры при разборе прайса неправильно: теряется исходная форма цены и правила округления.
  • Маркировка теперь может тарифицироваться за заказ: оператор берёт фиксированную сумму с заказа независимо от числа маркируемых единиц.
  • Отгрузка и доставка до маркетплейса допускают литры, хранение — литро-дни. Литро-день встал в тот же ряд, что товаро-день и паллето-день.
  • Расчётная метрика volume_l: литры и кубометры — одна величина в разных единицах, и формула перевода канонична, чтобы два оператора не пересчитывали её по-своему.

pricing 1.2

  • Поле условия volume_l и одноимённая шкала ступеней: цена может зависеть от объёма в литрах напрямую.

core 1.2, capacity 1.1, pricing 1.1, quote 1.2 — 25.07.2026

Доставка перестала быть абстрактной. До этой версии направление маршрута лежало свободной строкой, и «Коледино» одного оператора не сходилось с «Каледино» другого, хотя склад один. Сравнить две доставки было невозможно.

core 1.2

  • Новый реестр «Пункты назначения»: 1039 точек, до которых оператор везёт. Склады поставок и точки сдачи Wildberries, фулфилмент-центры, сортировочные и распределительные центры, кросс-доки и точки приёма заказов Ozon. У каждой строки идентификатор маркетплейса, поэтому ссылка однозначна.
  • Реестр собирается из официальных справочников маркетплейсов, а не заполняется руками.
  • Пункты выдачи покупателю и постаматы в реестр не входят: их десятки тысяч и состав меняется постоянно, ссылка на них идёт внешним идентификатором (CAT-012).

capacity 1.1

  • Маршрут ссылается на пункт назначения кодом, а не строкой. Название рядом остаётся для показа человеку и идентификатором не является (CAP-005).
  • Для пунктов выдачи и постаматов есть поле с идентификатором маркетплейса.

pricing 1.1

  • Поле условия destination_id: цена может зависеть от конкретного пункта назначения, а не от направления вообще.

quote 1.2

  • Направления запроса задаются кодами реестра. Свободный текст остаётся допустимым, но сравнить по нему нельзя.

Валидатор

  • Новая проверка реестра пунктов: дубли кодов, типы, маркетплейсы и статусы из закрытых списков. Всего проверок 42.

core 1.1, quote 1.1 — 25.07.2026

Первая правка после публикации. Нашлась при сверке разобранных прайсов с реестром допустимых единиц начисления: 24 строки из реальных прайс-листов использовали единицу, которую стандарт для этой услуги не разрешал, и валидатор этого не замечал.

core 1.1

  • Единица «товар» разрешена для отгрузки, разгрузки и доставки до маркетплейса. Все три встречаются в живых прайсах со ставкой за штуку.
  • У оператора появилось необязательное поле tax_id — налоговый идентификатор юрлица (ИНН в России, VAT number в ЕС). Позволяет проверить контрагента и сверить заявленный режим НДС. Банковские реквизиты в стандарт не добавлены: им место в договоре, а не в протоколе.

quote 1.1

  • Ответ на запрос сметы обязан раскрывать НДС: сумма без налога, сумма налога и режим его учёта (QUOTE-008). До этого возвращалась одна итоговая цифра, и смета с НДС была несравнима со сметой без него — разница в 20 процентов выглядела как разница в цене.

Валидатор

  • Новая проверка: единица начисления в разобранной строке прайса обязана быть разрешена для услуги. Источник истины — реестр «Метрики услуг» (CAT-010), а не текст строки. Всего проверок 41.
  • Манифест модуля объявляет список опубликованных версий (versions), текущая — последняя. Сторона вправе объявить любую из них: MINOR не отменяет предыдущие.

FSP 1.0 — 25.07.2026

Первая публичная версия протокола.

Модули: core 1.0, pricing 1.0, capacity 1.0, quote 1.0 — stable. order, tracking — planned, без реестров.

Что определяет версия

  • Общий язык (core): 59 услуг с неизменяемыми кодами, закрытый справочник единиц начисления, категории товара, габаритные профили с каноническими формулами, оператор и склад.
  • Описание прайса (pricing): rate_cards → offers → price_rules с условиями, модификаторами и ступенчатыми тарифами. Три уровня соответствия L1/L2/L3: плоский прайс описывается на L1, ступени требуют L3.
  • Мощности (capacity): витрина склада, свободная площадь и пропускная способность с отметкой актуальности, направления отгрузки с графиками.
  • Смета (quote): запрос операциями и объёмом, ответ со сметой, раскрытыми допущениями и кодами непокрытия из закрытого реестра.
  • Манифест (/.well-known/fsp): сторона объявляет модули, версии и уровни; стороны сводят манифесты и работают по пересечению. Правила PROFILE-001PROFILE-008.
  • 68 нормативных правил по модулям и 40 блокирующих проверок валидатора, включая сверку перечислений схем с реестрами и разрешимость ссылок между схемами.

Решения, которые стоит знать до реализации

  • Запрос сметы описывается работой и объёмом, а не площадью под хранение (QUOTE-001).
  • Формулы вывода площади и остатка не нормируются: применённые допущения обязаны возвращаться в ответе (QUOTE-002).
  • Свободная мощность декларативна, стандарт не требует её верификации (CAP-002).
  • Непокрытие возвращается кодом из закрытого реестра, а не текстом (QUOTE-003).
  • Коды услуг неизменяемы после публикации (CAT-001).
  • Своя операция вне стандарта оформляется расширением x-<vendor>:<code> и не ждёт новой версии (PROFILE-007).

Откуда взялся протокол и кто его ведёт — ABOUT.md.