> For the complete documentation index, see [llms.txt](https://lmile.gitbook.io/lmile-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lmile.gitbook.io/lmile-docs/resources/changelog.md).

# Changelog

## 2026-10-22 — v156: ピッキングリストの CSV にお届け予定日・配達指定日時

### 変更

* [`POST /api/routing/picking-list/batch`](/lmile-docs/fulfillment-api/picking-list.md#post-apiroutingpicking-listbatch) の CSV（`format=csv`）に `お届け予定日` / `配達指定日` / `配達指定時間帯` の列を足しました。お届け予定日は購入者のお届け状況ページと同じ計算です

## 2026-10-22 — v155: 受注明細の変更ログに、内容が同じ再送を記録しない

### 変更

* [`POST /api/order-line-master/bulk-upsert`](/lmile-docs/ingestion-api/order-line-master.md) は、内容が同じ行の再送を変更ログに記録しなくなりました。応答に `unchanged_rows`（何もしなかった件数）を足しました。`updated_rows` は値が変わった行だけになります。日時（`ordered_at` / `refunded_at`）は表記ではなく時刻で比べます
* 変更ログ（`order_line_master_update_logs`）は 365 日で消えます

## 2026-10-21 — v154: Shopify の顧客を顧客として取り込む

### 追加

* [`POST /api/ingest/customers`](/lmile-docs/ingestion-api/customers.md)。Shopify の顧客（購入の無い人を含む）を顧客にします。氏名・メールアドレス・電話番号は Shopify に合わせ、古い更新は当てません
* [`POST /api/ingest/customers/delete`](/lmile-docs/ingestion-api/customers.md#post-apiingestcustomersdelete)。Shopify で削除された顧客を消します

## 2026-10-20 — v153: 確保の履歴を返す

### 追加

* [`GET /api/operator/secure-history`](/lmile-docs/operator-api/queues.md)。拠点で確保した商品を、確保した時刻の新しい順に返します。出荷済み・取消・刻印などで別の拠点へ送る荷物になったあとも残ります

## 2026-10-19 — v152: アプリへの配信を自動で再送し、署名を Standard Webhooks にそろえる

### 変更

* [Apps](/lmile-docs/apps/overview.md) への配信が失敗したとき、LMile が自動で再送するようになりました（既定 6 回・約 7.5 時間）。送信元が自分で再送するイベント（倉庫への出荷指示など）は再送しません
* 配信の署名を [Standard Webhooks](https://www.standardwebhooks.com/) 形式（`webhook-id` / `webhook-timestamp` / `webhook-signature`）にそろえました。旧形式のヘッダーは送りません
* イベントの型を [`events.schema.json`](https://github.com/falcon0119/inventory-os/tree/main/docs/apps/events/events.schema.json) で公開しました。実行環境は handler を呼ぶ前にこの型で中身を確かめます
* handler の実行が上限を超えると `ctx.signal` が中断されるようになりました

## 2026-10-16 — v151: 配送状況の照会先 (`action=track`) を登録できるようにする

### 追加

* [`POST /api/routing/dispatch-config`](/lmile-docs/configuration/dispatch-config.md) が `action: "track"` を受け付けるようになりました。`payloadTemplate` は省略できます。照会先の `adapterType` に `dhl_unified`（DHL の追跡 API）を追加しました

## 2026-10-15 — v150: 注文履歴に出荷元ごとの注文ステータスを返す

### 追加

* [`POST /api/customer-orders/list`](/lmile-docs/customer-orders-api/orders.md) の `orders[].shipments[]`（出荷元の `id` と注文ステータス `orderStatus`）。まとめた受注レコード全部の出荷元を返す。`detail` の `shipments[]` にも `orderStatus` を足した

## 2026-10-15 — v149: 注文履歴の購入点数から返金した点数を引く

### 変更

* [`POST /api/customer-orders/list`](/lmile-docs/customer-orders-api/orders.md) の `itemCount` と、list / detail の `items[].quantity` が、返金した点数を差し引いた数になりました。全部返金した商品は `items[]` に含まれません。金額 (`total` / `amounts`) は変わりません

## 2026-10-14 — v148: 即時切替の変更先に、MFC でない出荷元を選べるようにする

### 変更

* [`POST /api/routing/change-source`](/lmile-docs/oversell-api/source-change.md) の `mode: "switch"` が、店舗に引き当てられた単位（出荷元だけが変わる）に限り、有効な在庫メンバーを持つ出荷元なら MFC / `return_destination_enabled` でなくても受け付けるようになりました（店舗を兼ねる出荷元など）。自己在庫の MFC に引き当てた単位と `transfer` の条件は変わりません

## 2026-10-14 — v147: 店舗受け取り（BOPIS）の注文を 受取待ち / 引渡し済み で進める

### 追加

* [`POST /api/routing/orders`](/lmile-docs/routing-api/orders.md) に `deliveryMethod`（`shipping` / `pickup`）。`pickup` の注文は受け取り店舗に引き当て、配送ラベルを発行しない
* [`POST /api/routing/store-pickup/ready`](/lmile-docs/fulfillment-api/store-pickup.md) / [`POST /api/routing/store-pickup/handover`](/lmile-docs/fulfillment-api/store-pickup.md) — 店頭の操作で受取待ち / 引渡し済みにする
* [Fulfillment Status Webhook](/lmile-docs/webhooks/fulfillment-status.md) に `status_after` = `store_pickup_ready` / `store_pickup_handed_over`

### 変更

* 注文ステータスに `ready_for_pickup`（受取待ち）と `picked_up`（引渡し済み）を追加（9 → 11 値）。配送の荷物の段は変わらない

## 2026-10-14 — v146: 来店予約のご来店の目的を返す

### 追加

* [`GET /api/operator/visit/reservations`](/lmile-docs/operator-api/visit.md#get-apioperatorvisitreservations) と [`POST /api/operator/visit/check-in`](/lmile-docs/operator-api/visit.md#post-apioperatorvisitcheck-in) の予約に `purpose`（お客様が選んだご来店の目的。聞かないメニューは `null`）を追加しました

## 2026-10-14 — v146: 拠点一覧の `memberOnly` に、来店予約の受付が有効な拠点を含める

### 変更

* [`GET /api/operator/locations`](/lmile-docs/operator-api/locations.md#get-apioperatorlocations) の `memberOnly=true` が、出荷元メンバーの拠点に加えて、来店予約の受付が有効な拠点も返すようになりました。出荷が流れない新店でも、店頭のスタッフがその拠点を選んで来店予約を確認できます

## 2026-10-14 — v145: 来店予約の同伴者の人数を返す

### 追加

* [`GET /api/operator/visit/reservations`](/lmile-docs/operator-api/visit.md#get-apioperatorvisitreservations) と [`POST /api/operator/visit/check-in`](/lmile-docs/operator-api/visit.md#post-apioperatorvisitcheck-in) の予約に `companionCount`（同伴者の人数。本人は含まない）を追加しました

## 2026-10-14 — v144: 店頭で来店予約を確認し、QR を読んで来店を記録できる

### 追加

* [`GET /api/operator/visit/reservations`](/lmile-docs/operator-api/visit.md#get-apioperatorvisitreservations): 拠点のその日の来店予約を開始時刻の早い順に返します。`code` に予約ページの QR の中身を送ると、その予約を 1 件返します
* [`POST /api/operator/visit/check-in`](/lmile-docs/operator-api/visit.md#post-apioperatorvisitcheck-in): 確定している予約を「来店済み」にします。同じ予約に再送しても安全です

## 2026-10-13 — v143: 出荷元メンバーの在庫ロケーションを、指定した商品だけ対象にできる

### 追加

* [`POST /api/routing/source-members`](/lmile-docs/configuration/source-members.md#post-apiroutingsource-members) に `onlyBarcodes` を追加しました。送ると、その在庫ロケーションは指定した商品だけ出荷元の合算在庫に足され、引き当ての候補になります。`[]` はどの商品も対象にしない、`null` は全商品。省略すると既存の値を変えません。新しい店舗を 1 商品だけで試してから広げる、といった使い方ができます

## 2026-10-12 — v142: 受注明細の取引に、注文のメールの顧客を結び付けられる

### 追加

* [`POST /api/order-line-master/customers`](/lmile-docs/ingestion-api/order-line-master.md#post-apiorder-line-mastercustomers): 受注明細に取り込んだ取引（店頭販売など、配送の宛先を持たないもの）に、注文のメールの顧客を結び付けます。同じメールの顧客がいなければ作り、いれば上書きしません

## 2026-10-12 — v141: 受注明細の取込で、拠点を取込元の識別子・販売チャネルをコードで指定できる

### 追加

* [`POST /api/order-line-master/bulk-upsert`](/lmile-docs/ingestion-api/order-line-master.md#post-apiorder-line-masterbulk-upsert) の各行で、`location_id` の代わりに `location`（`{ identifier_type, identifier_value }`。例 `smaregi_store_id`）、`channel_id` の代わりに `channel_code`（例 `store`）を送れるようになりました。ID で送る行はこれまでどおりです。識別子に当たる拠点が無い・2 つ以上ある行は `location_unresolved` / `location_ambiguous` で reject します

### 変更

* 読み取り view `agent_read.lm_routed_orders` から、[`/api/routing/orders/shipped`](/lmile-docs/routing-api/orders.md#post-apiroutingordersshipped) で登録したスマレジの店頭販売を外しました（振り分けた注文ではないため）

## 2026-10-12 — v140: 外部で引き渡しが終わった注文を、取込元の取消に合わせて取消にできる

### 追加

* [`POST /api/routing/orders/shipped/cancel`](/lmile-docs/routing-api/orders.md#post-apiroutingordersshippedcancel): `/api/routing/orders/shipped` で登録した注文（スマレジの取引など）が取込元で取り消されたとき、受注と出荷・単位を取消にします。お届け状況は配達完了からでも「取消」になります（この経路で登録した出荷に限ります）。在庫・配送ラベル・購入者や現場への通知は動きません。引き当てを通った出荷が生きている注文は `409 leg_not_external` で断ります。既に取消済みなら `idempotent: true`。

## 2026-10-10 — v139: 店頭販売など、外部で引き渡しが終わった注文を出荷済みで登録できる

### 追加

* [`POST /api/routing/orders/shipped`](/lmile-docs/routing-api/orders.md#post-apiroutingordersshipped): 取込元で既に引き渡しが終わっている注文（スマレジの取引など）を、受注とその拠点から出荷済みの出荷として登録します。引き当て・在庫・配送ラベル・購入者への通知は動きません。拠点は UUID か取込元の識別子（`smaregi_store_id` など）で指せます。同じ注文・同じ拠点の再送は `idempotent: true` で何も変えません。`dryRun: true` で判定だけ返し、何も書きません。`channel` が店舗のチャネル（種別 `store`）なら、お届け状況は発送済みではなく配達完了で入ります。

## 2026-10-09 — v138: 顧客注文照会が注文番号と明細を返し、分かれた受注を 1 注文にまとめる

### 変更

* [`POST /api/customer-orders/list`](/lmile-docs/customer-orders-api/orders.md#post-apicustomer-orderslist) の `orderNumber` を、routing に渡した注文番号（`orderName`。例 `BJP1001`）にしました。これまではカート側の注文識別子（`externalOrderRef`）で、刻印の注文では `…-engraved` のような値になっていました。識別子は新しい `externalOrderRef` で返します。
* 1 つの買い物が複数の受注レコードに分かれていても（刻印 / 出荷元の分割 / 予約分）、同じ取込元・同じ注文番号のレコードを **1 行にまとめて**返します。`totalCount` もまとめた後の数です。これまでは分かれたレコードがそれぞれ 1 行になり、`-engraved` のレコードは明細と突合できず `itemCount` / `total` が `null` でした。
* `list` の各注文に `items[]`（`detail` と同じ形の明細。商品名は商品マスターの値）を足しました。
* [`POST /api/customer-orders/detail`](/lmile-docs/customer-orders-api/orders.md#post-apicustomer-ordersdetail) も同じまとめ方になり、`orderId` がまとめた受注レコードのどれでも、同じ買い物として明細・出荷元を返します。

## 2026-10-08 — v137: 棚の数を、引き当て済みの数より少なくできない

### 変更

* `POST /api/shelf/inventory/adjust` と `POST /api/shelf/inventory/move`（barcode を付け替える場合）は、減らした結果その商品の棚の合計が注文に引き当て済みの数を下回るとき `409 shelf_qty_below_active` を返すようになりました。何も変更されません。数を増やす操作と、同じ商品を別の棚へ移すだけの操作、すでに下回っている在庫を実数に直す操作はこれまでどおりです。
* [`POST /api/shelf/inventory/move`](/lmile-docs/shelf-api/inventory.md#post-apishelfinventorymove) と [`POST /api/shelf/inventory/adjust`](/lmile-docs/shelf-api/inventory.md#post-apishelfinventoryadjust) のページを足しました（これまでも使えていました）。

## 2026-10-08 — v136: 店舗（スマレジ / Shopify が在庫の正の拠点）でも棚卸ができる

### 追加

* [Stocktake — 棚卸](/lmile-docs/operator-api/stocktake.md) を店舗でも開けるようにしました（`mode: "location"`。MFC は従来どおり `shelf`）。数え方は同じで、`shelfCode` に売場 / バックヤードなどのエリアのコードを入れます。提出（`transition: submit`）で商品ごとの帳簿数（取り込み元の生の在庫数 + 注文に引き当て済みで未確保の数）を固定し、承認（`commit`）で差分を[外部システムへの調整](/lmile-docs/routing-api/inventory-adjustments.md)として貯めます（在庫同期の向きが双方向の拠点だけ。取り込みのみの拠点は差異の記録まで）。帳簿にあるのにどのエリアでも読まれなかった商品は 0 と数えた行（`uncounted`）になり、`includeUncounted: true` で通せます。数えている間に動いた商品は保留になり、`includeMoved: true` で通せます（承認のたびに開始〜提出の窓で見直します）。帳簿数の取り込み元が当てる先のコネクタと違う商品は `book_source_mismatch` で保留します。生の在庫数が一度も届いていない拠点は `422 book_quantity_unavailable` で承認しません。
* [Inventory Adjustments — 外部システムへの在庫調整](/lmile-docs/routing-api/inventory-adjustments.md): `POST /api/routing/inventory-adjustments/claim`（コネクタが自分の分を取りに来る）/ `result`（当てた結果を返す）。差分は相対値で、`claimed` のまま 30 分結果が返らない行は取り直せます。
* 読み取り view `agent_read.stocktake_location_lines` / `inventory_external_adjustments`。
* `GET /api/operator/stocktake/current` に `locationMode`（この拠点で開く形）と `syncMode`（在庫同期の向き）を足しました。

## 2026-10-08 — v135: 旧の商品状態の仕組み（販売可能数の内訳・分類 API・隔離移動）を撤去

### 削除

* `POST /api/ingest/inventory-classification`（販売可能数を状態別に色分けする）と `POST /api/operator/inventory/block` / `unblock`（非販売品を隔離拠点へ移す）を削除しました。本番で使われていませんでした。商品状態は [棚ごとの状態の数](/lmile-docs/shelf-api/inventory.md#post-apishelfinventorycondition-move) に置き換わっています（良品以外は販売可能数に入りません）。旧ページは [Shelf Inventory](/lmile-docs/shelf-api/inventory.md) へリダイレクトします。
* 読み取り view `agent_read.inventory_balances` を削除しました。商品状態の一覧 `agent_read.inventory_condition_codes` と取り置きの履歴 `agent_read.inventory_ledger` は残ります。

## 2026-10-08 — v134: 棚のピックと MFC 在庫取込でも、引き当て済みの数を下回れない

### 変更

* [`POST /api/shelf/inventory/pick`](/lmile-docs/shelf-api/inventory.md) と [`POST /api/ingest/mfc-inventory`](/lmile-docs/ingestion-api/mfc-inventory.md)（`absolute` の減らし・`adjust` の `-`）は、減らした結果その商品の棚の合計が注文に引き当て済みの数を下回るとき `409 shelf_qty_below_active` を返すようになりました。何も変更されません。現場アプリの集荷・確保は止まりません。同じ商品の棚移動（`-1` / `+1`）もこれまでどおりです。

## 2026-10-08 — v133: 棚卸を「棚ごとに数える → 差異を見る → 承認して反映」の形に

### 追加

* [Stocktake — 棚卸](/lmile-docs/operator-api/stocktake.md) を作り直しました。`POST /api/operator/stocktake/open`（セッションを開く）/ `shelf-start`（棚を数え始める）/ `shelf-submit`（数えた数をまとめて送って締める。帳簿数を固定し差異を返す）/ `transition`（提出・取消・取り下げ）/ `commit`（承認して反映）。商品状態ごとに数えられます。反映は締めた時点との差分を当てるので、締めたあとの出荷・入庫と二重になりません。良品の合計が引き当て済みの数を下回る商品と、負になる行は保留にして残りを反映します。
* 読み取り view `agent_read.stocktake_sessions` / `stocktake_shelves` / `stocktake_counts` を作り直しました。

### 削除

* `POST /api/ingest/stocktake` と旧 `POST /api/operator/stocktake/commit`（`stocktake_key` で確定するもの）を削除しました。本番で使われていませんでした。旧ページは新ページへリダイレクトします。

## 2026-10-08 — v132: 棚ごとに良品以外の商品状態の数を持てる / 棚マスタ

### 追加

* [`POST /api/shelf/inventory/condition-move`](/lmile-docs/shelf-api/inventory.md#post-apishelfinventorycondition-move) を追加しました。同じ棚・同じ商品の数を、商品状態（良品 ⇄ アウトレット・展示用・不良品・検品中など）の間で動かします。良品以外の数は販売可能数に入りません（注文の引き当て対象外）。良品を減らすときは、注文に引き当て済みの数を下回る移動を止めます。
* [`POST /api/shelf/master/upsert`](/lmile-docs/shelf-api/shelves.md) を追加しました。棚の一覧（棚マスタ）に、空の棚の登録・売場 / バックヤードなどの区分・有効 / 無効を持てます。棚在庫に新しい棚が現れると自動で登録されます。
* 読み取り view `agent_read.shelf_stock`（棚 × 商品 × 状態の数）と `agent_read.shelves`（棚の一覧）を追加しました。

## 2026-10-08 — v131: 棚の在庫の行は MFC の拠点にだけ作れる

### 変更

* 棚の在庫の行は、MFC（`location_type` が `mfc`、または `mfc_enabled` の拠点）にだけ作れるようになりました。[`POST /api/shelf/inventory/receive`](/lmile-docs/shelf-api/inventory.md)・`move`・`adjust`、[`POST /api/ingest/mfc-inventory`](/lmile-docs/ingestion-api/mfc-inventory.md) で MFC ではない拠点に棚の行を作ろうとすると `422 not_self_inventory_location` を返します。既にある行を減らす操作と、MFC の拠点への操作はこれまでどおりです。

## 2026-10-08 — v130: 商品マスターを sku でも引ける

### 変更

* [`GET /api/ingest/products`](/lmile-docs/ingestion-api/products.md#get-apiingestproducts) に `skus` を追加しました。`barcodes` と `skus` のどちらかを送ります。`sku` は一意とは限らないので一致した行をすべて返します。取込元の商品コードから `barcode` を決めるときに、受け取った側で「ちょうど 1 件か」を確かめて使ってください。

## 2026-10-08 — v129: 商品マスターを barcode で引く

### 追加

* [`GET /api/ingest/products`](/lmile-docs/ingestion-api/products.md#get-apiingestproducts) を追加しました。`barcodes` にカンマ区切りで渡した `barcode` のうち、商品マスターにあるものとその `sku` を返します。取込元（EC モール等）から取れた `barcode` が登録済みかを、受注を送る前に確かめるときに使います。

## 2026-10-08 — v128: 在庫移動の送り状の出し方を作成のときに決められる

### 追加

* [`POST /api/routing/stock-transfer/create-request`](https://lmile.gitbook.io/lmile-docs/resources/pages/20DiVRGUzk7qNxNjt17I#送り状の出し方labelmethod) に `labelMethod` を追加しました。`"issue"` は出庫のときに配送ラベルを発行して印刷し、追跡番号を箱に記録します。`"manual"` は手書きの送り状で、出庫のときに追跡番号が必須になります。省略した移動はこれまでどおりです。
* [`POST /api/routing/stock-transfer/label-options`](/lmile-docs/stock-transfer-api/stock-transfer.md#post-apiroutingstock-transferlabel-options) を追加しました。配送ラベルを発行できる出庫元と、宛先にできる入庫先（住所が入っている拠点）を返します。
* [`POST /api/routing/stock-transfer/print-label`](/lmile-docs/stock-transfer-api/stock-transfer.md#post-apiroutingstock-transferprint-label) を追加しました。発行済みの配送ラベルをもう一度印刷します（追跡番号は変わりません）。

### 変更

* [`POST /api/routing/stock-transfer/ship`](/lmile-docs/stock-transfer-api/stock-transfer.md#post-apiroutingstock-transfership) の `trackingNumber` / `carrierCode` をページに載せました（箱の追跡番号。これまでも受け付けていました）。`labelMethod` を決めた移動では、出庫の前に送り状を用意します（発行に失敗・追跡番号が無いときは出庫しません）。

## 2026-10-07 — v127: 現場アプリにメールの確認コードでログインできる

### 追加

* [`POST /api/operator/login/otp/request`](/lmile-docs/operator-api/login.md#post-apioperatorloginotprequest) と [`POST /api/operator/login/otp/verify`](/lmile-docs/operator-api/login.md#post-apioperatorloginotpverify) を追加しました。スタッフのメールアドレスに確認コードを送り、そのコードでログインできます。パスワードも Google / Apple のアカウントも使わないスタッフ向けです。アカウントは作られません（すでにあるアカウントだけが対象）。

## 2026-10-06 — v126: 商品と出荷元の組み合わせで在庫連携を止められる

### 追加

* [`POST /api/ingest/products`](/lmile-docs/ingestion-api/products.md) に `inventory_push_disabled_source_ids` を追加しました。商品ごとに、在庫連携を止める出荷元を拠点 id の配列で指定します。指定した出荷元については、[出荷元在庫の通知](/lmile-docs/webhooks/source-inventory.md) の `availableTotal` が `0` になります。販売チャネルでその出荷元から売りたくない商品に使います。設定を変えた出荷元には、在庫の変動を待たずに 1 回通知します（止めた出荷元は `0`、再開した出荷元は最新の合算）。

## 2026-10-06 — v125: まとめて 1 箱で出す出荷にも追跡番号を入れられる

### 変更

* [`POST /api/routing/shipment/ship`](/lmile-docs/fulfillment-api/external-fulfillment.md#post-apiroutingshipmentship) で、複数店舗分を 1 箱にまとめる MFC 集約グループの出荷にも `trackingNumber` を指定できるようにしました。これまでは `400` で拒否していたため、配送ラベルを自動発行しない出荷元では箱に追跡番号を付けられず、出荷済みにできませんでした。指定した番号はグループ先頭の出荷に保存し、出荷ステータス通知にも載ります。`carrierCode` だけを `trackingNumber` なしで指定した場合は引き続き `400` です。

## 2026-10-05 — v124: 確保済みを解除できる

### 追加

* [`POST /api/routing/shipment/unsecure`](/lmile-docs/fulfillment-api/shipment-unsecure.md) を追加しました。誤って確保済みにした単位を、確保前へ戻せます。戻せるのは集荷前の単位だけです。

## 2026-10-04 — v123: 在庫行が無い商品にも販売チャネルの販売可能数を反映する

### 変更

* [`POST /api/ingest/channel-available`](/lmile-docs/ingestion-api/inventory-levels.md#post-apiingestchannel-available) で、その拠点に在庫行がまだ無い商品（倉庫から一度も在庫数が届いていない新商品など）を `unresolved[]`（`level_not_found`）で返すのをやめ、在庫 0 の行を作って反映するようにしました。再送は不要です。

## 2026-10-01 — v122: 引き当ての前に出荷元を確認できる

### 追加

* [`POST /api/routing/orders`](/lmile-docs/routing-api/orders.md) で、出荷元を引き当ての前に確認するアプリを登録したストアでは、アプリが答えた出荷元で引き当てるようになりました。確認が取れないときは引き当てずに `202`（`status: received` / `pending: "source_decision"`）を返し、確認が取れた時点で自動で引き当てます。再送は不要です。アプリを登録していないストアの動きは変わりません。

## 2026-09-29 — v121: 出荷準備中にするときに手書きの送り状の追跡番号を送れる

### 追加

* [`POST /api/routing/shipment/collect`](/lmile-docs/fulfillment-api/shipment-collect.md) に `trackingNumber` / `carrierCode` / `trackingCompany` / `trackingUrl` を追加しました。配送ラベルを発行しない出荷で、送り状を箱に付ける段階の追跡番号を保存できます。保存した番号は、出荷済みにするときに追跡番号を送らなければそのまま使われます。
* 配送ラベルを発行済みの出荷に追跡番号を送ると `409 label_already_issued` を返します。

## 2026-09-27 — v120: 外部倉庫の拠点で、販売チャネルで売れない商品を販売可能在庫 0 に

### 追加

* [`POST /api/ingest/channel-available`](/lmile-docs/ingestion-api/inventory-levels.md#post-apiingestchannel-available) を追加しました。在庫数を外部倉庫が送ってくる拠点で、販売チャネル（Shopify など）での販売可能数を伝えます。0 以下を送った商品は、倉庫に現物があってもその拠点の販売可能在庫が 0 になります。1 以上を送ると通常の計算に戻ります。倉庫から届いた在庫数は書き換えず、受注の引き当ても止まりません。

## 2026-09-25 — v119: 配達希望日を遅らせたときの遅延のお知らせ

### 追加

* [`POST /api/routing/shipment/delivery`](/lmile-docs/fulfillment-api/shipment-delivery.md) に `notifyDelay` を追加しました。配達希望日を遅らせる（または指定なしにする）ときに `true` を送ると、購入者へ遅延のお知らせメールを送ります。レスポンスに `delayed`（遅延だったか）と `delayNotice`（お知らせの送信結果）を追加しました。
* 配達希望日を遅らせると、購入者のお届け状況ページに「遅延」と変更前 → いまの予定が出ます。

## 2026-09-25 — v118: 予約納期の `"*"` キーを受け付けない

### 変更

* [`POST /api/ingest/products`](/lmile-docs/ingestion-api/products.md) の `preorder_delivery_dates` に `"*"` のキーを送ると `400 invalid_input` になるようにしました。v117 の移行期間が終わったためです。キーには出荷元の拠点 ID を使ってください。保存済みのデータに `"*"` のキーはありません。

## 2026-09-25 — v117: 予約納期を出荷元ごとに

### 変更

* [`POST /api/ingest/products`](/lmile-docs/ingestion-api/products.md) の `preorder_delivery_dates` は、**出荷元の拠点 ID → その出荷元から出荷できるようになる日**の対応表になりました。配送先の国コードと `"*"`（全マーケット）のキーは使いません。行のある出荷元だけが商品を出荷でき、行の無い出荷元は候補から外れます。到着予定日はこの日から出荷元の作業日数と配送日数を積んで出します（配送先までの日数は計算が足すので、国ごとに日付を分ける必要はありません）。
* 移行: 既存の `"*"` の値は、そのショップの出荷元すべてに同じ日付として展開しました。キーに拠点 ID 以外を送ると `400 invalid_input` になります（`"*"` は移行中のみ受け付けます）。

## 2026-09-24 — v116: 送信先 URL は https のホスト名だけに

### 変更

* [配送・連携先の設定](/lmile-docs/configuration/dispatch-config.md)と[各 webhook 設定](/lmile-docs/webhooks/overview.md)の `destinationUrl` は、`https://` で始まるホスト名の URL だけを受け付けるようにしました。IP アドレス・`localhost`・`.internal`・`.local` を指定すると `422 invalid_destination_url` になります。保存済みの設定がこの条件を満たさない場合は、送信せずに失敗として記録します。

## 2026-09-24 — v115: 送信先を変えたときの認証情報の扱い

### 変更

* [配送・連携先の設定](/lmile-docs/configuration/dispatch-config.md)と各 webhook 設定で、`destinationUrl` か `authHeaderName` を変えるときに `authSecret` を省略すると、保存済みの認証情報を消すようにしました。以前の送信先の認証情報が新しい送信先に送られないようにするためです。送信先を変えるときは `authSecret` も送り直してください。

## 2026-09-24 — v114: 出荷済みにするとき配送業者の名前と追跡 URL を渡せるように

### 追加

* [`POST /api/routing/shipment/ship`](/lmile-docs/fulfillment-api/external-fulfillment.md) に `trackingCompany` / `trackingUrl` を追加しました。手書きの送り状などで出荷したときに、追跡番号と一緒に配送業者の名前と追跡ページの URL を渡せます。
* [出荷ステータス通知](/lmile-docs/webhooks/fulfillment-status.md)の payload に同じ 2 項目を載せます。指定が無ければ `null` です。

## 2026-09-18 — v113: 振り分けで購入者への通知・店舗での印刷を止められるように

### 追加

* [`POST /api/routing/orders`](/lmile-docs/routing-api/orders.md) に `suppressCustomerMail` を追加しました。`true` にすると、その注文では購入者にお届け状況メールを送りません。
* 同じく `suppressStorePrint` を追加しました。`true` にすると、その振り分けでは店舗で商品ラベル（統合QR）を自動印刷しません。引き当ての通知は通常どおり送ります。
* レスポンスの `customerMailSuppressed` / `storePrintSuppressed` で、指定を受け付けたかを確認できます。

## 2026-09-17 — v112: API キーを画面で発行できるように

### 変更

* API キーを Last Mile のコンソール（設定 > API キー）で自分で発行・失効できるようになりました（[認証](/lmile-docs/getting-started/authentication.md)）。キーは発行時に 1 回だけ表示されます。
* 各エンドポイントのページで、`shop` が省略できることを分かるようにしました。

## 2026-09-17 — v111: API キーだけで呼べるように

### 変更

* API キーが 1 つのアカウントにひも付いている場合、リクエストの `shop` を省略できるようになりました。省略すると、キーのアカウントとして処理します（[認証](/lmile-docs/getting-started/authentication.md)）。
* `shop` を送る既存の連携はそのまま動きます。キーと違う `shop` を送った場合は、これまでどおり `403` を返します。

## 2026-09-16 — v110: 在庫の取り置き

### 追加

* [`POST /api/inventory/hold`](/lmile-docs/ingestion-api/inventory-holds.md) を追加しました。拠点の在庫の一部を参照 ID ごとに取り置き、販売可能在庫から外します。取り置き分は受注の引き当てに使われず、Shopify の販売可能在庫からも減ります。
* 参照 ID を省略すると LastMile が生成して返します。期限（`expires_at`）を付けると、過ぎた時点で自動で解除されます。
* 取り置きは在庫の取込とは別に保存されます。POS・倉庫から在庫の絶対値が届いても消えません。
* [`POST /api/inventory/release`](/lmile-docs/ingestion-api/inventory-holds.md#post-apiinventoryrelease) を追加しました。参照 ID の取り置きをまとめて解除します。

### 修正

* [`POST /api/operator/inventory/block`](https://github.com/falcon0119/inventory-os/tree/main/docs/operator/inventory-block.md) / `unblock` で、販売可能在庫の変化が [Source Inventory Webhook](/lmile-docs/webhooks/source-inventory.md) で通知されていなかった問題を修正しました。隔離・戻しの直後に Shopify の販売可能在庫へ反映されます。

## 2026-09-14 — v109: 商品を付帯サービスとして登録できるように

### 追加

* [`POST /api/ingest/products`](/lmile-docs/ingestion-api/products.md) に `is_accessory_service` を追加しました。当日出荷チケットや刻印サービスのように、それだけでは出荷する荷物にならない明細の印です。
* `true` にした商品は在庫の引き当て対象から外れ、出荷指示の `serviceLines` に入ります。
* `false` を送ると通常の商品に戻ります。省略すると既存値を維持します。
* [`GET /api/ingest/accessory-services`](/lmile-docs/ingestion-api/products.md#get-apiingestaccessory-services) を追加しました。付帯サービスにした商品の一覧を返します。

## 2026-09-12 — v108: 商品タイプとメタフィールドを商品マスターに持てるように

### 追加

* [`POST /api/ingest/products`](/lmile-docs/ingestion-api/products.md) に `product_type` を追加しました。到着予定日の商品区分を判定するための項目です。カテゴリ（`category_l1`）とは別に持ちます — カテゴリにはカテゴリ体系の名前が入るため、商品タイプが失われていました。省略すると既存値を維持します。
* 同じく `class_metafields` を追加しました。商品区分をメタフィールドで判定している場合に、その値を渡すための項目です。商品側とバリエーション側を分けて送ります。省略すると既存値を維持します。

## 2026-09-11 — v107: SKU 対応表に商品マスターの SKU を添える

### 追加

* [`GET /api/ingest/sku-mappings`](/lmile-docs/fulfillment-api/external-fulfillment.md#get-apiingestsku-mappings) の各行に `sku`（その barcode の商品マスター上の SKU）を追加しました。倉庫など、商品マスターの SKU で商品を識別する相手に渡すときに使えます。商品マスターに無い barcode は `null` です。既存の項目は変わりません。

## 2026-09-10 — v106: ピッキング・出荷準備中・出荷済みの操作で、お届け状況メールをその段だけ止められるように

### 追加

* [`POST /api/routing/secure`](/lmile-docs/fulfillment-api/units.md#post-apiroutingsecure)・[`POST /api/routing/shipment/collect`](/lmile-docs/fulfillment-api/shipment-collect.md)・[`POST /api/routing/shipment/ship`](/lmile-docs/fulfillment-api/external-fulfillment.md#post-apiroutingshipmentship) に任意の `suppressCustomerMail` を追加しました。`true` で送ると、その操作に対応するお届け状況メール（在庫確保 / 出荷準備 / 発送完了）を送りません。
* 止まるのはその段だけです。以降の段は店舗の通知設定どおり送られます。
* 送る方向には指定できません。店舗の通知設定で送らない段は、指定が無くても送りません。
* 3 つのレスポンスに `customerMailSuppressed`（指定を受け付けたか）を追加しました。

## 2026-09-10 — v105: 予約納期を商品マスターで持てるように

### 追加

* [`POST /api/ingest/products`](/lmile-docs/ingestion-api/products.md) に `preorder_delivery_dates` を追加しました。配送先の国コード → お届け予定日（`YYYY-MM-DD`）の対応表で、`"*"` が全マーケットの既定です。設定した商品は、チェックアウトと購入者ページの到着予定日が在庫や出荷元の計算ではなくこの日付になります。省略すると既存値を維持し、`{}` で外します。
* 配達日時指定（`/api/routing/delivery-window`）と配送予定日プレビュー（`/api/routing/delivery-estimate-preview`）に任意の `countryCode`（配送先の国）を追加しました。予約納期のマーケット別の値を引くのに使います。省略時は `"*"` の値だけを見ます。

## 2026-09-09 — v104: WMS 出荷指示は倉庫の様式ではなく「注文の中身」を送る形に

### 変更

* [`POST /api/routing/wms-shipping-request`](/lmile-docs/routing-api/wms-shipping-request.md) が受け取るのは、**倉庫の様式に組み上げた本文ではなく `instruction`（注文の中身）** になりました。宛先・明細・金額・お届け希望を **Shopify から取れた値のまま**送ると、倉庫ごとの様式への変換（項目名・日時や電話の書式・姓名の並び・住所の分割・送料按分・税の逆算・手数料）はサーバー側で行います。
* 送る側で**整形しないでください**。`null` は `null` のまま、金額は文字列のまま、日時は ISO のまま、姓と名は分けたまま、住所は分割せずに送ります。整形を前倒しすると倉庫に渡る内容が変わります。
* 出荷指示か取り下げかは、ボディ直下の **`action`**（`SHIPPING_REQUEST` / `SHIPPING_CANCEL`）で指定します。取り下げの `instruction` は伝票番号だけです。
* 旧形式（組み上げ済みの本文を `payload` で渡す）は**受け付けません**。

### 記述の訂正

* 「同じ注文番号で送り直すと WMS 側で**上書き**される」は**誤り**でした。WMS は伝票番号ごとに 1 伝票を持ち、**2 回目以降を無視します**。**初回に送った内容がそのまま出荷される**ので、送る前に内容を確定させてください。あとから変えたい場合は取り下げてから別の伝票として作り直すか、倉庫へ直接連絡してください。

## 2026-09-02 — v103: 発送完了メールを送るかは店舗の通知設定で決まるように

### 変更

* [`POST /api/routing/shipment/ship`](/lmile-docs/fulfillment-api/external-fulfillment.md#post-apiroutingshipmentship) の `sendShippedMail` を**廃止**しました。発送完了メール（お届け状況の更新メール）を送るかは**店舗の通知設定**が決めます。送り続けても無視するだけなので、呼び出し側の修正は不要です。
* 提携倉庫から出る注文にお届け状況メールを送る設定の店舗では、その出荷について**販売チャネル側の発送通知を送りません**（`notifyCustomer: true` でも抑止します）。同じ出荷で 2 通届くのを避けるためです。
* この 2 つを 1 つの設定から決めるようにしたので、**「どちらの通知も送られない」状態は起きません**。以前は「通知を止める」が店舗の設定、「メールを送る」がリクエストの項目という別々の指定で、両方が off になると出荷の連絡が 1 通も届きませんでした。

## 2026-08-28 — v102: ピッキングリストと配送ラベルを 1 つの PDF で受け取れるように

### 追加

* [Picking List（バッチ）](/lmile-docs/fulfillment-api/picking-list.md) に `labelShipmentIds` を追加しました。指定した出荷の発行済み配送ラベルを **ピッキングリストの後ろに綴じた 1 つの PDF** を返します。1 注文の画面から「作業指示 + 送り状」をまとめて開いて印刷する用途を想定しています。
* 綴じた枚数は `labelsIncluded`、綴じられなかった出荷（ラベル未発行 / 破棄済み）は `labelsSkipped` で返します。ラベルが 1 枚も無くてもピッキングリスト単体として成功で返るので、**綴じられたかは `labelsIncluded` で判定してください**。
* バッチの `locale`（帳票の表示言語 `ja` / `en`）をドキュメントに明記しました（挙動の変更はありません）。

## 2026-08-17 — v101: 集荷（オンコールピックアップ）を API から依頼できるように

### 追加

* [Carrier Pickup](/lmile-docs/fulfillment-api/pickup.md)（`POST /api/routing/pickup` / `POST /api/routing/pickup/cancel`）を追加しました。配送ラベルを発行済みの出荷をまとめて、キャリアの集荷（オンコールピックアップ）を依頼できます。対応キャリアは **UPS** です。集荷は「この拠点に、この日、この時間帯に、この個口数を取りに来てもらう」**1 回の訪問**なので、**複数の出荷を 1 リクエストにまとめて**送ります（個口数と宛先国は出荷から自動で決まります）。依頼が成功すると集荷受付番号（PRN）が返り、取消に使えます。
* **一度依頼した出荷は、取り消すまで別の依頼に入れられません**（`409`）。同時に 2 か所から依頼しても受付番号は 1 つしか立たず、同じ荷物への二重手配になりません。
* 集荷先の住所・キャリア認証情報・既定の時間帯は、出荷元拠点ごとの設定（[Dispatch Config](/lmile-docs/configuration/dispatch-config.md) の `action: "pickup"`）から読みます。設定が無い拠点への依頼は、エラーではなく `requestable: false` と理由を返します。
* 集荷先住所は依頼のたびに `pickupAddress` で**上書きできます**（その 1 回の依頼にだけ効き、設定は書き換わりません）。上書きした住所も設定側と同じ検証を通ります。
* キャリアが集荷を受け付けたあとで記録に失敗した場合は、**受付番号をレスポンスに載せて** `500` を返します（出荷は依頼済みのまま残します）。受付番号が記録されていない依頼は既定では取り消せません（`409`）— キャリアに集荷が残っているのにこちらだけ未依頼に戻すと二重手配になるためです。

## 2026-08-17 — v100: 出荷元への入荷転送を登録できるように（移動中を追跡）

### 追加

* [Transfer Inbound](/lmile-docs/transfer-api/inbound.md)（`POST /api/routing/transfer/inbound`）を追加しました。在庫のある拠点と出荷する拠点が違い、**現物を出荷元へ運んでから出荷する**注文（刻印加工のための倉庫送り、海外発送のための国内 MFC 集約など）で、その移動区間を拠点間移動として登録できます。送るのは「すでに発送した便の追跡番号」で、**配送ラベルは発行しません**。登録した注文は移動が終わるまで移動中として扱われ、**荷物が出荷元に届いた時点で自動的に出荷準備中へ進みます**（受け取りの登録は不要。倉庫アプリのスキャン受領はこの移動には使えません）。同じ出荷に再送しても二重に登録されません。
* 返送ラベルを発行する [返送バルク](/lmile-docs/transfer-api/batches.md) とは別の種別です。

### 変更

* 拠点間移動の配送状況の確認間隔を **4 時間から 1 時間** に短縮しました。届いてから出荷準備中になるまでの待ち時間が縮まります。
* 配送状況を確認するたびに**現在の状況を記録**するようになりました（配達完了以外も）。「いまどこまで運ばれているか」を参照できます。発送直後はキャリア側にまだ反映されておらず状況が取れないことがありますが、これは異常ではありません。24 時間を超えても取れない場合や、いったん進んだあとに異常が出た場合だけ警告として記録します。
* 配送状況の語彙を拡張し、`pre_transit` / `returned` / `exception` / `not_found` / `other` を区別するようになりました（従来はこれらがすべて「取得できなかった」に丸められていました）。発送完了メールの送信条件は変わりません。

## 2026-08-16 — v99: 発送完了メールを配送業者の実集荷後に送信（有効化）、集荷までお届け状況は発送前表示

### 変更

* 発送完了メール（お届け状況）を、出荷確定の瞬間ではなく **配送業者が実際に集荷した後** に送るようにしました（v83 で追加した保留の仕組みを有効化）。集荷前に「発送完了」を案内してしまい、追跡番号を照会しても配送業者側にデータが無い、という状態を避けます。
* 集荷検知の照会間隔を **1 時間** に変更しました。集荷から最大 1 時間でメールが届きます。
* 購入者向けお届け状況ページも、集荷を検知するまでは **「発送準備中」表示** に揃えました（発送完了の到達時刻と追跡番号は集荷まで表示しません）。集荷を検知した時点で「発送完了」と追跡番号が表示されます。
* 対象は配送ラベルを Ship\&Co で発行し、配送業者が佐川急便 / ヤマト運輸の出荷です。それ以外（外部倉庫からの出荷、DHL など）の顧客通知は従来どおりです。Shopify の発送通知（`notifyCustomer`）も変更ありません。

## 2026-08-12 — v98: 出荷ステータス通知の宛先を取込元（sourceSystem）ごとに設定可能に

### 変更

* [Fulfillment Status Webhook](/lmile-docs/webhooks/fulfillment-status.md) の設定（`POST /api/routing/status-webhook-config`）に任意項目 `sourceSystem`（取込元）を追加しました（LM-1375）。取込元ごとに宛先を分けられます。`sourceSystem` 指定なしの設定はその shop の**既定宛先**で、既存の設定はそのまま既定宛先として動き続けます（後方互換・再登録不要）。イベントは自分の取込元と一致する設定があればそちらへ、なければ既定宛先へ届きます。レスポンスに `source_system`（既定宛先は `null`）が加わりました。

## 2026-08-10 — v97: 出荷準備中への一括集荷 API を追加、出荷報告に sendShippedMail を追加

### 追加

* [Shipment Collect](/lmile-docs/fulfillment-api/shipment-collect.md)（`POST /api/routing/shipment/collect`）を追加しました。出荷（shipment）配下の全単位をスキャン操作なしでまとめて集荷済みにし、出荷を出荷準備中へ進めます。`issueLabel: true` で配送ラベルの発行を同時に行えます（発行済みは再発行しない / MFC 集約グループはグループ全レグ集荷後に先頭の出荷へ 1 枚 / 発行失敗でも集荷は成立し `label.error` で返す）。MFC 自己在庫の単位は集荷と同時に保管棚の在庫を 1 つ減らします（減らせなかった数は `shelf.markedWithoutDecrement` で返す）。再送は冪等で、未集荷の単位だけを前進させます。

### 変更

* [`POST /api/routing/shipment/ship`](/lmile-docs/fulfillment-api/external-fulfillment.md#post-apiroutingshipmentship) に任意項目 `sendShippedMail`（既定 `true`）を追加しました。`false` で発送完了メール（お届け状況の更新メール）を送信しません（後から送られることもありません）。出荷ステータス通知の webhook と `notifyCustomer` は従来どおりです。

## 2026-08-10 — v96: 在庫移動に入庫希望日 (receivingDesiredDate) を追加

### 追加

* [Stock Transfer](/lmile-docs/stock-transfer-api/stock-transfer.md) の `create` / `create-request` に任意項目 `receivingDesiredDate`（入庫希望日・`YYYY-MM-DD`）を追加しました。入庫先で受け取りたい日付を移動に記録できます。形式が不正な場合は `invalid_payload` で拒否します。

## 2026-08-07 — v95: WMS 出荷指示の取り下げ (SHIPPING\_CANCEL) に対応

### 変更

* [WMS Shipping Request](/lmile-docs/routing-api/wms-shipping-request.md) の `payload.action` に `"SHIPPING_CANCEL"`（出荷指示の取り下げ）を追加しました（LM-1351）。キャンセルされた注文の出荷指示を WMS 側で取り消す用途で、`{"action": "SHIPPING_CANCEL", "order_no": "..."}` をそのまま転送します。`order_detail` の配列必須は `SHIPPING_REQUEST` のときのみです。

## 2026-08-05 — v94: WMS 出荷指示送信 API を追加

### 追加

* [WMS Shipping Request](/lmile-docs/routing-api/wms-shipping-request.md)（`POST /api/routing/wms-shipping-request`）を追加しました（LM-1321）。生成済みの出荷指示 JSON（`action: "SHIPPING_REQUEST"`）を記録した上で外部 WMS 連携へそのまま転送します（`payload` はキー順・値とも無変換のパススルー）。転送せず記録だけを行う `shadow` モードがあり、移行前の旧経路との突合検証に使えます。冪等キーは持たず、未出荷の間に内容が変わった際は最新内容での再送（WMS 側は注文番号単位の上書き受理）で反映します。転送は 1 発のみ（この API 自身はリトライしない）で、失敗は `error_kind`（`lambda_http_error` / `lambda_timeout` 等）で機械判別できます。

## 2026-07-28 — v93: 外部フルフィルメント連携 API を追加

### 追加

* 出荷を外部フルフィルメントサービス（例: Amazon マルチチャネルフルフィルメント）が実行する出荷元向けの [External Fulfillment API](/lmile-docs/fulfillment-api/external-fulfillment.md) を追加しました（LM-1262）。連携アプリが 1) `GET /api/routing/shipment/fulfill-job` で発注に必要な情報（配送先・明細・外部システム SKU）を取得し、2) 外部サービスへ発注して 3) `POST /api/routing/shipment/fulfill-result` で受理 / 失敗を書き戻し（受理は再送に冪等・以後の fulfill-job は `alreadyAccepted: true` で二重発注を skip 可能）、4) `GET /api/routing/shipment/fulfill-pending` の受理済み・未出荷一覧をポーリングして出荷完了時に `POST /api/routing/shipment/ship` で出荷済みを報告する流れです。外部システム SKU は **barcode との事前登録された明示マッピングのみ**で解決し（SKU 名からの自動マッピングなし）、未登録 barcode は `seller_sku_unmapped` で発注に進めません。対応表は `GET /api/ingest/sku-mappings` で読み取れます。
* 出荷完了報告 [`POST /api/routing/shipment/ship`](/lmile-docs/fulfillment-api/external-fulfillment.md#post-apiroutingshipmentship)（1 出荷を出荷済みにする。既 shipped は `noop` の冪等 no-op）をドキュメントに掲載し、任意入力 `trackingNumber` / `carrierCode` を追加しました。外部フルフィルメントのように**追跡番号が出荷完了時に初めて確定する**ケース向けで、指定時は出荷済みへの遷移と同一の書き込みで保存し、出荷ステータス通知にも載ります（未指定は従来どおりラベル発行時に保存済みの値を使用）。MFC 集約グループ（1箱=1ラベル）の出荷では追跡番号はグループ先頭の出荷が保有するため、指定すると `400` で拒否します。

## 2026-07-14 — v92: 引き当て順を「在庫数の多い拠点優先」へ変更

### 変更

* [Routing](/lmile-docs/routing-api/orders.md) の引き当て順位を変更しました。出荷元自身の在庫を最優先で使い切った後は、**販売可能在庫（available）の多い在庫ロケーションから**引き当てます（旧: メンバーの `priorityRank` 順）。在庫数が同じ場合は配送先と同じ地域の拠点 → `priorityRank` 昇順で決定します。`committed` は順位に影響せず、引き当て可否と配分数にのみ使われます。
* SKU 拠点オーバーライドの `force_first` は**常に最上位**で適用されるようになりました（従来はメンバー優先順位に劣後して実質効かないケースがありました）。`force_only` / `avoid` の除外は従来どおりです。
* 判定根拠の理由コードに `stock_ranking` / `source_self_stock` が加わりました（旧 `top_score` は過去の記録にのみ残ります）。拠点優先度（channel × region 設定）と各スコアは判定記録として保存されますが、順位の決定には使われません。引き当て済みの既存注文には影響しません（新規ルーティング・注文更新・再引き当てから適用）。

## 2026-07-13 — v91: 在庫変動通知に発売日時 (releasedAt) を追加

### 追加

* [Source Inventory Webhook](/lmile-docs/webhooks/source-inventory.md) の各イベントに `releasedAt`（商品の発売日時・ISO 8601、未設定は `null`）を追加しました。発売前に在庫を公開しない運用では、受け手側で `releasedAt` が未来のイベントの在庫を `0` として反映してください。発売日時を過ぎると通常の合算値が流れます。既定の payload テンプレートに含まれます（独自テンプレート利用時は `{{releasedAt}}` を追加してください）。

## 2026-07-13 — v90: 商品マスターに発売日時 (released\_at) を追加

### 追加

* [Products](/lmile-docs/ingestion-api/products.md) の `products[]` に `released_at`（発売日時・ISO 8601）を追加しました。**タイムゾーンオフセット付き**（例 `2026-07-15T10:00:00+09:00`）を推奨します（オフセット無しは UTC として解釈）。省略すると既存値を維持するため、`released_at` を送らない取込元（Shopify 同期等）が既に設定された発売日時を消すことはありません。

## 2026-07-09 — v89: 拠点間在庫移動 (Stock Transfer) API を追加

### 追加

* 拠点間で商品を **数量ベース**で移動する [Stock Transfer API](/lmile-docs/stock-transfer-api/stock-transfer.md) を追加しました（作成 →（承認）→ 出庫 → 入庫のライフサイクル）。ステータスは 3 軸（進捗 `progress` / 承認 `approval` / 修正依頼 `modificationRequest`）で管理し、Shopify InventoryTransfer 相当の派生フェーズ（`shopifyPhase`）も返します。作成は `create`（承認なし・すぐ出庫可）と `create-request`（承認が要る出庫依頼）の 2 系統です。承認（`approve`）は既定で承認と同時に出庫まで実行します（スマレジの「承認＝出庫」に準拠。`autoShip: false` で承認のみ）。**実数量（棚・販売可能在庫）が動くのは自社在庫（MFC 自己在庫）の拠点だけ**で、外部システム（Shopify / スマレジ）が在庫を管理する拠点は移動を記録するのみです（実在庫は外部が正）。出庫時は **移動可能量（棚合計 − 引き当て済み）を超える出庫を `insufficient_transferable_qty` で拒否**し売越を防ぎます。入庫検品中の [修正依頼](/lmile-docs/stock-transfer-api/modification-request.md)（起票 / 完了 / 取消）で受領更新をロック・再開できます。認証は `x-ingest-secret` または operator JWT。**既存の返送バルク（**[**Transfer API**](/lmile-docs/transfer-api/batches.md)**・注文 unit の返送）とは別機能**です。

## 2026-07-09 — v88: 在庫内訳ビューの拡張・block の分類協調・新規店舗の condition 初期化

### 追加

* `agent_read.inventory_balances` に**在庫の一望**用の列を追加しました: `is_overflow`（非デフォルト condition の合計が販売可能在庫を超過している＝要確認）/ `is_sellable_location`（その拠点が出荷元として販売可能か。**隔離ロケーションは false ＝売れない**）/ `location_available`・`location_on_hand`（拠点在庫の文脈）。「どこに・どのグレードが・売れる/売れない」を1ビューで確認できます。
* 新しく登録された店舗にも品質グレード（condition）マスタ（A/B/C/UNKNOWN）が**自動で初期化**されるようになりました（拠点作成時に seed）。

### 変更

* [在庫の block](https://github.com/falcon0119/inventory-os/tree/main/docs/operator/inventory-block.md) 実行時、隔離した数量ぶんだけ**源拠点の condition 内訳を自動で減算**し、内訳合計が販売可能在庫を超える不整合（overflow）を出さないようにしました。
* 棚卸し・分類・block の `quantity` に上限（1,000,000）を設けました（極端な値による内部エラーを防止）。

## 2026-07-09 — v87: 在庫の block / unblock（非販売品を隔離して販売可能在庫から外す）

### 追加

* 非販売品（C品・検品中・破損など）を**隔離ロケーションへ移動して販売可能在庫から外す** [`POST /api/operator/inventory/block`](https://github.com/falcon0119/inventory-os/tree/main/docs/operator/inventory-block.md)（と戻す `/unblock`）を追加しました。しくみは**拠点間移動（Stock Transfer）の再利用**：源拠点 → 隔離ロケーションへ移すことで源の販売可能在庫（available）が自動的に下がります（自己在庫の移動可能量ガードで売越を防止・在庫変動通知も発火）。**隔離ロケーションを出荷元（source member）にしなければ、そこの在庫は販売可能として扱われません**（＝売れない）。対象は自社在庫。`unblock` は逆に隔離在庫を元拠点へ戻し available を復帰します。

## 2026-07-09 — v86: 棚卸しの確定 (commit) で自社在庫を実棚数へ反映

### 追加

* 記録した棚卸しを承認確定する [`POST /api/operator/stocktake/commit`](https://github.com/falcon0119/inventory-os/tree/main/docs/ingestion/stocktake.md#post-apioperatorstocktakecommit--%E6%A3%9A%E5%8D%B8%E3%81%97%E3%81%AE%E7%A2%BA%E5%AE%9A%E8%87%AA%E5%B7%B1%E5%9C%A8%E5%BA%AB%E3%81%AE%E3%81%BF) を追加しました。**自社在庫（MFC 自己在庫）の在庫数を実棚数へ合わせ**、変化分を販売可能在庫として反映します（在庫変動通知で Shopify にも伝わります）。**外部システムが在庫を管理している拠点は対象外**（`skipped`）、**実棚数 < 引き当て済み数は `rejected`**（物理不足の発覚・棚も引き当ても動かさない＝売越を作らない）、確定済みの再確定は安全な no-op（`already_committed`）。認証は `x-ingest-secret` または operator JWT。棚卸しの記録（[Stocktake](https://github.com/falcon0119/inventory-os/tree/main/docs/ingestion/stocktake.md)）自体は従来どおり在庫を動かしません。

## 2026-07-09 — v85: 在庫の品質グレード (condition) 内訳 API を追加 (別軸・在庫合計は不変)

### 追加

* 既存の販売可能在庫（available）を**品質グレード（`condition_code`：A品/B品/C品）で色分け**する [`POST /api/ingest/inventory-classification`](https://github.com/falcon0119/inventory-os/tree/main/docs/ingestion/inventory-classification.md) を追加しました。「available 10 のうち B=2, C=1（残り 7 は A）」のように内訳を記録します。**在庫の合計は変えません**（数量増減ではなく分類）。しくみは *residual モデル*：非デフォルト condition（B/C/UNKNOWN）の数量だけを絶対値で保存し、デフォルト（`A`）は `available − Σ(非デフォルト)` の残差として自動計算します（外部の在庫更新で available が動いても分類は保持され A 数量だけ追従）。上限ガード「Σ(非デフォルト) ≤ available」を満たさない行は `rejected[]` で返します。**販売可能在庫・在庫スナップショットには影響せず**（[Source Inventory Webhook](/lmile-docs/webhooks/source-inventory.md) も非発火）、内訳の可視化用途です（read は `agent_read.inventory_balances`）。C品を実際に売れないようにする（販売可能数の減算）は将来対応です。

## 2026-07-08 — v84: 棚卸し (実棚数) の取込 API を追加 (既存在庫と別軸・在庫は不変)

### 追加

* 現場で数えた**実棚数**を取り込む [`POST /api/ingest/stocktake`](https://github.com/falcon0119/inventory-os/tree/main/docs/ingestion/stocktake.md) を追加しました。実棚数を商品（`barcode`）× 拠点 × **品質グレード（`condition_code`：A品/B品）** × \*\*業務状態（`inventory_status`）**の単位で記録し、システムが持つ現在庫との**差分（variance）\*\*を返します。「実棚数を送るだけで差分はシステムが算出」する形（Square Inventory API の PHYSICAL\_COUNT を参照）で、同一 SKU 内の品質グレードを在庫バケットとして持てます（NetSuite Inventory Status を参照）。`stocktake_key` で棚卸イベントに束ねて冪等に再送でき、同じ barcode × condition × status は新しい `occurred_at` が勝ちます。**このエンドポイントは販売可能在庫・在庫スナップショットを一切変更しません**（現在庫は差分算出のため読み取るだけ・[Source Inventory Webhook](/lmile-docs/webhooks/source-inventory.md) も発火しません）。在庫を実棚数へ合わせる反映は棚卸しとは別の操作です。

## 2026-07-07 — v83: 発送完了メールを佐川実集荷後に送信 (Ship\&Co tracking webhook・flag gated)

### 追加

* 発送完了メール（お届け状況）を、オペレーターが出荷確定した瞬間ではなく **佐川が実際に集荷した後**（Ship\&Co tracking の collected/transit/delivered 検知後）に送る仕組みを追加しました（LM-1183）。検知は Ship\&Co tracking webhook（`POST /api/webhooks/shipandco/tracking`・HMAC 署名検証）を主経路、30 分間隔のバックストップ poll を副経路とします。対象 shop の設定フラグ `delay_shipped_until_collected`（既定 off）で有効化し、**off の間は挙動不変**（従来どおり出荷時に即送信）です。複数箱の注文は全箱集荷後にメール 1 通、24h 未集荷は自動送信せずエラー候補として可視化します。Shopify の発送通知（notifyCustomer）は変更しません。

## 2026-07-07 — v82: 即時切替 (mode: switch) のガード強化と WMS/通知パリティ

### 変更

* [`POST /api/routing/change-source`](/lmile-docs/oversell-api/source-change.md) の `mode: "switch"` にレグ整合性ガード 2 つを追加しました: 同一レグに他の active 単位がある場合は `409 shipment_has_siblings`、MFC 集約グループ（1箱=1注文）に属するレグは `409 consolidation_group_member`（いずれも返送フローで扱ってください）。あわせて切替時に**新出荷元 WMS への `create` dispatch** と**切替先の確保待ち通知イベント（`store_secure_pending_assigned`）の発火**を追加し、返送フローの受領と同じパリティにしました。レスポンスに `createDispatches` が追加されます。

## 2026-07-07 — v81: 出荷元変更に即時切替モード (mode: switch) を追加

### 追加

* [`POST /api/routing/change-source`](/lmile-docs/oversell-api/source-change.md) に **`mode: "switch"`（即時切替）** を追加しました。返送フロー（ケース起票 → 返送 → 受領）を使わず、**同一の出荷レグ・単位のまま出荷元と引当ロケーションだけを新拠点へ更新**します（旧レグの取消・新レグの作成をしません）。単位が `secured` なら確保を解除し、旧拠点の棚紐付け解放・旧出荷元 WMS への cancel dispatch・新旧両拠点の自己在庫 available 再計算・割当保管棚の再分配まで一括で行います。対象は未ピックの `allocated` / `secured` 単位のみ。発行済み配送ラベルが載っている場合は `requiresLabelReissue: true` を返します（旧出荷元の契約のため再発行が必要）。既定（`mode` 省略 / `transfer`）の返送フローは従来どおりです。

## 2026-07-06 — v80: 非在庫サービス品 (同梱品) を現場照会と出荷済み反映に対応

### 追加

* [`GET /api/operator/shipments/by-tracking`](/lmile-docs/operator-api/lookup.md) のレスポンス `order` に `serviceLines[]`（`{barcode, sku, productName, variantName, quantity}`）を追加しました（LM-1172）。非在庫サービス品（`products.is_non_inventory = true`。ショッパーバッグ等の同梱品）は在庫引き当ての対象外で unit を持たないため（LM-527）、これまで現場アプリからは見えませんでした。梱包時に同梱すべき品を追跡番号スキャン時点で明示し、同梱漏れを防ぎます。適用中の routing decision（`selected_reason = 'non_inventory_service'`）から注文単位で集計します。同梱品が無い注文は空配列で、既存クライアントへの影響はありません。

### 変更

* [Fulfillment Status Webhook](/lmile-docs/webhooks/fulfillment-status.md) の `shipped` 遷移の `lines` に、注文の非在庫サービス品の barcode / 数量を合流するようにしました（LM-1173）。routing に送られた明細は出荷済み反映の対象、という契約の明確化です。これまで unit を持たない同梱品の明細が `lines` に載らず、受け手（Shopify 連携等）で注文が「一部発送済み」のまま残っていました。受け手が明細を残数ベースで冪等に反映していれば、分割出荷でも最初の出荷 1 回だけに反映されます。`shipped` 以外の遷移は従来どおりです。

## 2026-07-06 — v79: 出荷追跡照会の集約フィールド公開 + 返送バルクの配送完了自動受領

### 追加

* [`GET /api/operator/shipments/by-tracking`](/lmile-docs/operator-api/lookup.md) のレスポンスフィールドをドキュメントに追記しました: `consolidationShelfCode`（集約棚）/ `consolidationLabelPlacedAt`（「③ ラベルを置く」の配置完了時刻・LM-1157）/ `consolidationGroupId`（同一 MFC 複数店舗分割の集約グループ id・LM-1144。head ヒット時の `units[]` は箱全体の union）/ `labelVoidedAt`・`labelVoidReason`（ラベル void 情報）/ `order.orderName`（表示用注文番号）。あわせて `units[].shelfCode` の説明を unit 単位の永続割当（引当時の FIFO 分配・LM-1101）に基づく現行仕様へ更新しました。

### 変更

* [倉庫間移動バルク](/lmile-docs/transfer-api/batches.md): `dispatched` のバルクは返送ラベルの配送完了（キャリアの delivered）検知で**ステータスのみ** `received` に自動遷移するようになりました（LM-1159）。サーバーが約 1 時間ごとに配送状況をポーリングし、`received_at` と所属単位の受領時刻を記録します（中止済み単位には付与しません）。[受領照合](/lmile-docs/transfer-api/receive.md)が行う単位の再フルフィルメント等の副作用は伴いません。

## 2026-07-03 — v78: 在庫 ingest の as-of 逆行ガード（幽霊在庫防止）

### 追加

* [`/api/ingest/inventory-snapshot` / `/api/ingest/inventory-available`](/lmile-docs/ingestion-api/inventory-levels.md) の `lines[]` に任意の `as_of`（読み値のソース時刻・ISO 8601）を追加しました（LM-1154）。既存行の `inventory_as_of` より古い行は適用せず、レスポンスの `stale_skipped[]`（`{ barcode, as_of, current_as_of }`）と `lines_stale_skipped` で明示します。バッチ同期の古い読み値がリアルタイム更新（webhook 等）済みの値を後勝ちで上書きする事故（幽霊在庫 → 二重引当・売越）を防ぎます。`as_of` 省略時は従来どおり `inventory_as_of`（→ 現在時刻）で、既存の送信側は挙動不変です。

## 2026-07-03 — v77: 出荷元変更ケースの shipmentId 解決

### 追加

* [`GET /api/operator/source-changes`](/lmile-docs/operator-api/queues.md) に `shipmentId` パラメータを追加しました（LM-1152）。統合QR（`barcode|shipmentId`）の shipment uuid から注文を解決してその注文のケースに絞ります。出荷元変更で unit が relink された後の旧 shipment（cancelled）でも解決できるため、同一 barcode の返送予定が複数あってもスキャンしたラベルの注文を一意に特定できます（iOS 集荷チェックの別注文誤記録 LM-1146 の恒久対策）。指定時はレスポンスに `resolvedRoutingOrderId` を echo します（クライアントはこれが返った場合のみ解決を信頼）。レスポンスに `collectedCheckedAt`（集荷チェック記録日時）も追加。

## 2026-07-02 — v76: 店舗→EC送客（Share Analytics）取り込み

### 追加

* 店舗スタッフの商品共有（LINE / メール / QR）とその追跡イベント（開封・カート追加・購入等）を投入する [`/api/ingest/share-analytics`](/lmile-docs/ingestion-api/share-analytics.md) を追加しました（LM-1148）。送信元は `source`（slug）で識別する汎用エンドポイントで、`sot.lm_share_analytics_shares` / `_items` / `_events` に冪等 upsert します（`UNIQUE (source, source_*_id)`）。
  * **PII 遮断**: raw の共有トークン・スタッフメール・LINE ユーザー id・顧客 id は保存せず、受信時に HMAC-SHA-256 の hash 列へ変換します。イベント `payload` / 共有 `metadata` も PII キーを strip した残りのみ保存します。
  * 行単位の不備（必須欠落・許可外 `event_type`・不正/未来 `occurred_at`）は `skipped[]`（reason 付き）で返し silent skip しません。テーブル単位の upsert 失敗は HTTP `207` で部分失敗を明示します。
  * shares / items / events 間に FK を張らないため、分割送信でイベントが先に届いても失敗しません。

## 2026-06-26 — v75: 配達希望日・時間帯の更新エンドポイント

### 追加

* 出荷作業の注文に**配達希望日・時間帯を後から設定／変更**する [`/api/routing/shipment/delivery`](/lmile-docs/fulfillment-api/shipment-delivery.md) を追加しました（LM-1096）。注文ヘッダ（`sot.lm_routing_orders`）の `desired_delivery_date` / `desired_delivery_time` の 2 列だけを部分更新します（**再ルーティング・再 dispatch なし**。それが必要な場合は従来どおり [`/api/routing/update`](/lmile-docs/routing-api/cancel-update.md)）。
  * 値は[ラベル生成時](/lmile-docs/fulfillment-api/fulfillment.md)に Ship\&Co `setup.date` / `setup.time` へ載って佐川送り状へ印字されます（LM-1043 の取込列を再利用）。既発行の送り状へ反映するには [`retry-label`](/lmile-docs/fulfillment-api/address-recovery.md)（`force`）で再発行します。
  * `null` で指定解除。キャンセル済み注文は `409 order_cancelled`、別 shop の注文は `404 routing_order_not_found`。
  * これまではカート側（Shopify メタフィールド `custom.pickup_date` / `pickup_time` → [Routing](/lmile-docs/routing-api/orders.md)）の自動取込のみでしたが、Last Mile の出荷詳細ページからオペレーターが手で設定できるようになりました。

## 2026-06-24 — v74: 出荷元メンバー変更時に合算在庫 webhook を再発火

### 修正

* 出荷元↔在庫ロケーションの[マッピング変更](/lmile-docs/configuration/source-members.md)（`/api/routing/source-members` の設定・解除）時に、**影響を受けた出荷元の合算販売可能在庫を再計算して** [**Source Inventory webhook**](/lmile-docs/webhooks/source-inventory.md) **を発火**するようにしました（LM-1079）。これまでは在庫取込時しか発火しなかったため、出荷元からメンバーを外しても外す前の合算値が外部在庫ミラー（Shopify available 等）に固着し、在庫過大→オーバーセルになる不具合がありました。
  * メンバー追加・別出荷元への付け替え（新・旧の両出荷元）・解除のいずれにも対応し、**最後のメンバーを外した場合も合算を `0` に補正**します。
  * set / detach のレスポンスに起票した在庫変動イベント数 `enqueued` を追加しました。
  * 内部的に出荷元を直接受ける再計算 RPC `public.lm_fs_inventory_recompute_source` を追加（既存の在庫取込起点の検知経路は変更しません）。

## 2026-06-24 — v73: 確保前キャンセルの通知（Routing Cancel Webhook）

### 追加

* 注文が**確保（secure）前にキャンセル**されたとき、確保前の出荷元（shipment）ごとに通知する **Routing Cancel Webhook** を追加しました（LM-1074）。確保前に外部システムへ反映済みだった引き当て（例: 店舗 POS の理論在庫の先行減算）を取り消す用途です。
  * [`/api/routing/cancel`](/lmile-docs/routing-api/cancel-update.md) のキャンセル確定直後、**確保前**（`secured_at IS NULL`）かつ未出荷の shipment ごとに `event: "routing_order_cancelled"` を 1 通バックグラウンド送信します。確保後（物理確保済み）・出荷済みの shipment は通知しません（= 自動で取り消さない）。
  * 送信先は専用設定を持たず、[Routing Allocation Webhook](/lmile-docs/webhooks/allocation.md) の設定（`shop` 単位・同一宛先 / secret）を**再利用**します。受信側は `event` フィールドで引き当て通知と判別します。
  * ペイロードは `shipmentId`（受信側の冪等キー）中心で**明細を含みません**。耐久性のため outbox（`sot.lm_routing_cancel_events`）へ起票し、`pending` / `failed` は自動 drain で再送します。
  * 詳細は [Routing Cancel Webhook](/lmile-docs/webhooks/order-cancelled.md) を参照。

## 2026-06-24 — v72: バッチピッキングリスト（複数注文を 1 枚に統合）

### 追加

* **複数の注文をまとめて 1 つのピッキングリストに統合する** API を追加しました（LM-1053）。出荷作業一覧（inventory-agent `/mypage/routing/shipments`）で複数行を選択 → スキャン可能な作業指示書（CODE128 バーコード付き PDF）と共有用 CSV を発行する用途です。LM-505 のとおりピッキングリスト出力は inventory-os に集約します。
  * `POST /api/routing/picking-list/batch`（`x-ingest-secret`）— `routingOrderIds[]`（1〜500 件）を受け、選択注文の applied decision を**在庫拠点単位に統合**して `format=pdf`（統合 PDF 1 枚）/ `csv`（共有用 CSV）/ `json` を生成し、PDF・CSV は Storage 保存して**公開 URL** を返します。各明細に**注文番号**と\*\*商品バーコード（CODE128）\*\*を付け、刻印違いは別行で運びます。
  * `missing`（不在 id）/ `unrouted`（未ルーティング注文）/ `unpickable[]`（引き当て不能）は silent skip せず応答・PDF に含めます。複数注文にまたがるため `sot.lm_picking_lists` への追記は行いません（単一注文版 `/api/routing/picking-list` のみ追記）。
  * 詳細は [Picking List](/lmile-docs/fulfillment-api/picking-list.md) を参照。

## 2026-06-21 — v71: 刻印注文は店舗で佐川顧客ラベルを生成しない

### 変更

* 刻印注文（`external_order_ref` に `-engraved` サフィックス）が **`secured` へ遷移しても、店舗では佐川の顧客ラベルを生成しない**ようにしました（LM-960）。刻印品は change-source で流山倉庫へ転送し、顧客出荷は流山レグから行うため、店舗での顧客ラベル生成は不要で、生成失敗（住所不備等）が[住所不備キュー](/lmile-docs/fulfillment-api/address-recovery.md)に紛れ込む・無駄なキャリア呼び出しが発生するのを防ぎます。`secured` 遷移自体は従来どおり確定し、`labelStatus` は `skipped`（`last_label_error` は記録しません）。確保フロー（`/api/routing/secure`・`/api/operator/secure-scan` 等）と出荷ステータス報告（`/api/routing/fulfillment`）の**両経路**に適用します。

## 2026-06-21 — v69: 出荷メモ（shipment memo）追記 API

### 追加

* 出荷作業の各 shipment（注文 × 出荷元）にオペレーターが時系列でメモを残せる**追記 API** を追加しました（LM-1002）。出荷詳細ページ（inventory-agent `/mypage/routing/shipments/:shipmentId`）のタイムライン（システムイベント + 手書きメモ）に新しい順で表示します。
  * `POST /api/routing/shipment/memo`（`x-ingest-secret` または operator JWT）— 指定 shipment にメモを 1 件追記します（`body` 1〜2000 文字）。operator JWT 経由は投稿者（検証済スタッフ ID）を記録します。**追記のみ**（編集・削除なし = 完全な記録 / 監査ログ）で、呼ぶたびに新しい行を append します。
  * 別 shop の `shipmentId` には付けられません（`404 shipment_not_found`）。一覧取得 API はなく、`body` / 投稿者は PII 相当のため merchant 管理 UI が `service_role` で直読します（`agent_read` / LLM agent 非露出）。新テーブル `sot.lm_shipment_memos`（`service_role` 専用・`agent_readonly` grant なし）。

## 2026-06-16 — v70: 出荷元変更（change-source）を中止（cancelled）後に再起票可能に

### 変更

* [**Source Change**](/lmile-docs/oversell-api/source-change.md) の起票（`POST /api/routing/change-source`）が、対象 unit に**中止（`cancelled`）済みの変更が残っている場合でも再起票（再オープン）できる**ようになりました（LM-956）。`lm_fulfillment_source_changes` は `UNIQUE(shop, fulfillment_unit_id)` で 1 単位 1 行・`cancelled` は終端のため、従来は一度中止すると同じ単位を二度と転送に乗せられませんでした（前進経路では `409`）。今後は `secured` の単位であれば、残った `cancelled` 行を `change_requested` に**同一行で再オープン**します（新 decision / 新ヘッダ / 旧ヘッダ cancel / 返送便ラベル生成を起票と同一に再実行）。レスポンスに `reopened`（前回 `cancelled` を再オープンしたか）を追加しました。`cancelled` 以外の進行中（`change_requested` / `return_in_transit` / `return_received`）は従来どおり前進/中止のままで挙動不変です。

## 2026-06-15 — v68: 外部アプリによる配送ラベル生成（汎用 read / write-back）

### 追加

* 配送ラベルを inventory-os の組み込みアダプタ（Ship\&Co 等）ではなく**外部の mini-app（lm-apps）が生成**するための、キャリア非依存の汎用 read / write-back を追加しました（LM-916）。越境注文の Global-e（DHL Express）など、住所正規化や ZPL→PDF 変換といった顧客固有・キャリア固有の処理を inventory-os に持ち込まず外部アプリ側に分離するための土台です。
  * `GET /api/routing/shipment/label-job`（`x-ingest-secret`）— secured 遷移の `fulfillment_shipment_status_changed` イベントを受けた app が、ラベル生成に必要な注文情報（`orderName` / `externalOrderRef` / 明細 `sku × quantity` / 出荷元 location）を取得します。宛先 PII は含めません。
  * `POST /api/routing/shipment/label-result`（`x-ingest-secret` または operator JWT）— app が生成した追跡番号とラベル PDF（base64）を書き戻します。PDF は Storage `shipping-labels` に保存し、`tracking_number` / `carrier_code` / `label_pdf_path` を shipment 行へ記録します（`status=generated`）。失敗は `last_label_error` のみ記録（`status=failed`）。shipment の状態は変更しません（`secured` は確保時に確定済み）。
* ラベル config（`action='label'`）を登録しない出荷元では従来どおり inventory-os 側のラベル生成は `skipped` となり（確保自体は確定）、この read / write-back で外部アプリが補完します。print-job / print-result（物理印刷, LM-711）と同じ app-facing プラミングのため、公開エンドポイント一覧（overview / authentication）には掲載しません。

## 2026-06-14 — v66: 出荷元変更（change-source）を `secured` のみに一本化

### 変更

* [**Source Change**](/lmile-docs/oversell-api/source-change.md) の起票（`POST /api/routing/change-source`）が、対象 unit が **`secured` のときのみ**起票できるようになりました（LM-913。従来は `allocated` も可）。物理オペは「店舗で確保（`secured`）→ 業者が MFC へ集荷 → MFC で流山転送を起票」の順で、流山転送の指定は店舗確保より後でなければなりません。確保前（`allocated`）での起票を許すと[確保報告](/lmile-docs/operator-api/secure-scan.md)に転送品が現れてしまうため弾きます。`allocated` での起票は `409 unit_not_changeable`（`unit must be 'secured' to change source — secure it first`）。前進（`return_in_transit` / `return_received`）・中止の挙動は不変です。

## 2026-06-12 — v67: routing 注文に参照 URL（referenceUrl）

### 変更

* [**Routing**](/lmile-docs/routing-api/orders.md) の `POST /api/routing/orders` に **`referenceUrl`**（任意）を追加しました（LM-910）。カート側の注文参照 URL（例 Shopify admin の注文ページ）を受け取り、管理 UI が注文番号からカート管理画面へ遷移できるようにします。`http(s)` の URL のみ受け付け、省略時は従来どおり（純 additive）。あわせて `orderName`（LM-888 で受理済の表示用注文番号）をボディパラメータ表に追記しました。

## 2026-06-12 — v66: 住所修正からラベル自動再発行・自動再印刷（autoRetryLabel）

### 変更

* [**Address Recovery**](/lmile-docs/fulfillment-api/address-recovery.md) の `POST /api/routing/shipment/address` に **`autoRetryLabel`** オプション（default `false` = 既存呼び出し元は挙動不変）を追加しました（LM-838 / LM-904）。`true` のとき住所更新成功後に、ラベルエラー中の出荷元（住所不備復旧）と、ラベル面に影響する項目が**実際に変わった**発行済み出荷元（`secured` / `oversell_secured`・ラベル未破棄）をまとめて自動再発行し、結果を `retryResults` で返します。発行済み出荷元の再発行は**新しい追跡番号**になります（旧ラベルは現場で破棄）。
* `POST /api/routing/shipment/retry-label`（および `autoRetryLabel`）の**再発行成功時に、印刷イベント（`fulfillment_shipment_status_changed`）を印刷アプリへ自動配信**するようになりました（LM-836）。住所修正 → 再発行 → 物理印刷が 1 操作で完結します（従来は [Print Label](/lmile-docs/fulfillment-api/print-label.md) の手動呼び出しが必要でした。同 API は紙詰まり等の手動再印刷専用に）。
* 再発行成功時に `label_printed_at` / `last_print_error` をリセットするようになりました（LM-837）。新ラベルは未印刷のため、印刷済み出荷元の `force` 再発行でも自動印刷が二重印刷ガード（`alreadyPrinted`）に塞がれません。

## 2026-06-12 — v65: 出荷元変更（change-source）の secured 対応

### 変更

* [**Source Change**](/lmile-docs/oversell-api/source-change.md) の [`POST /api/routing/change-source`](/lmile-docs/oversell-api/source-change.md) が **`secured`（確保済 = ピック済み）の unit でも起票**できるようになりました（LM-872。従来は `allocated` のみで `409 unit_not_changeable`）。物理返送は出荷元でピック済みの品を送るのが前提のため、`secured` を弾く従来仕様は物理オペと矛盾していました。`secured` からの起票では、確保を解除（unit の `secured` / `secured_at` をクリア。宛先 B での受領 = `allocated` 復帰後に B で再確保）し、unit が抜けて旧出荷元 A のヘッダにアクティブ unit が残らない場合のみ、A の顧客出荷ヘッダを `cancelled` に遷移・発行済み配送ラベルを運用破棄マーク（`label_voided_at`。tracking / label 列は監査用に温存）・[棚紐付け](/lmile-docs/shelf-api/link.md)を新しい `released_reason="source_changed"` で解放します。レスポンスに解放数 **`releasedShelfLinks`** を追加（純 additive）。`allocated` からの起票・前進/中止の挙動は不変です。

## 2026-06-12 — v64: 出荷完了（shipped）にも transfer\_required ガード

### 変更

* [**Fulfillment**](/lmile-docs/fulfillment-api/fulfillment.md) の `POST /api/routing/fulfillment` が、`shipped` 報告のヘッダに出荷可能な unit が無く、注文配下に[倉庫間移動](/lmile-docs/transfer-api/batches.md)（出荷元変更）フロー中（`source_change_pending` / `source_change_in_transit`）の unit がある場合に **`409 transfer_required`** で明示拒否するようになりました（LM-874）。出荷元変更（刻印の倉庫返送等）後に現場へ残った旧ヘッダの顧客向け配送ラベルをスキャンして出荷完了できてしまう穴を塞ぎます。出荷可能な unit が残る混在ヘッダは従来どおり出荷できます（移動中 unit はヘッダ一括更新の対象外のまま）。

## 2026-06-12 — v63: Transfer API（倉庫間移動バルク）+ 通常出荷の transfer\_required ガード

### 追加

* [**Transfer API**](/lmile-docs/transfer-api/batches.md) を新設しました（LM-853）。[出荷元変更](/lmile-docs/oversell-api/source-change.md)で旧倉庫に残った現品を**複数まとめて（バルク）宛先倉庫へ送る**運用の backend です。[バルク作成・一覧・ユニットQR スキャンでの単位追加/取消](/lmile-docs/transfer-api/batches.md)（`/api/operator/transfer/batches` + `add-unit` / `remove-unit`）、[発送確定](/lmile-docs/transfer-api/dispatch.md)（`dispatch`：内容物リスト PDF の生成・保存 + 所属単位の一括 `return_in_transit` + 旧拠点の自己在庫棚 −1）、[宛先側の入荷照合](/lmile-docs/transfer-api/receive.md)（`receive`：1 点ずつスキャン受領 = `return_received`・全受領でバルク `received`）の 6 エンドポイント（operator JWT 認証）。単位の状態機械は既存の出荷元変更をそのまま使い、dispatch / receive の遷移は `POST /api/routing/change-source` と同一実装を共用します。バルク所属の単位は返送ラベルの夜間バッチ生成から除外されます（二重手配防止）。
* [**Operator Queues**](/lmile-docs/operator-api/queues.md) の `GET /api/operator/source-changes` に **`batchId`** フィルタ（バルクの内容物一覧）とレスポンスの **`batchId`** を追加しました。
* [**Operator Lookup**](/lmile-docs/operator-api/lookup.md) の `GET /api/operator/shipments/by-tracking` の各 unit に **`sourceChange`**（移動フロー中の status / 行き先 / バルク所属 / 返送追跡番号。フロー外は `null`）を追加しました（LM-860）。

### 変更

* 通常出荷の write API（[在庫確保](/lmile-docs/fulfillment-api/units.md) `/api/routing/secure`・[確保スキャン](/lmile-docs/operator-api/secure-scan.md)・[追跡番号で確保](/lmile-docs/operator-api/secure-by-tracking.md)・[棚ピック](/lmile-docs/shelf-api/lookup.md) `/api/operator/shelf/pick`）が、倉庫間移動（`source_change_pending` / `source_change_in_transit`）中の unit への操作を **`409 transfer_required`** で明示拒否するようになりました（LM-860。従来は黙ってスキップ / 汎用エラー）。`/api/routing/secure` は確保可能な unit と混在する場合のみ従来どおり確保し、`transferRequiredUnits[]` で表面化します。[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) のヘッダ一括 unit 更新も移動中 unit を巻き込まなくなりました。

## 2026-06-12 — v62: 確保（secured）遷移でも Fulfillment Status Webhook を発火

### 変更

* [**Fulfillment Status Webhook**](/lmile-docs/webhooks/fulfillment-status.md) が、確保フロー（[在庫確保](/lmile-docs/fulfillment-api/units.md) `/api/routing/secure`・[確保スキャン](/lmile-docs/operator-api/secure-scan.md) `/api/operator/secure-scan`・[追跡番号で確保](/lmile-docs/operator-api/secure-by-tracking.md) `/api/operator/secure-by-tracking`）でヘッダが `secured` に遷移したときも発火するようになりました（LM-851）。従来は [`/api/routing/fulfillment`](/lmile-docs/fulfillment-api/fulfillment.md) 経由の遷移しか起票されず、確保フローの `secured` は外部から見えませんでした。ペイロード形・outbox（再送回収）・配信機構は既存（LM-521）と同一で、`status: "secured"` のイベントが増えるだけです。特定ステータスだけを処理する既存の受け手には後方互換です。

## 2026-06-12 — v61: 出荷元変更（拠点間移動）の一覧 API + change-source の operator JWT 対応

### 追加

* [**Operator Queues**](/lmile-docs/operator-api/queues.md) に [`GET /api/operator/source-changes`](/lmile-docs/operator-api/queues.md) を追加しました（LM-849）。[出荷元変更](/lmile-docs/oversell-api/source-change.md)（`/api/routing/change-source`）で起票された「移動すべきもの」の read 専用一覧で、送り側（旧出荷元 MFC）は `fromSourceLocationId` で梱包キューを、受け側（流山等の新出荷元）は `toSourceLocationId` で入荷待ちキューを取得します。`status`（CSV 複数可）・返送便の `trackingNumber`（入荷照合）でも絞り込めます。商品・拠点表示名・注文・unit 現在 status を enrich し、返送ラベルは `hasReturnLabel` / `returnLabelGeneratedAt` のみ（PDF パス・エラー本文は非公開）。

### 変更

* [**Source Change**](/lmile-docs/oversell-api/source-change.md) の [`POST /api/routing/change-source`](/lmile-docs/oversell-api/source-change.md) が **operator JWT（`Authorization: Bearer`）でも**呼べるようになりました（LM-850・[Routing write の 2 系統認証](https://lmile.gitbook.io/lmile-docs/resources/pages/7cB70I8yeRnMpvcdLkNu#routing-write-の-2-系統認証) に追加 = 11 エンドポイント目）。系統はヘッダの有無で明示判別し、既存の機械間クライアント（`x-ingest-secret`）の挙動は不変です。operator 経由は操作スタッフを記録します（起票 = `opened_by_staff_user_id` / 前進・中止 = `updated_by_staff_user_id`）。

## 2026-06-12 — v60: 住所不備キュー（labelErrorOnly）+ 住所修正の dry-run（validateOnly）

### 変更

* [**Operator Queues**](/lmile-docs/operator-api/queues.md) の [`GET /api/operator/shipments`](/lmile-docs/operator-api/queues.md) に **`labelErrorOnly`**（`true`/`1`・任意）フィルタと各 shipment の **`hasLabelError`**（`boolean`・純 additive）を追加しました（LM-840）。ラベル発行エラー中（住所不備等で `last_label_error` が非 null）の shipment だけに絞る「住所不備キュー」として使えます。エラー本文はキャリア応答に住所断片が混ざりうるため一覧には出さず、真偽値のみ返します。住所を修正（[Address Recovery](/lmile-docs/fulfillment-api/address-recovery.md)）→ 再発行が成功（`labelStatus: "generated"`）するとエラーがクリアされ、このフィルタから外れます（= 解消の判定）。絞り込みは一覧・サマリの双方に効きます。
* [**Address Recovery**](/lmile-docs/fulfillment-api/address-recovery.md) の [`POST /api/routing/shipment/address`](/lmile-docs/fulfillment-api/address-recovery.md) に **`validateOnly`**（`boolean`・任意）を追加しました。`true` のときマージ + 国内必須項目の検証だけを実行し、保存・変更履歴・webhook は行わない dry-run です（UI の保存前バリデーション用。検証失敗は通常時と同じ `422 validation_failed` + `missing[]`）。既存のリクエスト / レスポンス契約は不変です。

## 2026-06-12 — v59: 棚紐付けの付け替え（relink）+ 追跡番号照会に棚紐付けを追加

### 変更

* [**Shelf Link**](/lmile-docs/shelf-api/link.md) の [`POST /api/shelf/link`](/lmile-docs/shelf-api/link.md) に **`relink`**（`boolean`・任意）を追加しました。`true` のとき、shipment が既に別棚へ紐付け済みなら既存のアクティブ紐付けを `manual_release` で解除してから新しい棚へ付け替えます（`200` + `relinked: true` + `previousShelfCode`。解除行は履歴として残ります）。省略時は従来どおり `409 shipment_already_linked` でブロックします（自動付け替えはしません）。picking-ios の棚紐付け画面で「既に棚 X に紐付いています → 別の棚に紐付け直す」フローに使います。
* [**Operator Lookup**](/lmile-docs/operator-api/lookup.md) の [`GET /api/operator/shipments/by-tracking`](/lmile-docs/operator-api/lookup.md) の各 shipment に **`shelfLink`**（アクティブな棚紐付け。`shelfCode` / `locationId` / `linkedAt`、未紐付けは `null`・純 additive）を追加しました。`units[].shelfCode`（引き当て在庫棚）とは別物で、こちらは shipment の置き場所棚（`sot.lm_shelf_links`）です。追跡番号スキャン時点で「既に棚 X に紐付け済み」を案内し付け替えフローへ誘導するために使います。既存フィールド・リクエスト契約は不変です。

## 2026-06-10 — v58: 追跡番号照会の unit にギフトラッピング要否（giftWrap）を追加

### 変更

* [**Operator Lookup**](/lmile-docs/operator-api/lookup.md) の [`GET /api/operator/shipments/by-tracking`](/lmile-docs/operator-api/lookup.md) の各 unit に **`giftWrap`**（`boolean`）を追加しました（LM-827・純 additive）。ギフトラッピング要否を、line item property **`isGiftWrapping = "true"`**（`sot.lm_fulfillment_units.line_properties` に保持）または SKU に `GIFT` を含むかから導出して返します。出荷時のギフトラッピング確認（picking-ios）に使います。`line_properties` の生値は PII のためレスポンスに出さず、導出した真偽値のみを返します。既存フィールド・リクエスト契約は不変です。

## 2026-06-10 — v57: 出荷作業キュー一覧に出荷元（メンバー在庫集合）フィルタを追加

### 変更

* [**Operator Queues**](/lmile-docs/operator-api/queues.md) の [`GET /api/operator/shipments`](/lmile-docs/operator-api/queues.md) に、選択中の出荷元（MFC/倉庫）で絞り込む **`fulfillmentSourceLocationId`**（uuid・任意）を追加しました（LM-815・純 additive）。指定すると、その出荷元の**有効なメンバー在庫ロケーション集合**（`sot.lm_fulfillment_source_members` の `is_active=true` な `inventory_location_id`）で `from_location_id` を `IN` 絞り込みします。出荷元自身もメンバー行（self）として登録されているため集合に含まれ、出荷元自身の自己在庫 shipment も拾います。この絞り込みは一覧・サマリ（`totalCount` / `byStatus` / `unlabeled`）の双方に効きます。
* 単一ロケーション完全一致の `fromLocationId` とは用途が排他で、**両方指定すると `400`** です。メンバーが 0 件の出荷元は shop 全体に逃げず\*\*空（該当 0 件）\*\*を返します（フォールバックしません・[Locations](/lmile-docs/operator-api/locations.md) の `memberOnly`／LM-741 と同じ思想）。既存の公開リクエスト / レスポンス契約は不変です。

## 2026-06-10 — v56: 追跡番号で確保（Secure by Tracking）+ 追跡番号照会に棚番号を追加

### 追加

* [**Secure by Tracking**](/lmile-docs/operator-api/secure-by-tracking.md)（[`POST /api/operator/secure-by-tracking`](/lmile-docs/operator-api/secure-by-tracking.md)）を追加しました（LM-778）。先行印刷された配送ラベルの**追跡番号**をスキャンして、その shipment（出荷元単位の梱包）配下の `status=allocated` ユニットを**一括確保**する operator 向け API です。案 A（MFC 配送ラベル先行印刷）の「ピック（棚スキャン）→ ラベル貼付 → 確保」動線の「確保」ステップを担います。ユニットQR で 1 件ずつ確保する [Secure Scan](/lmile-docs/operator-api/secure-scan.md) と違い、追跡番号を解決キーにして shipment 配下の確保可能ユニットをまとめて確保し、案 A では確保時点でユニットが既に picked のことがあるため **picked 済も含めて確保**します。確保で shipment 配下の全ユニットが確保済になるとヘッダを `secured` に遷移させますが、先行生成済みラベルは**再生成しません**。レスポンスには各 shipment の確保数（`secured` / `alreadySecured`）・棚番号（`shelves[]`）・ヘッダ結果を含みます。
* 認証は operator JWT（`Authorization: Bearer`）または `x-ingest-secret`（dual auth）で、operator 経由の確保は `secured_by_staff_user_id` に操作者を記録します。冪等で、確保可能ユニットが無く既確保が居れば `200` + `secured: 0`、確保可能でも既確保でもないユニットしか無い shipment は `409 unit_not_securable`、追跡番号に該当 shipment が無ければ `404 shipment_not_found` で表面化します（fallback しません）。

### 変更

* [**Operator Lookup**](/lmile-docs/operator-api/lookup.md) の [`GET /api/operator/shipments/by-tracking`](/lmile-docs/operator-api/lookup.md) の各 unit に **`shelfCode`** を追加しました（LM-774・純 additive）。ユニットの引き当て先（`allocated_location_id`）× `barcode` から、棚運用と同一規則（同一 `(location, barcode)` で `qty>0` 優先・同点は `shelf_code` 昇順の 1 棚）で棚番号を解決して返します。確保前の「追跡番号 → 棚表示」に使えます。棚を持たない店舗 / 同期拠点のユニットは `null` です。既存フィールド・リクエスト契約は不変です。

## 2026-06-09 — v55: 宛先住所・氏名の変更を完全な変更履歴として保存

### 変更

* 宛先住所の手修正（[Address Recovery](/lmile-docs/fulfillment-api/address-recovery.md) の [`POST /api/routing/shipment/address`](/lmile-docs/fulfillment-api/address-recovery.md)）が、これまで `sot.lm_routing_orders.ship_to_*` を**上書き**するだけで**変更前の値を残していなかった**問題に対応し、変更のたびに **append-only の変更履歴**（`sot.lm_routing_order_ship_to_changes`）へ 1 行を記録するようにしました（LM-783）。各行に「**変更前（before）／変更後（after）の宛先住所スナップショット**」「変更した項目（`changedFields`）」「実施者（operator の `staff_user_id` または `correctedBy`）」「変更時刻」を残します。
* 住所の更新と履歴記録を **RPC で同一トランザクション**（atomic）にしました（`public.lm_routing_order_ship_to_update`）。変更前の値は**行ロック下に DB の現在値を読む**ため、真の before→after を取りこぼしなく記録します。**実際に値が変わったときだけ** 1 行を append するため、同じ住所での再 POST（冪等）は履歴を増やしません。
* レスポンスに **`changedFields`**（今回の修正で実際に変わった shipTo 項目名の配列）を追加しました（純 additive。リクエスト契約・既存フィールドは不変）。
* 変更履歴は受取人氏名・電話・メール・住所を含む **PII** のため `service_role` 専用です（公開 view / `agent_read` には出しません）。

## 2026-06-09 — v54: MFC ピック時に棚 qty を減算（出荷後の窓をゼロ化）

### 変更

* 自己在庫 MFC のユニットを [`POST /api/operator/shelf/pick`](/lmile-docs/shelf-api/lookup.md) で **picked にする瞬間**（`picked_at` の未→確定遷移）に、そのユニットが置かれていた棚の `qty` を **−1（`reason=pick`）** してから自己在庫の `available_qty` を再計算（[MFC Inventory](/lmile-docs/ingestion-api/mfc-inventory.md) LM-761 と同式）し、変化分を源在庫 webhook で販売面へ反映するようにしました（LM-769）。ピックはユニットが物理的に棚を離れる瞬間のため、出荷（`shipped`）を待たずに棚 `qty` が実態へ落ち、`shipped` 除外と合わせて「出荷後〜MFC が棚を再報告するまで」`available_qty` が一時的に過大になる窓（v52 で残課題として明記）がゼロになります。
* 減算する棚は star ラベルが作業者に提示する棚（同一 `(location, barcode)` で qty>0 優先・同点は `shelf_code` 昇順の 1 棚）と一致させ、「作業者がピックした棚」と「qty を −1 する棚」を揃えました。ピックの取り消し（`unpick`）では棚 `qty` を **+1（`reason=receive`）** して対称に復元します。
* **対象は自己在庫 MFC のみ**（`sot.lm_shelf_inventory` に棚在庫を持つ出荷元）。棚を持たない店舗 / 同期拠点のユニットは該当棚が無いため no-op です。棚の増減と再計算は `picked_at` の遷移時のみ行うため二重減算しません。MFC が `mode=absolute` で棚を再報告すると棚 `qty` は物理実数へ上書きされ整合します（差分積算でないため二重減算なし）。
* あわせて、`available_qty` / capacity（LM-768）の算出に使う「引き当て済み未出荷数」から**ピック済み**（`picked_at` 確定）ユニットを除外しました（`sot.lm_self_inventory_active_count` に `picked_at IS NULL` を追加）。ピック時に棚 `qty` を物理減算するため、棚合計とアクティブ引当数の両方で引くと二重減算になり、同一 barcode に複数在庫があるとき `available_qty` が過少になっていたのを是正します（ピック確定の瞬間に `available_qty` が不変になる）。この除外はピック時の棚減算とセットで適用します。
* 本リリースは公開リクエスト / レスポンス契約を変更しません（内部 SoT の棚 `qty` / `available_qty` 挙動のみ）。

## 2026-06-09 — v53: 受注情報更新（住所修正など）の webhook 通知を追加

### 追加

* [**Order Update Webhook**](/lmile-docs/webhooks/order-update.md)（[`POST /api/routing/order-update-webhook-config`](/lmile-docs/webhooks/order-update.md)）を追加しました（LM-742）。[Address Recovery](/lmile-docs/fulfillment-api/address-recovery.md)（[`/api/routing/shipment/address`](/lmile-docs/fulfillment-api/address-recovery.md)）で受注の配送先住所を手修正すると、`shop` 単位で登録した宛先へ修正後の `shipTo`（絶対状態）と `changeType` / `correctedAt` / `correctedBy` を自動 POST します。変更種別 `changeType` を持ち、当面は住所修正（`address_corrected`）の 1 種です（将来、明細プロパティ修正など他の更新種別も同じ webhook に `changeType` を追加して載せられます）。
* 既存 4 つの webhook（[Source Inventory](/lmile-docs/webhooks/source-inventory.md) / [Routing Allocation](/lmile-docs/webhooks/allocation.md) / [Fulfillment Status](/lmile-docs/webhooks/fulfillment-status.md) / [Oversell Status](/lmile-docs/webhooks/oversell-status.md)）と**同一の outbox / 配信機構**（テンプレートエンジン・暗号化 secret・リトライ・[outbox 自動 drain](https://lmile.gitbook.io/lmile-docs/resources/pages/OotbCjshtf2WFaZaqjCi#耐久性outbox) / 再送）を共有する 5 本目の webhook です。住所修正成功直後にバックグラウンド送信し、操作レスポンスや住所修正処理の成否には影響しません。
* 配送先住所（`shipTo`）は\*\*個人情報（PII）\*\*のため、outbox（`sot.lm_order_update_events`）は service\_role 限定とし、公開 read view を作りません（`request_payload` も service\_role 直のみ）。設定（`sot.lm_order_update_webhook_config`）の認証 secret は既存 webhook と同じ Vault 鍵で暗号化します。本リリースは既存の公開リクエスト / レスポンス契約を変更しません（住所修正レスポンスは不変・additive な webhook 発火のみ追加）。

## 2026-06-09 — v52: 自己在庫（MFC 棚付き入庫）を引き当て確定時に即時減算

### 修正（Bug）

* 自己在庫（[MFC Inventory](/lmile-docs/ingestion-api/mfc-inventory.md) で入庫する出荷元自前在庫）が**引き当て後も `available_qty` から減算されず**、源在庫 webhook（[Webhooks](https://github.com/falcon0119/inventory-os/tree/main/docs/webhooks/README.md)）が phantom available を販売面へ push してオーバーセルしていた問題を修正しました（LM-761）。受注ルーティングは判定のみで在庫を書かず、自己在庫の `available_qty` は入庫 API の棚合算 set が唯一の更新経路だったためです。
* 自己在庫の `available_qty` を**派生量** `max(0, 棚合計 − 引き当て済み未出荷数)` として再計算する経路を追加しました（`引き当て済み未出荷数` = `sot.lm_fulfillment_units` の `allocated` / `secured` / `in_transit_to_mfc` / `packing`）。引き当て（`/api/routing/orders`）・取消（`/api/routing/cancel`）・出荷元変更（`/api/routing/change-source`）・再引き当て（`/api/routing/reallocate`）・入庫（`/api/ingest/mfc-inventory`）の各点で再計算し、変化した自己拠点は源在庫 webhook で Shopify に反映します。再計算は確定値 set のため**冪等**で、`committed_qty=0` の自己在庫では `routable=available` となり LM-526 と整合します。
* **対象は自己在庫のみ**（`inventory_levels.source_system='mfc_inventory_ingest'`）。Shopify / smaregi 同期拠点は外部 push が在庫真実を持つため触りません（二重減算回避）。
* 出荷後〜MFC の棚再報告までの窓（pick 時の物理棚減算）と、engine 判定の同時刻レース完全封じ込め（行ロック原子化）は別チケット（LM-769 / LM-768）に分離しています。本リリースは公開リクエスト / レスポンス契約を変更しません（内部 SoT の `available_qty` 挙動のみ）。

## 2026-06-09 — v51: MFC 入庫（棚付き）に `mode`（absolute / adjust）を追加

### 変更

* [**MFC Inventory**](/lmile-docs/ingestion-api/mfc-inventory.md)（[`POST /api/ingest/mfc-inventory`](/lmile-docs/ingestion-api/mfc-inventory.md)）に top-level の **`mode`** を追加しました（LM-739）。`mode=absolute`（**既定 / 省略時**）は従来どおり各行の qty を**絶対値で set**（棚卸し的な確定）、`mode=adjust` は qty を符号付き**差分**として加減算します（`+` 入庫 / `-` 減算）。`mode` 省略時の挙動は従来と完全に同一です（後方互換）。いずれの mode でも棚別在庫（`sot.lm_shelf_inventory`）の反映と barcode 集約 `sot.inventory_levels.available_qty`（ルーティング引当原資）への更新を同一トランザクションで行います。`adjust` で在庫が負になる行はバッチ全体を `409 insufficient_shelf_qty` で reject します（部分適用なし）。`adjust` は差分加減算のため**非冪等**です（[Idempotency](/lmile-docs/reference/idempotency.md)）。なお `adjust` は棚在庫のみ反映する [`POST /api/shelf/inventory/receive`](/lmile-docs/shelf-api/inventory.md) とは別レイヤーで、本 API は引当原資（`inventory_levels.available_qty`）まで反映する点が異なります。
* あわせて本ページのレスポンス例・エラー表・冪等性の記述を実装に合わせて是正しました（実レスポンスは `{ ok, applied, mode }`。`product_not_found` はバッチ全体を `422` で中断、占有チェックは本 API には無い旨）。

## 2026-06-09 — v50: 拠点一覧を出荷元メンバーに絞り込む `memberOnly`

### 変更

* [**Operator Locations**](/lmile-docs/operator-api/locations.md)（[`GET /api/operator/locations`](/lmile-docs/operator-api/locations.md)）に **`memberOnly`** クエリを追加しました（LM-741）。`memberOnly=true`（または `1`）で、`sot.lm_fulfillment_source_members` の `is_active=true` な `inventory_location_id` に一致する拠点だけを返します（出荷が実際に流れる拠点のみ）。`type` 絞り込み（role 別）とは AND で、**fallback はありません**（member が 0 件なら空配列）。出荷元（MFC / 倉庫）自体も member 行（自己 member 登録を含む）が無ければ一覧に出ません。picking-ios（LM-737）の店舗選択 UI を、店舗・POPUP の全拠点ではなく出荷元メンバー拠点だけに絞るためのオプションです。既定（`memberOnly` 未指定）は従来どおり全アクティブ拠点を返します。

## 2026-06-09 — v49: ストア表示名（shopNames）をログインレスポンスに追加

### 変更

* [**Operator Login**](/lmile-docs/operator-api/login.md) の `login` / `login/google` / `login/apple` / `me` のレスポンスに **`shopNames`（shop ドメイン → 表示名の map）** を追加しました（LM-736・純 additive）。これまで picking-ios の shop / 拠点選択・設定画面は shop ドメイン（`mybonaventura.myshopify.com`）をそのまま表示していましたが、表示名（ブランド名）を inventory-os 側の単一ソースで一元管理し、アプリがドメインの代わりにブランド名を表示できるようにします。表示名が登録されている shop のみ map に含み、未登録の shop はキーに現れません（アプリはその shop のドメインをそのまま表示する graceful fallback）。既存の `shops` フィールドは変更ありません。

## 2026-06-09 — v48: セルフサインアップ（Operator Signup）を廃止

### 変更

* **`POST /api/operator/signup` を撤去**しました（LM-723 / LM-724）。picking-ios はサインインのみのマーチャント業務アプリ（Shopify POS モデル）として一般公開する方針に変更したため、アプリ内のセルフサインアップを廃止します。スタッフアカウントはプラットフォーム / 管理者側で発行し、本 API は既存アカウントの認証（`login` / `login/google` / `login/apple` / `refresh`）のみを担います。これに伴い signup 専用の `error_kind`（`weak_password` / `invalid_email` / `signup_disabled` / `user_already_exists`）は廃止しました。アカウント作成がアプリ内に無くなるため、アプリ内アカウント削除（Apple 5.1.1(v)）の要件も対象外になります（バックエンドの `POST /api/operator/account/delete` は残置）。

## 2026-06-09 — v47: 再引き当て（reallocate）の `ok` セマンティクスを明文化

### ドキュメント

* [**Oversell / Reallocate**](/lmile-docs/oversell-api/oversell-reallocate.md)（[`POST /api/routing/reallocate`](/lmile-docs/oversell-api/oversell-reallocate.md)）のレスポンス `ok` フィールドの意味を明記しました（挙動変更なし）。**再引き当て先の在庫が無くても（`status: no_stock` / `unresolvedReallocations > 0` / `skipped > 0`）`ok: true` のまま** `200` で返り、`ok: false` になるのは入力不正（`400`）・注文不在（`404`）・dispatch 送信失敗（`status: failed`）に限ります。再引き当ての成否は `ok` ではなく `status` / `unresolvedReallocations` / `skipped` で判定する旨をレスポンスフィールド表と「挙動・冪等性」に追記しました。

## 2026-06-08 — v46: Apple サインイン（Operator Login with Apple）

### 新規

* [**Operator Login**](/lmile-docs/operator-api/login.md)（[`POST /api/operator/login/apple`](/lmile-docs/operator-api/login.md)）— ピッキングアプリ（picking-ios）が Sign in with Apple で取得した Apple identity token を検証して operator JWT を発行する API を追加しました。アプリは Supabase の anon key を持たず api.lmile.io のみと通信する設計のため、inventory-os が Supabase Auth の `signInWithIdToken`（provider=apple）を代理します（[Operator Login](/lmile-docs/operator-api/login.md) の Google サインインと同じプロキシ方針）。Google サインインを併設するアプリに同等の代替ログインを求める Apple ガイドライン 4.8 への対応です。認証は `identityToken` のみで完結し（`email` / `fullName` / `user` は初回のみ届く付随情報）、束縛 shop が 0 件（自己登録直後 / Hide My Email の新規ユーザー）でも `ok: true` + `shops: []` で返してアプリのオンボーディングが shop 紐付けを担います。検証失敗は一律 `401 invalid_id_token` / 試行上限 `429 rate_limited` / 認証基盤不通 `503 auth_unavailable`（フォールバックなし）。

## 2026-06-08 — v45: MFC 入庫（棚付き）を operator JWT でも実行可能に

### 変更

* [**MFC Inventory**](/lmile-docs/ingestion-api/mfc-inventory.md)（[`POST /api/ingest/mfc-inventory`](/lmile-docs/ingestion-api/mfc-inventory.md)）の認証を **2 系統**（`x-ingest-secret` / operator JWT）に拡大しました（[認証](https://lmile.gitbook.io/lmile-docs/resources/pages/7cB70I8yeRnMpvcdLkNu#routing-write-の-2-系統認証)）。倉庫スタッフのピッキングアプリ（picking-ios）から棚付き在庫を直接入庫できます。系統は**ヘッダの有無で明示判別**し、既存の機械間クライアント（`x-ingest-secret` のみ提示）の挙動は不変です。operator JWT で呼んだ場合は入庫操作者（検証済の `auth.users.id`）を棚在庫ログ（`lm_shelf_inventory_logs.operator`）に記録します（機械間経由は NULL）。これで 2 系統認証で呼べるエンドポイントは 10 になりました。

## 2026-06-08 — v44: アカウント削除（Operator Account Delete）

### 新規

* [**Operator Login**](/lmile-docs/operator-api/login.md)（[`POST /api/operator/account/delete`](/lmile-docs/operator-api/login.md)）— ピッキングアプリ（picking-ios）の退会導線として、ログイン中スタッフ**本人**が自分のアカウントを即時削除できる API を追加しました。削除できるのは JWT の持ち主自身のみで、誤操作防止のため `confirm: true` が必須です。削除すると全セッション / refresh token が即時失効し、shop 束縛も解除されます。出荷作業などの操作履歴は匿名 UUID として保持し、メールアドレス（個人情報）は削除します。削除はメールアドレスの snapshot 付きで内部監査トレイル（`sot.lm_operator_account_deletions`）に記録します。**デモアカウント**（審査・デモ用）は `403 demo_account_protected` で保護され削除できません。既に削除済みのアカウントへの再実行は `200` + `deleted: true` で冪等です（[Idempotency](/lmile-docs/reference/idempotency.md) / [Error Codes](/lmile-docs/reference/error-codes.md)）。

## 2026-06-08 — v43: セルフサインアップ（Operator Signup）

### 新規

* [**Operator Signup**](/lmile-docs/operator-api/login.md)（[`POST /api/operator/signup`](/lmile-docs/operator-api/login.md)）— 倉庫スタッフ向けピッキングアプリ（picking-ios）が、メールアドレス + パスワードで**セルフサインアップ**できる API を追加しました。アプリは Supabase の anon key を持たず api.lmile.io のみと通信する設計のため、inventory-os が Supabase Auth の `signUp` を代理します（[Operator Login](/lmile-docs/operator-api/login.md) と同じプロキシ方針）。確認メール方式に従い、作成成功時は確認メールを送信して `confirmed: false`（JWT 未発行）を返し、スタッフは確認後に [`POST /api/operator/login`](/lmile-docs/operator-api/login.md) で JWT を取得します。既存メールの重複は、メールアドレスの存在有無を漏らさないため**新規と同じ** `confirmed: false` に吸収します（user enumeration 対策）。パスワード強度不足 `422 weak_password` / 無効なメール `422 invalid_email` / 試行上限 `429 rate_limited` / 認証基盤不通 `503 auth_unavailable`（フォールバックなし）。作成直後のアカウントは shop 未束縛です（[認証](https://lmile.gitbook.io/lmile-docs/resources/pages/7cB70I8yeRnMpvcdLkNu#operator-jwt-認証) / [Error Codes](/lmile-docs/reference/error-codes.md) / [Idempotency](/lmile-docs/reference/idempotency.md)）。

## 2026-06-08 — v42: MFC 入庫（棚付き）エンドポイント（MFC Inventory）

### 新規

* [**MFC Inventory**](/lmile-docs/ingestion-api/mfc-inventory.md)（[`POST /api/ingest/mfc-inventory`](/lmile-docs/ingestion-api/mfc-inventory.md)）— 大阪 MFC などの出荷元ロケーションに**棚番号付き**の在庫を絶対値で入庫する取込 API を追加しました。1 リクエストで棚別在庫（`sot.lm_shelf_inventory`）の `(barcode × shelfCode)` 絶対値 set と、その barcode を全棚で合算した販売可能在庫（`sot.inventory_levels.available_qty`）の更新を**同一トランザクション**で行います（部分適用なし・絶対値 set のため再送に冪等）。この入庫在庫は受注ルーティングで**優先的に引き当て**られ、MFC 引き当て時は Star ラベルに棚番号が印字されます。barcode 未登録の行は `unresolved[]` に返して skip します（[Data Model](/lmile-docs/reference/data-model.md) / [Idempotency](/lmile-docs/reference/idempotency.md) / [Error Codes](/lmile-docs/reference/error-codes.md)）。

## 2026-06-08 — v41: 出荷ステータス遷移を operator JWT でも実行可能に

### 変更

* [**Fulfillment**](/lmile-docs/fulfillment-api/fulfillment.md)（[`POST /api/routing/fulfillment`](/lmile-docs/fulfillment-api/fulfillment.md)）の認証を **2 系統**（`x-ingest-secret` / operator JWT）に拡大しました（[認証](https://lmile.gitbook.io/lmile-docs/resources/pages/7cB70I8yeRnMpvcdLkNu#routing-write-の-2-系統認証)）。倉庫スタッフのピッキングアプリ（picking-ios）から確保済 → 梱包 → 出荷完了などの状態遷移を直接報告できます。系統は**ヘッダの有無で明示判別**し、既存の機械間クライアント（`x-ingest-secret` のみ提示）の挙動は不変です。operator JWT で呼んだ場合は報告した出荷元ヘッダに操作スタッフ（検証済の `auth.users.id`）を記録します（`status_reported_by_staff_user_id`。機械間経由は NULL・非公開列）。これで [Routing write の 2 系統認証](https://lmile.gitbook.io/lmile-docs/resources/pages/7cB70I8yeRnMpvcdLkNu#routing-write-の-2-系統認証)は 9 エンドポイントになりました。

## 2026-06-07 — v40: 拠点一覧（Operator Locations）

### 新規

* [**Operator Locations**](/lmile-docs/operator-api/locations.md)（[`GET /api/operator/locations`](/lmile-docs/operator-api/locations.md)）— ピッキングアプリ（picking-ios）の店舗（location）選択 UI 用に、shop のアクティブな拠点一覧（`id` / `label` / `locationType` / `region`）を返す read 専用 API を追加しました。`type`（`location_type` の CSV、例: `store,popup`）で拠点種別を絞り込めます。返る `id` は [Operator Queues](/lmile-docs/operator-api/queues.md) の `fromLocationId` フィルタにそのまま渡せます。認証は operator JWT です。

## 2026-06-07 — v39: 確保スキャン（Secure Scan）+ ユニットQR を本番印字の 2 値規格に統一

### 新規

* [**Secure Scan**](/lmile-docs/operator-api/secure-scan.md)（[`POST /api/operator/secure-scan`](/lmile-docs/operator-api/secure-scan.md)）— 店舗スタッフが商品ラベルのユニットQR（`<barcode>|<shipmentId>`）をスキャンして在庫を 1 ユニットずつ確保する API を追加しました。QR からの解決（`shipmentId` → 注文）と対象ユニットの選定（`allocated` かつ 未 picked の `lineInstanceNo` 昇順先頭 1 件）をサーバ側で行うため、呼び出し側は QR をそのまま渡すだけです。出荷元の全ユニットが確保済になるとヘッダを `secured` に遷移させ、[`POST /api/routing/secure`](/lmile-docs/fulfillment-api/units.md) と同一経路で配送ラベルを自動生成します。再スキャンは冪等（`alreadySecured`・二重確保なし）。認証は operator JWT / `x-ingest-secret` の 2 系統です。

### 変更

* **ユニットQR の規格を本番印字形式（2 値）に統一** — [Shelf Lookup](/lmile-docs/shelf-api/lookup.md)（`GET /api/operator/shelf/lookup` / `POST /api/operator/shelf/pick`）の QR 形式を、出荷指示ラベルの本番印字形式である `<barcode>|<shipmentId>`（2 値）に修正しました（従来ドキュメントの `LM2|...` 4 値形式は印字実態と不一致のため撤回）。2 値は同一 barcode の複数ユニットを区別しないため、`pick` はスキャンごとに未 picked の `lineInstanceNo` 昇順先頭 1 件、`unpick` は picked の降順先頭 1 件（LIFO）を対象にし、レスポンスに `units.total` / `units.picked`（進捗）を追加しました。lookup は `shipmentId` の shipment 不在を `404 shipment_not_found` で区別します（[Error Codes](/lmile-docs/reference/error-codes.md)）。

## 2026-06-07 — v38: 出荷作業キュー・引当不能注文の一覧（Operator Queues）

### 新規

* [**Operator Queues**](/lmile-docs/operator-api/queues.md) — 倉庫スタッフ向けピッキングアプリ（picking-ios）が現場（店舗 / MFC）の作業量を pull で把握する一覧 API を公開ドキュメント化しました。出荷作業キュー一覧（[`GET /api/operator/shipments`](/lmile-docs/operator-api/queues.md)・location × status × 期間でフィルタ + フィルタ全体の status 別件数・未ラベル件数サマリ）と、引当不能（`no_stock`）のまま滞留している注文の一覧（[`GET /api/operator/unallocated-orders`](/lmile-docs/operator-api/queues.md)・[Routing Allocation Webhook](/lmile-docs/webhooks/allocation.md) の `unallocated` イベントを見逃しても滞留に気づける pull 経路）です。いずれも read 専用・operator JWT 認証（API は提供済で、本リリースはドキュメントの追加です）。

## 2026-06-07 — v37: Allocation Webhook に出荷元（fulfillmentSourceLocationId）を追加

### 変更

* [**Routing Allocation Webhook**](/lmile-docs/webhooks/allocation.md) のペイロード変数に `fulfillmentSourceLocationId`（注文の出荷元 id = [Routing](/lmile-docs/routing-api/orders.md) リクエストの `fulfillmentSourceLocationId`）を追加しました。既定テンプレートにも同梱されます。`unallocated`（引き当て不能）イベントは `shipmentId` / `fromLocationId` が `null` で出荷元を特定できませんでしたが、本フィールドで「どの出荷元の注文が引き当て不能か」を受け手が解決できます（出荷元単位の通知・印刷用途）。追加のみの後方互換変更で、カスタム `payloadTemplate` 利用時は影響ありません。本フィールド追加前に起票済みのイベントが再送される場合は `null` です。

## 2026-06-07 — v36: operator Google サインイン（Operator Login）

### 新規

* [**`POST /api/operator/login/google`**](/lmile-docs/operator-api/login.md) — 倉庫スタッフ向けピッキングアプリ（picking-ios）のログインに Google サインインを追加しました。アプリ側で取得した Google ID token（`idToken`）を渡すと、[`POST /api/operator/login`](/lmile-docs/operator-api/login.md)（`email` + `password`）と同形のレスポンス（operator JWT / refreshToken / staff / shops）を返します。staff↔shop 束縛はスタッフのユーザー単位なので、同じメールアドレスのスタッフは email + password ログインと同じ束縛 shop 群に解決されます。ID token の検証失敗は `401 invalid_id_token`（[Error Codes](/lmile-docs/reference/error-codes.md)）。

## 2026-06-07 — v35: リカバリ系 3 エンドポイントの operator JWT 対応（Address Recovery / Print Label）

### 変更

* **リカバリ系 write の 2 系統認証** — [宛先住所修正 / ラベル再発行](/lmile-docs/fulfillment-api/address-recovery.md)（`/api/routing/shipment/address` / `/api/routing/shipment/retry-label`）と[ラベル手動再印刷](/lmile-docs/fulfillment-api/print-label.md)（`/api/routing/shipment/print-label`）の 3 つが、`x-ingest-secret` に加えて operator JWT（`Authorization: Bearer`）でも呼べるようになりました（[Routing write の 2 系統認証](https://lmile.gitbook.io/lmile-docs/resources/pages/7cB70I8yeRnMpvcdLkNu#routing-write-の-2-系統認証)は計 7 エンドポイント。系統はヘッダの有無で明示判別・フォールバックなし。既存の機械間クライアントの挙動は不変）。
* operator JWT 経由の操作は操作スタッフを記録します — 住所修正は既存の監査列 `sot.lm_routing_orders.ship_to_corrected_by` にスタッフの検証済 ID（`correctedBy` ボディ値より優先）、ラベル再発行 / 手動再印刷は新設の `sot.lm_fulfillment_shipments.label_retried_by_staff_user_id` / `label_printed_by_staff_user_id`（[Data Model](/lmile-docs/reference/data-model.md)）。

## 2026-06-07 — v34: 倉庫スタッフ向け Operator API（authentication / Operator）

### 新規

* [**Operator API**](/lmile-docs/operator-api/login.md) — 倉庫スタッフ向けピッキングアプリ（picking-ios）が呼ぶ `/api/operator/*` を公開ドキュメント化しました。スタッフ個人ログイン（[`POST /api/operator/login`](/lmile-docs/operator-api/login.md)）で operator JWT を発行し、[`POST /api/operator/refresh`](/lmile-docs/operator-api/login.md) で更新、[`GET /api/operator/me`](/lmile-docs/operator-api/login.md) で id / email / 束縛 shop を取得します。照会 API（[Operator Lookup](/lmile-docs/operator-api/lookup.md)）として追跡番号 → shipment + 注文 + 明細 + 配送先 + 状態（`GET /api/operator/shipments/by-tracking`）、バーコード → 商品（`GET /api/operator/products/by-barcode`）、追跡番号 / ステータスで売越しケース検索（`GET /api/operator/oversell-cases`）を追加しました。棚運用（`/api/operator/shelf/*`）は [Shelf Lookup](/lmile-docs/shelf-api/lookup.md) を参照してください。
* **認証の 2 系統化を明文化** — [認証](/lmile-docs/getting-started/authentication.md) に **operator JWT**（`Authorization: Bearer`）系統を追記しました。倉庫スタッフはスタッフ個人ログインで発行した JWT で `/api/operator/*` を呼び、操作できる `shop` は staff↔shop 束縛で制限されます（束縛 shop 外は `403 shop_not_authorized`）。
* **Routing write の 2 系統認証** — [在庫確保](/lmile-docs/fulfillment-api/units.md)（`/api/routing/secure`）・[売越しマーク / 再引き当て](/lmile-docs/oversell-api/oversell-reallocate.md)（`/api/routing/oversell` / `/api/routing/reallocate`）・[売越しケース](/lmile-docs/oversell-api/cases.md)（`/api/routing/oversell-case`）の 4 つは、`x-ingest-secret` と operator JWT のどちらでも呼べるようになりました（系統はヘッダの有無で明示判別・フォールバックなし。既存の機械間クライアントの挙動は不変）。operator JWT 経由の write は操作スタッフを記録します（`sot.lm_fulfillment_units.secured_by_staff_user_id` / `sot.lm_routing_decisions.oversold_by_staff_user_id`・`created_by_staff_user_id` / `sot.lm_oversell_cases.opened_by_staff_user_id`・`updated_by_staff_user_id`）。
* `sot.lm_operator_staff_shops`（スタッフ ↔ shop の operator API 認可束縛）を追加（[Data Model](/lmile-docs/reference/data-model.md)）。個人情報を含むため service\_role 限定で `agent_read.*` / 公開 view には露出しません。

## 2026-06-07 — v33: 棚（シェルフ）運用 API（Shelf）

### 新規

* [**Shelf API**](/lmile-docs/shelf-api/link.md) — 倉庫内の棚運用（picking-ios 移行）を routing-native に再構築した API 群を追加しました。配送ラベルの追跡番号 + 棚コードをスキャンして棚に出荷を割り当てる [Shelf Link](/lmile-docs/shelf-api/link.md)（`POST /api/shelf/link`）、棚在庫を barcode 単位で増減する [Shelf Inventory](/lmile-docs/shelf-api/inventory.md)（`POST /api/shelf/inventory/receive` / `/pick`）、ピッキングアプリ向けの照会・ピック [Shelf Lookup](/lmile-docs/shelf-api/lookup.md)（`GET /api/operator/shelf/lookup` / `/by-code` / `POST /api/operator/shelf/pick`）です。
* **統合QR v2 規格** `LM2|<barcode>|<routingOrderId>|<lineInstanceNo>` を採用し、3 値で [Units](/lmile-docs/fulfillment-api/units.md) を per-unit で完全特定します（旧規格 `JAN|FulfillmentOrderId` は受理せず `legacy_qr` で再印刷を案内）。棚コードは `^[A-Z0-9]+(-[A-Z0-9]+)+$`（英字必須・32 文字以内）に統一し、追跡番号との誤認を構造的に防ぎます。
* 棚紐付けは **shipment 単位**で、確保済（`secured`）以降〜出荷前の shipment にのみ可能。出荷完了 / 取消で自動解除されます。棚在庫は **qty 集約モデル**（同一棚に複数 barcode 不可・同一 barcode は複数棚に分散可）で、増減は `sot.lm_shelf_inventory_logs` に append-only で記録します。ピッキング完了は配送 status と直交の作業状態として `sot.lm_fulfillment_units.picked_at` / `picked_by` で表現します。
* write 系（link / inventory / pick）は `x-ingest-secret` または operator JWT（`Authorization: Bearer`）、read 系（lookup / by-code）は operator JWT で認証します。`sot.lm_shelf_links` / `sot.lm_shelf_inventory` / `sot.lm_shelf_inventory_logs` と `sot.lm_fulfillment_units.picked_at` / `picked_by` を追加（[Data Model](/lmile-docs/reference/data-model.md)）。read 用 view `public.lm_v_shelf_links` / `public.lm_v_shelf_inventory` は内部 service / 管理用途で、`agent_read.*` には露出しません。

## 2026-06-07 — v32: 売越しケース受付完了通知（Oversell Status Webhook）

### 新規

* [**Oversell Status Webhook**](/lmile-docs/webhooks/oversell-status.md) — [売越しケース](/lmile-docs/oversell-api/cases.md)が **MFC 倉庫で受付完了（`warehouse_received`）に遷移したとき**に shop 単位で登録した宛先へ通知する webhook を追加しました（既定イベント名 `oversell_case_warehouse_received`）。確保元ロケーション（`foundLocationId`）からの出庫分が MFC で受付完了したことを外部システムへ伝え、スマレジ等への入庫処理を実行する用途を想定しています。設定は `POST /api/routing/oversell-status-webhook-config` で upsert します。
* ペイロードは受付完了の絶対状態（`oversellCaseId` / `foundLocationId` / `status: warehouse_received`）と明細 snapshot（`lines` = `barcode` / `sku` / `productName` / `quantity`、1 ケース = 1 単位のため常に 1 行）です。配信・リトライ・暗号化・耐久性（outbox）は既存 webhook と共通（[Webhooks 概要](/lmile-docs/webhooks/overview.md)）。outbox は `UNIQUE (oversell_case_id)` で二重発行を防ぎます。
* `sot.lm_oversell_status_webhook_config` / `sot.lm_oversell_status_events` を追加（[Data Model](/lmile-docs/reference/data-model.md)）。

## 2026-06-07 — v31: 在庫変動通知（Source Inventory Webhook）の並列配信

### 変更

* [**Source Inventory Webhook**](/lmile-docs/webhooks/source-inventory.md) の配信を並列化しました。これまではイベントを 1 件ずつ順次送信していたため、全量再同期などで数千件の変動が一度に発生すると配信に時間がかかっていました。今後は同時実行数の上限つきで並列送信します（同一 `barcode` のイベントは順序を保持）。受け手は複数 `barcode` の POST を同時に受け取ることがあります。ペイロード・認証・リトライの仕様に変更はありません。

## 2026-06-05 — v30: 出荷ラベルの出荷元プリンター自動印刷 + 手動再印刷

### 新規

* **ラベル自動印刷** — ラベル生成（[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) の確保済遷移 / [Retry Label](/lmile-docs/fulfillment-api/address-recovery.md)）の成功直後に、出荷元の `action: "print"` 設定（[Dispatch Config](https://lmile.gitbook.io/lmile-docs/resources/pages/bGOYICmcj4SdTpefqrDg#actionprint-ラベル物理印刷)）があれば保存した PDF を出荷元の print server へ `multipart/form-data`（A5 / Cardstock）で自動送信するようになりました。印刷は best-effort で、失敗してもラベル生成・状態遷移は維持し `last_print_error` に記録します（レスポンスに `printStatus` を追加）。[Source Change](/lmile-docs/oversell-api/source-change.md) の返送ラベルも旧出荷元で自動印刷されます（`returnLabelPrintStatus`）。
* [**`POST /api/routing/shipment/print-label`**](/lmile-docs/fulfillment-api/print-label.md) — 保存済みラベル PDF の手動再印刷。キャリア API を再呼び出ししないため追跡番号は変わりません（紙詰まり等の回収用）。
* `sot.lm_location_dispatch_config.action` に `print` を追加（`print` は `payloadTemplate` 不要）。`sot.lm_fulfillment_shipments` に `label_printed_at` / `last_print_error` を追加（[Data Model](/lmile-docs/reference/data-model.md)）。

## 2026-06-05 — v29: 顧客注文照会 API（Customer Orders）

### 新規

* [**Customer Orders**](/lmile-docs/customer-orders-api/orders.md) — 顧客のメールアドレスを突合キーに、注文履歴（`POST /api/customer-orders/list`）と注文詳細（`POST /api/customer-orders/detail`）を返す read API を追加。マイページ等の BFF から server-to-server で呼び出す想定です。注文ごとに 4 値の集約ステータス（`processing` / `partially_shipped` / `shipped` / `cancelled`）、明細（商品名・バリアント・数量・税込単価・画像）、金額（`order_line_master` 合算）、配送先、出荷元単位の追跡番号・出荷日時を返します。
* 突合対象は [Routing](/lmile-docs/routing-api/orders.md) に **`shipTo.email` 付きで投入された注文**のみ（email の大文字小文字・前後空白は正規化して照合。`sot.lm_routing_orders.ship_to_email_norm` 生成列 + index を追加）。`detail` は email と注文の組み合わせを所有権チェックとして使い、不一致は `404 order_not_found`（存在を判別させません）。
* 配達完了（delivered）はキャリア配達イベントを持たないため返しません（終端は `shipped`）。送料・決済手段も SoT に存在しないため返しません（`shipping: null` / `payment` 無し）。

## 2026-06-04 — v28: LMile Apps（ホスト型ミニアプリ・プレビュー）

### 新規

* [**Apps**](/lmile-docs/apps/overview.md) — イベントを検知して自動処理（外部システム連携・通知・LMile API への write-back）を実行するミニアプリを、LMile がホストする専用実行環境（1 アプリ = 1 VM、相互に隔離）で動かせるようになりました（**プレビュー**）。アプリは TypeScript の SDK（[`@lmile/app-kit`](/lmile-docs/apps/sdk.md)）で handler を書くだけで、受け手サーバーの運用は不要です。既存の [Webhooks](/lmile-docs/webhooks/overview.md)（自前サーバーへの通知）と同じ発火点から並走して配信されるため併用できます。
* 現在配信されるイベントは [`routing_allocation_decided`](/lmile-docs/apps/events.md)（引き当て暫定確定）。`fulfillment_shipment_status_changed` / `fulfillment_source_inventory_changed` は準備中です。配信は outbox 記録 + at-least-once（[Idempotency](/lmile-docs/reference/idempotency.md)）。明細の `properties`（名入れ等）と配送先住所はアプリ向けイベントに**含まれません**（PII 保護）。
* アプリの登録・デプロイ・環境変数の設定は現在 LMile 運用が行います（<admin@lmile.io>）。`sot.lm_apps` / `lm_app_subscriptions` / `lm_app_deliveries` / `lm_app_executions` を追加（[Data Model](/lmile-docs/reference/data-model.md)）。

## 2026-06-04 — v27: 出荷ラベル設定の解決キーを出荷元（fulfillment source）に変更

### 変更

* **`action=label` の** [**Dispatch Config**](/lmile-docs/configuration/dispatch-config.md) **は出荷元 location で解決** — 出荷ラベルを物理出力するのは引き当て店舗ではなく出荷元（MFC センター / 倉庫）のため、ラベル設定の解決キーを shipment の引き当て先在庫ロケーションから**注文の出荷元（fulfillment source location）に変更しました。`label` 設定の `locationId` には出荷元 location を指定してください（`create` / `update` / `cancel` は従来どおり引き当て先在庫ロケーションで解決）。**[**Source Change**](/lmile-docs/oversell-api/source-change.md) **の返送便ラベルは旧出荷元** + `tag`（既定 `return`）で解決します。
* [ラベル再発行](/lmile-docs/fulfillment-api/address-recovery.md)（`/api/routing/retry-label`）の skip 理由に `fulfillment_source_unresolved`（shipment 配下の unit から出荷元を特定できない場合）を追加。
* ラベル PDF の Storage パス（`{shop}/{routingOrderId}/{fromLocationId}.pdf` = shipment 単位）は不変です。

> 出荷元とその実在庫メンバーが同一 location の構成（単一倉庫など）では挙動は変わりません。出荷元配下に複数の店舗在庫メンバーを持つ構成では、メンバーごとに設定を複製せず**出荷元 1 箇所**に登録します。

## 2026-06-04 — v26: 引き当て暫定確定 webhook（Routing Allocation Webhook）

### 新規

* [**Routing Allocation Webhook**](/lmile-docs/webhooks/allocation.md) — [Routing](/lmile-docs/routing-api/orders.md)（`/api/routing/orders`）で在庫引き当てが暫定確定した直後に、引き当て先ロケーションごとに 1 通ずつ通知する webhook を追加。引き当て不能明細があれば `unallocated` イベントを 1 通追加送信します（全量在庫不足 = `no_stock` 含む）。設定は `POST /api/routing/allocation-webhook-config`（shop 単位。既存 webhook と同じ設定スキーマ / ペイロードテンプレート / リトライ / outbox / secret 暗号化）。
* 明細（`lines`）は起票時の引き当て結果を outbox（`sot.lm_routing_allocation_events`）に snapshot して送信します（出荷指示と同じ `barcode` × `properties` 単位の行に、商品情報 `sku` / `productName` と明細単位の任意キー/値 `properties` を同梱）。後続の売越し再引き当て・出荷元変更で引き当てが変わる場合があるため、確保以降の進捗は [Fulfillment Status Webhook](/lmile-docs/webhooks/fulfillment-status.md) で追跡してください。

## 2026-06-04 — v25: ロケーション単位の Star プリンター設定 API

### 新規

* [**Star Printer**](/lmile-docs/configuration/star-printer.md)（`/api/routing/star-printer`）— 在庫ロケーションに Star プリンターの device ID を紐付ける設定 API を追加。設定（upsert）/ 解除（detach）/ 一覧（GET）。キーは `(shop, locationId)` = 1 ロケーション 1 プリンターで、再設定は device ID の差し替えになります。`sot.lm_location_star_printers` に保存します。

## 2026-06-04 — v24: routing 明細単位の properties（line item property 相当）

### 新規

* **`lines[].properties`** — [Routing](/lmile-docs/routing-api/orders.md)（`/api/routing/orders` / `/api/routing/update`）の受注明細に、明細単位の任意キー/値（刻印テキスト・名入れ・ギフト指定等。Shopify line item property 相当）を渡せるようになりました。object 形式（最大 20 キー、キー 100 文字・値 500 文字以内）。`sot.lm_routing_decisions.line_properties` / `sot.lm_fulfillment_units.line_properties` に保存し、出荷指示（`shipments[].lines[]` / `unroutableLines[]` / `serviceLines[]`）→ [Picking List](/lmile-docs/fulfillment-api/picking-list.md)（JSON `items[].properties` + PDF 1 行表示）→ [Dispatch Config](/lmile-docs/configuration/dispatch-config.md) の WMS / label テンプレート（`$each` 内 `{{properties.<キー>}}`）まで透過します。[Reallocate](/lmile-docs/oversell-api/oversell-reallocate.md) / [Source Change](/lmile-docs/oversell-api/source-change.md) でも後継 decision へ引き継がれます。
* **テンプレート変数の日本語キー対応** — `payloadTemplate` の `{{path}}` が `{}` と空白を除く任意の文字を受け付けるようになり、`{{properties.刻印}}` のような日本語キーを参照できます。

### 変更

* **同一 barcode 複数明細の引き当て修正** — 同一 `barcode` の明細が複数ある注文（properties 違い等）で、在庫を二重参照して二重引き当てになり `lineInstanceNo` が衝突する問題を修正。明細は barcode 単位に**合算して 1 回で引き当て**、unit へ元明細の順に `properties` を配り戻します。出荷指示・ピッキングリストは `barcode × properties` 単位で行を分けて集計します。

> `properties` は名入れ等で顧客 PII になり得るため、`agent_read` には公開しません。properties 導入前に保存された出荷指示の明細は `properties: null` として扱われます（後方互換）。Ship\&Co ラベルアダプタの送信 payload は不変です。

## 2026-06-04 — v23: ドキュメント再構成（Webhooks セクション新設）

### 変更

* **ナビゲーションを機能別セクションに再編** — Getting Started / Ingestion / Routing / Fulfillment / Oversell / Configuration / **Webhooks** / Reference。2 種の webhook を [Webhooks](/lmile-docs/webhooks/overview.md) に集約し、共通機構（設定・ペイロードテンプレート・リトライ・outbox・暗号化）を概要ページに一本化。
* **共通記述の集約** — 共通エラーは [Error Codes](/lmile-docs/reference/error-codes.md)、冪等性は [Idempotency](/lmile-docs/reference/idempotency.md) を正とし、各エンドポイントページはエンドポイント固有の挙動のみを記載。
* 移動したページの旧 URL はリダイレクトされます。curl サンプル集（examples/curl）は各エンドポイントページのリクエスト例に集約し廃止。

> API 自体の変更はありません（エンドポイント・パラメータ・挙動は不変）。

## 2026-06-04 — v22: 出荷ステータス webhook に出荷明細（lines）を同梱

### 変更

* [**Fulfillment Status Webhook**](/lmile-docs/webhooks/fulfillment-status.md) **の既定テンプレート拡張** — ペイロードに `shipmentId`（`sot.lm_fulfillment_shipments.id`。受信側の冪等キー用）と `lines`（shipment 配下の `sot.lm_fulfillment_units` を barcode 単位に集約した `[{ "barcode", "sku", "quantity" }]`）を追加。受信側が**注文全体ではなく出荷された明細だけ**を外部システム（Shopify 等）の出荷済みに反映できるようにする。
* units の取得失敗・0 件時は lines 無しのまま送信せず `delivery_status: failed`（`last_error: units_fetch_error / no_units_for_shipment`）として残し、再送 endpoint で回収する。
* カスタム `payloadTemplate` 利用時は新変数 `{{shipmentId}}` / `{{lines}}`（単一変数で配列型を保持）を任意で利用可能。既存テンプレートの挙動は不変。

## 2026-06-04 — v21: 非在庫サービス品をルーティング対象から除外

### 変更

* **非在庫サービス品の除外** — 物理在庫を持たないサービス/カスタム明細（刻印サービス等）が在庫ベースのルーティングで恒久的に `no_stock_anywhere` / `unroutableLines` ノイズになる問題を解消。`sot.products.is_non_inventory = true` の商品は**在庫引き当ての対象外**になり、出荷指示の新フィールド **`serviceLines[]`**（`barcode` / `quantity`）に分類されます（[Routing — 受注ルーティング](/lmile-docs/routing-api/orders.md)）。
* 判定根拠は従来どおり `sot.lm_routing_decisions` に記録（`selected_reason: non_inventory_service` / `selected_location_id: null`）。`/api/routing/orders` / `/api/routing/update` / `/api/routing/reallocate` の全経路に適用。
* フラグの設定は **ops の明示操作のみ**（SKU や品名による自動判定はしない）。products ingest は本列を上書きしません。

> `serviceLines` は出荷指示（レスポンス / 保存 payload）レベルのフィールドです。per-location の WMS dispatch payload（[Dispatch Config](/lmile-docs/configuration/dispatch-config.md) テンプレート）には従来どおり引き当て済みの `lines` のみが渡ります。

## 2026-06-04 — v20: ルーティング引き当てを available + committed で判定

### 変更

* **自己予約レースの解消** — 受注ルーティングの引き当て可能数を `available_qty` のみから **`routable = available_qty + committed_qty`** に変更。Shopify の `available` は注文作成の瞬間に `committed` へ移って減るため、約10分後にルーティングが走る頃には `available=0` となり、その注文のために確保済みのユニットへ引き当てられず `no_stock` になっていた。`committed` を足し戻すことで物理確保分（reserved/damaged/safety を除く）へ正しく引き当てる。
* **在庫取込の拡張** — [Inventory Levels](/lmile-docs/ingestion-api/inventory-levels.md)（`POST /api/ingest/inventory-available`）が任意の `committed_qty` / `on_hand_qty` を **absolute** で受領（省略時は据え置き。`available` の absolute/delta・冪等・clamp は不変）。変更は `sot.inventory_update_logs` に `committed_set` / `on_hand_set` で記録。
* `sot.inventory_levels.committed_qty` 列を追加（`agent_read.inventory_levels` view にも露出）。判定根拠用に `sot.lm_routing_candidates.committed_qty_at_decision` を追加。

> `available` のみを送る取込経路（committed を持たない POS 等）は従来どおり `routable = available` で判定されます（committed 省略=据え置き=0）。

## 2026-06-03 — v19: 注文取消の内部状態 cascade

### 変更

* **Cancel の内部 SoT 同期** — `POST /api/routing/cancel`（[Cancel / Update](/lmile-docs/routing-api/cancel-update.md)）が、注文ヘッダ（`lm_routing_orders.status=cancelled`）と WMS への `cancel` dispatch に加えて、出荷元ヘッダ `lm_fulfillment_shipments` / 単位明細 `lm_fulfillment_units` を `status='cancelled'`（+ `cancelled_at`）に、出荷指示 `lm_shipping_instructions` を `delivery_status='cancelled'` に同期します。**`shipped`（出荷完了）は終端として保護**し上書きしません（追跡番号・ラベル PDF は温存）。
* レスポンスに cascade 件数（`cancelledShipments` / `cancelledUnits` / `shippingInstructionCancelled`）を追加。
* 集計 view `lm_v_routing_order_fulfillment`（`cancelled_count`）/ `lm_v_routing_order_unit_fulfillment`（`cancelled_unit_count`）に `cancelled` 分類を追加。

> 在庫数量（`inventory_levels`）は「状態のみ」方針のため変更しません。WMS への `cancel` dispatch 経路（[Dispatch Config](/lmile-docs/configuration/dispatch-config.md) の `action: "cancel"`）は従来どおりです。

## 2026-06-03 — v18: 出荷ステータス変動 webhook

### 新規

* **Fulfillment Status Webhook** — [Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md)（`POST /api/routing/fulfillment`）で出荷元（shipment）の `status` が**直前の値と変わったとき**（初回報告含む）に、`shop` 単位で登録した宛先へ POST で通知（[Fulfillment Status Webhook](/lmile-docs/webhooks/fulfillment-status.md)）。設定は `POST /api/routing/status-webhook-config`（`shop` 単位・`authSecret` は pgcrypto 暗号化・`payloadTemplate` 省略可）。
* **即時かつ軽量**: フルフィルメント報告の成功直後にバックグラウンド送信。注文レスポンスは遅延させない。ペイロードには `status` / `previousStatus` / `trackingNumber` / `carrierCode` / `externalOrderRef` 等を含む。
* `sot.lm_fulfillment_status_webhook_config`（送信設定・`UNIQUE (shop)`）/ `sot.lm_fulfillment_status_events`（status 遷移イベント outbox + 送信ログ）+ 読み取り view `lm_v_fulfillment_status_webhook_config`（secret 除外）/ `lm_v_fulfillment_status_events`。暗号鍵は Vault `lm_dispatch_enc_key` を共有。
* **耐久性**: 送信前にプロセスが落ちても `pending` / `failed` の event は outbox に残り、回収・再送できる。

## 2026-06-03 — v17: Ship\&Co 配送ラベル + 宛先住所修正・ラベル再発行

### 新規

* **Ship\&Co ラベルアダプタ** — [Dispatch Config](/lmile-docs/configuration/dispatch-config.md) の `action=label` に `adapterType=shipandco` を追加。Ship\&Co API（`https://api.shipandco.com/v1/shipments` / `x-access-token`）向けに、県名正規化・電話整形・市区町村の `address1` 前置・商品配列フィルタといった手続き的変換を行ってラベル発行し、`delivery.label`(URL) から PDF を取り込み（`shipping-labels` バケット）。`carrierId` / `fromAddress` 等は `payloadTemplate` に静的設定、API トークンは pgcrypto 暗号化（ソース直書きしない）。[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md) の確保済遷移で自動発行。
* **Shipment Address Recovery** — ラベル発行が宛先住所不備で失敗したケースのリカバリ（[Shipment Address Recovery](/lmile-docs/fulfillment-api/address-recovery.md)）。`POST /api/routing/shipment/address`（宛先住所の部分上書き + 国内必須住所検証 + 監査列更新）/ `POST /api/routing/shipment/retry-label`（失敗した出荷元のラベル再発行・二重発行ガード）。
* 宛先住所は `sot.lm_routing_orders.ship_to_*` を**単一ソース**として保持・更新（出荷ラベル生成もこの行から読む）。監査列 `ship_to_corrected_at` / `ship_to_corrected_by` を追加（PII 列同様に公開 view から除外）。

> 移植元（MFC の Ship\&Co 連携）には無かった住所修正・再発行の導線を inventory-os の fulfillment レイヤーに新設。代引き / 配達希望日時 / 刻印返送（Shopify 注文固有）は対象外。

## 2026-06-03 — v16: マーチャント単位の ingest API キー（shop スコープ）

### 新規

* **per-merchant API キー** — `x-ingest-secret` に発行済みの API キーを渡すと、そのキーに**ひも付いたストア（`shop`）にのみ** ingest / routing できます。1 キー = 複数 `shop` も可。ボディの `shop` がキーの範囲外の場合は `403 shop not authorized for this key`（[認証](/lmile-docs/getting-started/authentication.md)）。
* 既存のサーバー間連携（LastMile 運用の取込アプリ）はこれまでどおり動作します（admin global secret = `x-ingest-secret` の env 値はそのまま・後方互換）。

> キーの平文は発行時に一度だけ返されます（DB には sha256 ハッシュのみ保存）。発行・失効は <admin@lmile.io>。

## 2026-06-03 — v15: 出荷元変更（返送→別拠点出荷）

### 新規

* **Source Change** — 引当先（出荷元A）では加工できないため別の出荷元B へ返送してから出荷するケースの管理 `sot.lm_fulfillment_source_changes`（`change_requested` → `return_in_transit` → `return_received` + `cancelled`）。`POST /api/routing/change-source`（起票 + 前進の単一 advance）（[Source Change](/lmile-docs/oversell-api/source-change.md)）。
* **出荷元の切替** — 起票時に旧 decision を `superseded`・新 decision（出荷元=B）を `applied` にし、unit の 3 ロケーション列（引当 / 出荷元 / 現在在庫）を更新。旧出荷元A へ `cancel`、受領時に新出荷元B へ `create` を dispatch。最終出荷ラベルは B 受領後に既存 `/api/routing/secure` で生成。
* **返送便ラベル自動生成** — 起票時に A 拠点の `action=label` + `returnTag` 設定で返送便（A→B）ラベルを生成し追跡番号 + PDF を取り込み。送付先 B の住所はテンプレートに定義。`generateAndStoreLabel` に `pathKey` を追加し顧客出荷ラベルと衝突回避。
* `sot.lm_fulfillment_units.status` に `source_change_pending` / `source_change_in_transit` を追加。注文集計 view `lm_v_routing_order_unit_fulfillment` に `source_change_unit_count` + `source_changing` 分類を追加。読み取り view `lm_v_fulfillment_source_changes`。

> [Oversell / Reallocate](/lmile-docs/oversell-api/oversell-reallocate.md)（同一出荷元内の振替）や `in_transit_to_mfc`（出荷元は変えず現在在庫のみ移動）とは別経路。在庫は状態のみで `inventory_levels` は不変。

## 2026-06-03 — v14: 出荷元の合算在庫変動 webhook

### 新規

* **Source Inventory Webhook** — [出荷元](/lmile-docs/configuration/source-members.md)の member 在庫ロケーションが在庫取込で更新され、その出荷元の `barcode` 単位の合算 `available_qty`（= member の `available_qty` 合算）が**前回送信値と変わったとき**に、登録した宛先へ POST で通知（[Source Inventory Webhook](/lmile-docs/webhooks/source-inventory.md)）。設定は `POST /api/routing/source-webhook-config`（`(shop, fulfillment_source_location_id)` 単位・`authSecret` は pgcrypto 暗号化・`payloadTemplate` 省略可）。
* **即時かつ軽量**: 在庫取込（`/api/ingest/inventory-snapshot` / `/api/ingest/inventory-available`）の成功直後にバックグラウンド送信。取込レスポンスは遅延させない。送信は合算の**絶対値**（差分でない）。
* `sot.lm_fulfillment_source_webhook_config`（送信設定）/ `sot.lm_fulfillment_source_inventory_state`（前回送信した合算値 = dedup）/ `sot.lm_fulfillment_source_inventory_events`（変動イベント outbox + 送信ログ）+ 読み取り view `lm_v_fulfillment_source_webhook_config`（secret 除外）/ `lm_v_fulfillment_source_inventory_events`。

## 2026-06-03 — v13: ピッキングリスト生成（JSON / PDF 作業指示書）

### 新規

* **Picking List** — `POST /api/routing/picking-list`。ルーティング済み注文（`routingOrderId` または `sourceSystem + externalOrderRef`）から在庫ロケーション単位のピック内容を生成（[Picking List](/lmile-docs/fulfillment-api/picking-list.md)）。
  * `format=json` は構造化データ（商品名 / SKU / `imageUrl` / 数量、ロケーション別 + 引き当て不能）。
  * `format=pdf` は**出荷元ロケーション単位の作業指示書**（A4・IPAex ゴシック埋め込み・スキャン用 CODE128 バーコード・商品画像・1 点 1 行のピックチェック枠）。`locationId` 指定で単票を本体返却（`X-Picking-List-Url`）、省略時は全拠点分を生成し JSON で URL 一覧を返却。Storage bucket `picking-lists`（public read）。
* `sot.lm_picking_lists`（生成ログ・append-only）+ 公開 view `lm_v_picking_lists` + Storage bucket `picking-lists` を追加。`sot.products.primary_image_url` を商品画像に利用。

## 2026-06-03 — v12: 単位ステータス + 在庫確保 + 店舗→MFC移動 + 売越しケース

### 新規

* **Fulfillment Units** — `order_line_master` 方式の単位明細 `sot.lm_fulfillment_units`（1 行 = 1 単位・数量列なし）。`barcode` / `sku` / 引当ロケーション / 出荷元 / **現在在庫ロケーション**（店舗→MFC で更新）/ status / 在庫確保フラグ。ヘッダ `lm_fulfillment_shipments` にリンク（[Fulfillment Units](/lmile-docs/fulfillment-api/units.md)）。
* **在庫確保** — `POST /api/routing/secure`（単位ごとに確保。出荷元ヘッダの全単位確保で `secured` 遷移 + ラベル生成）。一部確保は `partially_secured`（`public.lm_v_routing_order_unit_fulfillment`）。在庫は状態のみで `inventory_levels` は不変。
* **店舗→MFC 移動** — `/api/routing/fulfillment` の `status: "in_transit_to_mfc"` に `targetMfcLocationId` を追加。単位の現在在庫ロケーションを MFC へ更新（状態遷移を単位へ cascade）。
* **Oversell Cases** — 売越しの 8 ステップ管理 `sot.lm_oversell_cases`（発生→探索→連絡→確保→出庫依頼→出庫→追跡番号→MFC受付完了 + `wont_do`）。`POST /api/routing/oversell-case`（起票 + 前進の単一 advance）。LM-498 の自動再引き当てとは独立共存（[Oversell Cases](/lmile-docs/oversell-api/cases.md)）。

> Shopify fulfillment order id 非依存（`routingOrderId` / `sourceSystem`+`externalOrderRef` / `barcode`+`lineInstanceNo` で特定）。追跡番号・ラベル PDF は梱包単位＝出荷元ヘッダに保持（単位に重複させない）。

## 2026-06-03 — v11: 出荷元の状態遷移 + 確保済ラベル生成

### 新規

* **Fulfillment** — `POST /api/routing/fulfillment`（出荷元 from-location 単位の状態遷移を報告。確保済→移動中→梱包→出荷完了 + 売越サブ状態）（[Fulfillment](/lmile-docs/fulfillment-api/fulfillment.md)）。
* **確保済ラベル生成** — `secured` / `oversell_secured` への遷移時に `action: "label"` 設定で送信先（キャリア API / 印刷 agent）へ POST し、応答から追跡番号 + ラベル PDF を取り込み。PDF は Supabase Storage `shipping-labels`（private）に保存。
* **Dispatch Config を label 対応** — `action` に `label` を追加し、応答マッピング `responseMapping`（`trackingNumber` / `carrierCode` / `labelPdfBase64` / `labelPdfUrl`）を登録可。
* `sot.lm_fulfillment_shipments`（出荷元単位の状態 + 追跡番号 + ラベル PDF パス）+ 読み取り view `lm_v_fulfillment_shipments` / 注文集計 view `lm_v_routing_order_fulfillment`。

## 2026-06-03 — v10: 受注ルーティングの取消・更新 + action別ディスパッチ

### 新規

* **Cancel / Update** — `POST /api/routing/cancel`（注文を `cancelled` にし `cancel` を dispatch）+ `POST /api/routing/update`（最新内容で再ルーティングし `update` を dispatch）（[Cancel / Update](/lmile-docs/routing-api/cancel-update.md)）。
* **Dispatch Config を action 対応** — 設定を `(shop, location, tag, action)` で保持。`action`(create/update/cancel) 別に宛先/テンプレートを登録可。dispatch は action 完全一致 + tag 一致優先で解決。
* `sot.lm_routing_orders.status` に `cancelled` 追加。`lm_location_dispatch_config` / `lm_location_dispatch_log` に `action` 列。

## 2026-06-03 — v9: routing tag + tag条件ディスパッチ + 配送先住所の詳細化

### 新規 / 変更

* **`/api/routing/orders` に `tag`（任意・単一）を追加** — ディスパッチ先(WMS)選択の条件。引き当て自体には影響しない。
* **Dispatch Config を tag 対応** — `(shop, location, tag)` で設定。注文 tag に一致する設定を優先、無ければ `tag=NULL` 既定（`POST /api/routing/dispatch-config` に `tag` 追加）。
* **配送先住所の詳細化** — `shipTo` に `name` / `company` / `phone` / `email` / `address1` / `address2` を追加（Shopify `MailingAddress` / ship\&co 準拠。全任意）。出荷指示・ディスパッチテンプレートの変数として利用可。
* **PII 是正** — 公開 view `lm_v_routing_orders` から詳細配送先（氏名/会社/電話/email/住所）を除外（service\_role 直アクセスのみ）。

## 2026-06-03 — v8: 出荷元↔ロケーション マッピング管理 API

### 新規

* **Source Members** — 出荷元↔在庫ロケーションのマッピングを API で管理（[Source Members](/lmile-docs/configuration/source-members.md)）:
  * `POST /api/routing/source-members` 設定（upsert。キー `shop + inventoryLocationId`、別出荷元への付け替え可、`isActive` で論理無効化）
  * `POST /api/routing/source-members/detach` 解除（物理削除）
  * `GET /api/routing/source-members?shop=...` 状況取得（ラベル付き一覧）

## 2026-06-03 — v7: 引き当て先ロケーションの明示指定

* `/api/routing/orders` に任意の **`inventoryLocationId`** を追加。指定時は出荷元の**その在庫ロケーションのみ**に引き当て（他メンバーへ振らない）。指定 location が出荷元にマッピングされていなければ `422 location_not_member_of_source`。

## 2026-06-02 — v6: per-location WMS ディスパッチ設定（テンプレート送信）

### 新規

* **Dispatch Config** `POST /api/routing/dispatch-config` — 在庫ロケーション単位で WMS 宛先 URL・認証・**ペイロードテンプレート**（`{{barcode}}`/`{{sku}}`/`{{quantity}}` 等の変数差し込み + `$each` 配列展開）を登録。`authSecret` は pgcrypto 暗号化保存（鍵 = Supabase Vault）。`sot.lm_location_dispatch_config` / `lm_location_dispatch_log` を追加（[Dispatch Config](/lmile-docs/configuration/dispatch-config.md)）。

### 変更

* 引き当て確定時の外部送信を **per-location 設定駆動**に変更。`/api/routing/orders`・`/api/routing/reallocate` のレスポンスは単一 `dispatch` → **`dispatches[]`**（ロケーションごとの送信結果）。旧 単一 env 宛先（`ROUTING_FULFILLMENT_URL`）は撤去。

## 2026-06-02 — v5: 出荷元(fulfillment source)モデル + 売越し・再引き当て

### 破壊的変更

* **`/api/routing/orders` に `fulfillmentSourceLocationId`（必須）を追加**。受注は出荷元ロケーションIDを必須で受け取り、その出荷元に紐づく在庫ロケーション（member）内だけで引き当てます。`ec_fulfillable` 横断のルーティングは廃止。

### 新規

* **出荷元 ↔ 在庫ロケーション 紐付け** `sot.lm_fulfillment_source_members`（1出荷元 : N在庫）。出荷元の販売可能在庫はメンバー在庫の合算。
* **Oversell / Reallocate** `POST /api/routing/oversell`（売越しフラグ）+ `POST /api/routing/reallocate`（同一出荷元の別メンバーへ再引き当て）。`lm_routing_decisions` に `fulfillment_source_location_id` / `oversold` / `superseded_by_decision_id` を追加（[Oversell / Reallocate](/lmile-docs/oversell-api/oversell-reallocate.md)）。

## 2026-06-02 — v4: Routing API を inventory-os に一本化

### 新規

* **Routing API** `POST /api/routing/orders` — cart-agnostic 受注ルーティング。出荷元拠点の判定 → canonical 出荷指示の生成 → 外部 fulfillment への dispatch を 1 リクエストで実行。`x-ingest-secret` 認証・`shop` はボディ（入力フィールドは camelCase）。
* 永続モデル追加: `sot.lm_routing_orders` / `lm_shipping_instructions`、および `lm_routing_decisions` の routing\_order 経路拡張（[Data Model](/lmile-docs/reference/data-model.md)）。

### アーキテクチャ変更

* routing 公開 API を **inventory-os（Hono）に一本化**。これにより取込（ingest）と受注ルーティングが同一サーバー・同一認証（`x-ingest-secret` / `shop` ボディ）に統一されました。

## 2026-06-02 — v3: Base URL を api.lmile.io に変更

* **Base URL が `https://api.lmile.io` に変更**（ingest 専用カスタムドメイン）。旧 `https://inventory-os.fly.dev` も当面エイリアスとして利用可能ですが、新規連携は `api.lmile.io` を使用してください。

## 2026-05-24 — v2: Products + Inventory API

### 新規

* **Products API** `POST /api/products/bulk-upsert` — 商品マスター一括登録・更新。価格変更ログ自動記録。
* **Inventory Levels API** `POST /api/inventory-levels/bulk-upsert` — 絶対値 + delta 両対応。欠品自動検知 (`stock_zero`)。
* **Inventory Daily Snapshots** — 日次 cron で全在庫を毎日スナップショット保存。

### 破壊的変更

* **External Signals API 廃止** — `POST /rest/v1/external_signals` (Supabase PostgREST 直接) は使用不可。
* **Pixel Events API 廃止** — `POST /api/pixel-events` は使用不可。
* **Shopify Webhooks 自動購読 廃止** — Webhook 依存から外部アプリ push モデルに移行。
* **DB スキーマ再構築** — `sot` / `agent_runtime` / `agent_read` / `public` の 4 スキーマに分離。旧テーブルは全て削除。

### アーキテクチャ変更

* 全データは外部アプリが API 経由で push する設計に統一。
* Base URL が `inventory-os.fly.dev` に統一（外部アプリ push モデル）。
* 認証が Supabase service\_role から `x-cron-secret` + `x-shop` ヘッダーに変更。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://lmile.gitbook.io/lmile-docs/resources/changelog.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
