zudo-slack-wisdom
GitHub リポジトリ

検索したい単語を入力

いつでも検索バーを開ける

スキーマの可変性 — 作成後に変えられるものと変えられないもの

作成後に select カラムのオプションが実質的に閉じてしまう理由と、その狭い例外

概要

「スキーマは作成時に固定され、API からは変更できない」という一括りの主張は、真実に近いが厳密には正しくない。この機微は、外部のステータスフィールドを写す select カラムを設計する人にとって重要だ:作成時にオプションを多めに用意しておくコストは安いが、あとから 1 つ増やすコストは安くない。

slackLists.update が受け取るのは 4 フィールドだけ

slackLists.update は既存リストのトップレベルの形を変更する唯一のメソッドであり、受け取るのはちょうど idnamedescription_blockstodo_mode だけだ。12 個の slackLists.* メソッドのどれも、カラムの型・名前・オプション集合を直接触ることはない。

オプションを追加・改名・削除するドキュメント化された経路は存在しない

書き込みはカラムの既存の定義に対して検証される:options.choices[] に存在しないオプション値を送ると invalid_option_id で失敗する(items.create 版の同じエラーは "Option ID provided does not match column definition" と読める)。セルの形 {column_id, select: string[]} には新しいオプションのラベルや色を運ぶ構造的な余地がない — 書き込み契約のどこにもオプションを 定義する 場所はなく、すでに存在するものを 選ぶ 場所しかない。

エラーレジストリに何が欠けているかが、これを補強する:ドキュメント化されたおよそ 50 個のリスト系エラーのどこにも option_id_to_create は存在しない一方で、行とカラムの作成に対応するもの(row_id_to_createcolumn_id_to_create)は両方とも存在する。この非対称性は、オプション集合が API に対して意図的に閉じられているという構造的な証拠だ — 行とカラムの作成には逃げ道が与えられたが、オプションの作成には与えられなかった。

唯一の本物の例外:todo_mode

todo_mode: true を指定した slackLists.update は、メソッド自身の使い方の散文によれば、既存の リストにタスク管理用のカラム — Completed(todo_completed)、Assignee(todo_assignee)、Due date(todo_due_date)— を追加させる。これは API サーフェス全体で唯一の、ドキュメント化された作成後のスキーマ追加だ。逆に言えば、todo_mode: false でリストを作った場合、この 3 カラムについては確定とみなして差し支えない。

column_id_to_create — 機能ではなく、ドキュメント化されていない裂け目

column_id_to_create の名が挙がるのは column_id_not_provided のエラー文字列("The column_id or column_id_to_create field must be provided")の中だけだ。どのメソッドのドキュメントページにも引数の定義はなく、動く例もなく、公式 3 SDK の型のいずれにも存在しない。

ドキュメント化されていない — 依存しないこと

column_id_to_create には実世界での使用例の確証がゼロであり(コード検索で見つかるのは同じエラー文字列のミラーばかりで、実際の呼び出し箇所は一度も出てこない)、実際の API による検証もどちらの方向にも存在しない。サポートされたカラム作成の経路ではなく、未実証のバリデータの残滓として扱うこと。本当に新しいカラムが必要なら、本番でこのフィールドを探るのではなく、後述の公認された copy_from_list_id による作り直しの回避策を使うこと。

人間は UI からスキーマを編集できる

ここまでの記述はすべて API サーフェスについてのものだ。編集アクセスを持つ人間は、Slack の UI からいつでも直接オプションの追加・削除やラベルの変更ができる — スキーマの不変性は「API に対して閉じている」のであって、「完全に閉じている」わけではない。

このことには運用上の直接的な帰結が 1 つある:キャッシュした valuelabel のマップは運用の途中で陳腐化しうる。削除されたオプションは、それまで成功していた書き込みに対して invalid_option_id を返し始める。一方でラベルの変更は安全だ、書き込みが指定するのは label ではなく value だからだ。予期しない invalid_option_id に遭遇したら、スキーマが変わらないことを前提としたハードコードの定数を信じるのではなく、items.info 経由で list_metadata.schema を読み直すこと。

ドリフトを能動的に検知する

invalid_option_id が起きてから反応するやり方でも機能はするが、それは書き込みがその特定のスラッグに当たるまでの間、ビジネス状態が誤ったオプションへ黙って再マップされたままになりかねないということでもある — 書き込み頻度の低いステータスカラムなら、この誤った前提を何日も引きずる可能性がある。より防御的なパターンは、ドリフトが書き込みに影響を与える前に検知することだ:

  1. 登録時に解決済みの契約をフィンガープリント化する。 書き込みが実際に依存している list_metadata.schema の部分 — カラムの id とその型、各 select カラムのフォーマット、そしてすべてのオプションの value / label / 色の三つ組 — を SHA-256 でハッシュ化し、その List を同期用に登録する際に list_id と一緒にそのフィンガープリントを永続化する。

  2. 同期サイクルごとに、書き込む前に再検証する。 items.info を呼び、最新の list_metadata.schema から同じフィンガープリントを再計算し、そのサイクルの書き込みが送信される 前に 永続化しておいた値と比較する — 書き込みが失敗したあとではなく。

  3. 不一致があれば必ず fail closed する。 その List の登録を unhealthy とマークし、そのリストへの同期を止め、オペレーターが対応できるよう bounded なエラーコードを永続化する。新しいスキーマに自動で適応しようとしてはならない:オプションのリネーム、カラムの型変更、オプション順序の変更は、ビジネス状態が意味するものを黙って再マップしてしまいかねず、「親切に」新しい形へ照合する同期ループは、人間のレビューを一度も経ないままその再マップをコミットしてしまう。ここでの fail-closed は、この節自身のエラーリファレンスが他のあらゆる恒久的な設定エラーに適用している方針をそのまま延長したものだ:自分の知らないところで変わってしまったスキーマは、リトライ(や自動適応)では直せない — 直せるのは人間、あるいは意図的な再デプロイだけだ。

デプロイに関して一文だけ触れておく価値のある機微がある:フィンガープリントの構成そのものが互換性のサーフェスになる。加算的なマイグレーションのウィンドウ中 — 登録するスキーマに新しいカラムを追加する Worker バージョンをロールアウトしている最中 — は、追加されたばかりのカラムをハッシュから除外してロールアウトが完了するまで待たない限り、既にデプロイ済みの Worker と新しくデプロイされた Worker は、同じリストに対して異なるフィンガープリントを計算してしまう。そうしないと、ロールアウトの途中で 2 つのバージョンが「正しい」スキーマについて食い違い、片方は実際には何も問題がないにもかかわらず、自分の視点からは予期せず異なって見えるスキーマに対して fail closed してしまう。

公認の回避策:copy_from_list_id による作り直し

「オプションをもう 1 つ増やしたい」に対するドキュメント化された API 経路は 新しいリスト だ:copy_from_list_idinclude_copied_list_records を指定した slackLists.create を使う。同じ呼び出しで copy_from_list_idschema の両方を渡すことはできず — その組み合わせは invalid_copy_and_schema_args で失敗する — したがって新しいリストはコピー元のスキーマの完全な複製として始まり、オプションの追加はそのあと UI から手作業でやるか、手で編集したコピー元リストからもう一度作り直すことになる。いずれにせよ、これは真新しい list_id とすべてのカラムの新しい column_id を発行するので、あらためて永続化し直す必要がある。

計算列は書き込めない

created_bylast_edited_bycreated_timelast_edited_time は Slack が計算するカラムであり、スキーマの状態にかかわらず書き込みを試みると常に uneditable_column を返す。

設計時に織り込むべき上限

slackLists.create のドキュメント化された制約より:

上限
select カラムあたりのオプション数100
セルあたりの選択値の数50
使用できるチップの色indigobluecyanpinkyellowgreengrayredpurpleorangebrown

実務上の帰結:作成時に多めに用意しておく

既存カラムのオプション集合を編集する API 経路が存在しない以上、実際に機能するパターンは リスト作成時にステータスのオプションを多めに用意しておく ことだ — 100 オプションの上限までの範囲で、まだ使わない予備のスラッグを焼き込んでおく。あとから本当に新しいオプションが必要になったら、人間が UI から手作業でリストを編集するか、上記の copy_from_list_id の回避策でリストを作り直すかのどちらかになる。

関連

この閉じたオプション集合が制約している書き込みの契約はリストアイテムへの書き込みselect カラムを参照。invalid_option_id をはじめ、このページの制約が生むエラーについてはエラーリファレンスを参照。

Revision History

作成更新