


root権限なしで動くコンテナツールを、ロックとダウンロードの確認つきで作る
root権限なしで動くコンテナツールを作る時に使う。変更中のコンテナにロックをかけ、ダウンロードしたイメージのレイヤーを全部確かめ、ホストの設定をコンテナへ持ち込まず、プロセスツリーごと止め、バックアップの復元で危ないパスをはじく。
このAIルールを使うには
## 中心部分を標準ライブラリだけで作り、モバイルのホストを見分ける
コアランタイムにサードパーティの依存関係を持たせず、システム情報の照会、ダウンロード、アーカイブ処理、プラットフォームの検査には、外部コマンドより言語標準の機能を優先します。
### 依存関係の方針
- ターミナル機能の確認、ユーザーとグループのデータ、バイナリ検査、アーキテクチャ判定、HTTP、アーカイブには標準ライブラリを使います。
- 実際の隔離に必要なコンテナランタイムだけを実行します。
- 対応ホストにそのランタイムがない場合は、対話型ターミナル上で、ユーザーが同意した後に限りインストールを提案します。
- 適切な場合はシェルを一層挟まず、現在のプロセスを置き換えてランタイムを実行します。
- パッケージマニフェストをバージョンの正本とし、未インストールのソースツリー向けに文書化された代替手段を用意します。
- すべてのコマンド別名とコンソールエントリーポイントを、一つの正規`main`関数へ振り分けます。
### プラットフォーム判定
- OS上の証拠、専用環境変数、アクセス可能なプラットフォームプレフィックスという独立した信号のうち、少なくとも二つが一致した場合にだけ特殊なモバイルホストと判定します。
- 結果は一度だけ計算し、パス、既定の環境、利用可能なフラグ、バインド、ランタイム拡張へ一貫して使います。
- 通常のホストにはモバイル固有のバインドを加えず、標準のベースディレクトリ規約を既定として使います。
## コンテナをフォルダ名で見分け、特殊なゲストを分けて扱う
ディレクトリによる識別、メタデータの有無、旧形式からの移行、ゲストの挙動を別々の判断として扱います。
### ストレージモデル
- 検証済みのディレクトリ名を唯一のコンテナ識別子として使います。
- 組み立て済みファイルシステムをそのディレクトリ配下へ保存し、イメージのメタデータは別のマニフェストに保持します。
- レジストリイメージがない場合は、通常のアーカイブからのインストールでイメージのメタデータを省略できるようにします。
- 新しい構造が必要になる最初の操作で旧レイアウトを移行し、その影響を受ける互換リンクを書き換えます。
- ランタイム、キャッシュ、コンテナ、セッション、レイヤー、マニフェストの場所は、プラットフォーム対応の一つのパスモジュールから導出します。
- イメージから導出した別名やアーカイブから読んだ名前を含め、すべてのエントリーポイントでコンテナ名を検証します。
### ゲストの分類
- 特殊なゲストは、パスが存在するだけではなくファイルでなければならないセンチネルで判定します。並行セッションがバインド先をディレクトリとして実体化する場合があるためです。
- 特殊なゲストには、専用のホーム、実行パス、プレフィックス、一時ディレクトリの基本設定を与えます。
- 独自環境を備えるゲストへ、ホストアプリケーションのプライベートディレクトリやインストール先プレフィックスを絶対に上書きバインドしません。
- そのゲスト種別では、互換性のないリンク変換と識別情報を変更するオプションを無効にします。
- 任意のホストシステムのバインドは、隔離モードと最小モード以外でのみ適用します。
- 共有プレフィックスによってホストのバイナリがゲストのバイナリを覆い隠す場合は、異なるアーキテクチャの特殊ゲストを拒否します。
## コマンドを正しく振り分け、ロックと一時ファイルで書き込みを守る
コマンド解析とロックの所有権は、中断、再入、プロセス置換、デタッチ、キャッシュの並行操作のすべてで正しく保たれなければなりません。
### CLIの流れ
1. 進捗表示と不完全なファイルを一貫して片づけられるよう、補助的な終了シグナルを通常の中断処理経路へ割り当てます。
2. 高い権限での実行を警告しつつ警告自体は致命的にせず、コンテナランタイムの入れ子の呼び出しは拒否します。
3. ランタイムが必要なコマンドでだけ検査し、確認、プロセス、イメージ専用コマンドにはより限定的な条件を定義します。
4. 位置引数の検証前にコマンドヘルプを処理し、通常の解析より前に不明なコマンドを拒否します。
5. 内部プログラムを起動するコマンドでは、リテラルのオプション区切りより後ろの引数列を保持します。
6. 入力モードが意図的に要件を決める場合を除き、必須引数を中央で強制します。
7. コマンド固有の意味を保ちつつディスパッチ前に全体のquietモードを適用し、エラーと警告は常に表示します。
### ロックとアトミック性
- 読み取り中心のセッションとバックアップには共有ロックを、インストール、取り外し、名前変更、リセット、復元、書き込み先への書き込みには排他ロックを使います。
- 複数のコンテナロックはパス順に並べて取得します。
- ビルドロックは出力イメージとアーキテクチャでキー化し、共有キャッシュインデックスは専用ロックで保護します。
- 同じコンテナに対する別の変更コマンドを呼ぶコマンドでは、排他ロックを再入可能にします。
- セッションロックをプロセス置換後も存続させ、デタッチされた子孫が所有権を継承した場合は、unlockせずにdisownします。
- ロックが競合したら直ちに失敗させ、特定できる場合は保持元を報告します。
- すべてのキャッシュとセンチネルの書き込み処理は、一時ファイルの作成、アトミックな置換、全例外時の後片づけを必ず使います。
## ダウンロードしたイメージのレイヤーを確かめ、レジストリの認証情報を守る
レジストリ参照、認証、リダイレクト、ダイジェスト、レイヤー、アーカイブメンバーは、検証が終わるまで敵対的な入力として扱います。
### 取得とキャッシュ
- 完全に検証されたキャッシュをオフライン利用で優先し、レイヤーだけが不足している場合は不足分だけを取得します。
- ダウンロードしたすべてのレイヤーをストリームハッシュし、昇格前にダイジェストを照合します。
- 細工された参照がキャッシュルート外へ出られないよう、ダイジェストをファイルシステムのパスへ変換する前に構文を検証します。
- アーカイブ実装が安全に展開できない圧縮形式は拒否します。
- 不透明whiteoutと項目単位のwhiteoutを実装し、ハードリンク先を検査して、メンバー名によるパストラバーサルを拒否します。
### 認証と送信
- トークンサービスでBasic認証情報を扱う前に、ユーザー名とパスワードが明示された形式であることを要求します。
- 異なるホストへのリダイレクトではAuthorizationヘッダーを取り除きます。
- 取得したトークンの範囲を、要求されたpullまたはpushの操作に限定します。
- push前に保存済みの設定を正規化し、そのダイジェストをマニフェストと照合します。
- リモートblobを検査し、不足している内容だけをアップロードします。
- 未対応のアップロードモードとマルチアーキテクチャインデックスは近似実装せず、対象外に保ちます。
- 認証情報を露出させず、認可失敗をアクセス許可エラーとして示します。
## ゲストのアーキテクチャを正しく伝え、子プロセスの環境を一から作る
アーキテクチャの報告と子プロセス環境は、ホストを意図せず継承するのではなく、ゲストを表さなければなりません。
### アーキテクチャ
- 既知の実行ファイルにあるバイナリヘッダーから、インストール済みゲストのアーキテクチャを判定します。
- ネイティブ名、レジストリ名、プラットフォームプレフィックス付きアーキテクチャ名を一つの対応表で正規化します。
- ネイティブ実行が使えない場合にだけエミュレーターを選び、そのローダーが必要とするシステムパスだけをバインドします。
- ホストの値を複製せず、ゲストのアーキテクチャとエミュレートしたカーネル識別情報を報告します。
### 子プロセスの環境
- 空の対応表から子プロセス環境を構築し、プロセス置換へ直接渡します。
- 基本設定、フィルタ済みのイメージ変数、許可されたホスト変数、ユーザー指定、識別情報の変数、ターミナル変数の順で、明示的に優先順位を適用します。
- イメージ変数とユーザー変数はすべてのモードで適用し、モバイルホスト変数は通常の非隔離モードだけに限定します。
- 最小モードでは、明示的に必要な場合を除き、基本設定のパス、ホスト統合変数、ユーザー識別情報を省きます。
- ログインプロファイルへ書き込む前に変数名を検証し、値を安全に引用処理します。
- セッション単位、ランタイム内部、ローダー、識別情報の変数は永続プロファイルの対象外にします。
- 実行前にローダーのpreload変数を取り除き、並行セッション間で共有互換ディレクトリを安定させます。
## コンテナを裏で動かし、プロセスツリーごと止める
実行、デタッチ、停止、ビルドの操作では、マニフェストの挙動、ロックの存続期間、移植性、プロセスの所有権を保たなければなりません。
### 実行とデタッチ
- コンテナイメージの規則に従って、イメージのエントリーポイントとコマンドの値を組み合わせます。
- 明示された作業ディレクトリの上書き指定を尊重し、それ以外ではイメージの設定またはファイルシステムのルートを使います。
- デタッチの分岐へ入る前にコマンド確認モードを解決します。
- 二重forkと新しいセッションでデタッチし、標準ストリームをリダイレクトして、最終ランタイムプロセスを孫プロセスで登録します。
- 最終プロセス識別子をフォアグラウンドへ伝達し、継承されたコンテナロックはデタッチした子孫が保持したままにします。
### 安全な停止とビルド
- 停止対象は稼働中セッションのレジストリからだけ解決します。
- ルートのランタイムプロセスだけでなく、子孫ツリー全体を停止します。
- 循環に強い親子関係表を構築し、現在のプロセスやシステム上重要なプロセス識別子には絶対にシグナルを送らず、ツリーをたどる前にルートの実行ファイルを検証します。
- 既定では穏当な終了シグナルを使い、明示的な名前または番号による上書きを許可します。
- 実行前にビルド段階とグローバル引数を解析し、対象を早期検証して、メタデータ、実行、copy、addの操作を専用処理関数へ振り分けます。
- here-documentが入力を供給する場合を除き、ビルド工程を隔離された非対話モードで実行します。
- ビルドキャッシュの項目は親状態、命令、関連する追加入力でキー化し、キャッシュインデックスの更新をロックします。
- 移植可能なレイヤーのsnapshotからランタイム互換メタデータを除外しつつ、参照先ファイルの内容は保持します。
## コンテナのバックアップと復元で、危ないアーカイブの項目をはじく
アーカイブとターミナル出力は信頼境界をまたぐため、コンテナの状態や対話型プロンプトを壊してはなりません。
### バックアップと復元
- 各コンテナを一つのアーカイブルート配下に置き、任意のメタデータとファイルシステムツリーを格納します。
- 読み取れないサブツリーをバックアップ可能にし、デバイスと通信エンドポイントを除外して、所有者メタデータを正規化します。
- 明示的な出力先がない限り、対話型ターミナルへのバイナリアーカイブ出力を拒否します。
- ストリーム入力を含め、アーカイブデータと標準形式から圧縮方式を判定します。
- 旧アーカイブ形式を現在のコンテナ構造へ付け替えます。
- 空、現在のディレクトリ、親ディレクトリ、無効なコンテナ名のメンバーを拒否します。
- そのコンテナで最初の有効なメンバーを復元できる状態になった時だけ、書き込み先のロックを取得して既存ファイルシステムの中身を空にします。
### ターミナルとコマンドの統合
- 同時に動くパスワードプロンプトまたは全画面プロンプトがターミナルのechoやcanonicalモードを占有している間は、情報表示用のターミナル書き込みを抑止します。
- ヘルプ内容をデータとして保持し、文書化された幅の範囲内で表示幅に応じて描画します。
- 新しいコマンドはすべて、ディスパッチ、解析メタデータ、必須引数、ヘルプデータ、別名対応表へ登録します。
- 新しいソースファイルには、パッケージのライセンスヘッダーと命名規則を保ちます。
