notes mizzy.org

信頼境界を越えるデータは境界で再検証する

AI由来 出典: explorations/2026-06-10-carina-type-system-type-theory/plan-as-compilation.md §6 作成

「一度検査したのだから、あとは信用してよい」は、データが同じ信頼領域に留まっている間だけ成り立つ。別の場所・別の時刻・別のバージョンに対して作られたデータが入ってくる点では、検査済みという前提そのものを疑い直す必要がある。コンパイラの世界はこの問題に段階的な解を積み上げてきた。

戦略は四段階に整理できる。

検査の強さ (a)検査しない C / ELFリンカの再配置 型なしの操作 無音の破壊 (b)識別子に型を C++の名前マングリング RustのSVH リンクエラーに変換 (c)境界で再検証 JVMバイトコード検証器 WASMインスタンス化時検証 IaCの正しい解 (d)最後まで型を Typed Assembly Language 型付きIRリンク(LTO) 変換後も再検査可能 (c)が検査を置き、(d)の精神が検査を外せなくする — 併用が修正の完成形である。 篩の述語は値依存なので、値が到着した時点で走らせる以外にない。
四段階は排他ではない。IaCの再配置点では(c)が正しい解であり、(d)から取り込めるのは「検査を飛ばした代入を型レベルで書けなくする」という構造の方である。

(a)検査しない。 古典的なC/ELFリンカの再配置は型なしの操作で、翻訳単位間で宣言が食い違っても黙ってリンクが成功し、実行時に静かに壊れる(Cの有名な未定義動作の一族)。

(b)識別子に型を運ばせる。 C++の名前マングリングはシンボル名に型を焼き込み、不一致を「無音の破壊」から「リンクエラー」に変換する。RustのSVHも同系で、保存planのlineage / serial照合はこの戦略の粗粒度版に当たる。

(c)境界で再検証する。 JVMのバイトコード検証器が代表で、クラスロード(動的リンクに相当)のたびに「コンパイル時に検査済みだったはず」を信用せず型整合を再検査する。理由は信頼境界 — クラスファイルは別の場所・別の時刻・別のバージョンに対して作られたかもしれない — であり、WebAssemblyのインスタンス化時検証、proof-carrying codeも同じ形。JVMが示した経験則は「検証は付いている型の整合確認なのでコンパイルよりずっと安く、毎回やって割に合う」。

(d)最後まで型を持ち続ける。 Typed Assembly Languageや型付きIRリンク(LTO)のように、最下層の表現にも型を運び、あらゆる変換の後で再検査可能にする。

IaCの再配置点に当てはめると(c)が正しい解である。代入される値の出所は上流stateとプロバイダ応答 — このplanの検査器が自分で検査していない、外から来るデータ — であり、JVMがクラスローダに検証器を置いたのと同じ理由で、代入点が検証を置く正しい場所になる。コストの経験則も同じ方向に倒れる(所属検査は既にある述語の適用だけで、クラウドAPI呼び出しに比べれば誤差)。

なお(d)を「実行時検査なし」の意味で取ることは原理的にできない。篩の述語は値依存で、値は動的段階に初めて生まれるため、値が到着した時点で述語を走らせる以外にない。(d)から取り込めるのは構造の方である。deferredの穴に期待型を持たせ、穴を埋める唯一のAPIが「その型の検証器だけが生成できる検証済み値」を要求するようにすれば、検査を飛ばした代入が実装言語の型レベルで書けなくなる。つまり(c)が検査を置き、(d)の精神が検査を外せなくする、という併用が修正の完成形である。

根拠の確度

JVM検証器・WebAssembly検証・proof-carrying code・Typed Assembly Language・名前マングリング・SVHへの言及はAIの学習データ由来で、一次ソース未確認。

#型システム #信頼境界 #設計原則