# 通知設計書 69-Artifactsオーバーライド不正エラー

## 概要

本ドキュメントは、Julia の Artifacts モジュールにおいてアーティファクトオーバーライドファイル（`Overrides.toml`）に不正なエントリがある場合に出力されるエラー通知の設計を記述する。

### 本通知の処理概要

`load_overrides` 関数内で `Overrides.toml` ファイルを解析する際に、不正な形式のエントリ（無効な SHA1 ハッシュ、無効な UUID、パース不能なマッピング、不明なマッピング型など）が検出された場合にエラーレベルのログを出力する通知である。

**業務上の目的・背景**：Julia のアーティファクトシステムでは、`Overrides.toml` を使用してアーティファクトのインストール場所を上書きできる。このファイルに不正なエントリがあると、アーティファクトの解決が正しく行われず、パッケージのビルドや実行に影響を与える可能性がある。不正エントリを検出してエラーログで通知することにより、開発者は設定ミスを早期に発見し修正できる。

**通知の送信タイミング**：`load_overrides` 関数内で `Overrides.toml` を解析する際に、各エントリのバリデーション失敗時に発生する。具体的には以下の4つのケースがある:
1. マッピングのパースに失敗した場合（`parse_mapping` が `nothing` を返した場合）
2. 直接マッピングのキーが無効な SHA1 ハッシュの場合
3. Dict マッピングのキーが無効な UUID の場合
4. マッピングの型が String/SHA1 でも Dict でもない場合

**通知の受信者**：Julia パッケージ開発者またはアーティファクトの設定を行うユーザー。Julia のロギングフレームワークを通じて配信される。

**通知内容の概要**：`"Invalid override in '$(override_file)': ..."` 形式のメッセージで、問題のあるファイルパスとエントリの詳細が含まれる。

**期待されるアクション**：開発者は `Overrides.toml` ファイルの該当エントリを確認し、正しい形式（有効な SHA1 ハッシュ、UUID、絶対パス）に修正することが期待される。

## 通知種別

ログ（Error） - Julia 標準ロギングフレームワーク `@error` マクロによるログ出力

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（関数実行中に即座にログ出力） |
| 優先度 | 高（Error レベル） |
| リトライ | 無 |

### 送信先決定ロジック

Julia の標準ロギングフレームワークにより、現在アクティブなロガーにメッセージが配信される。

## 通知テンプレート

### メール通知の場合

該当なし（ログ出力のみ）

### 本文テンプレート

パターン1（パース失敗）:
```
Error: Invalid override in '<file>': failed to parse entry `<key>`
```

パターン2（無効な SHA1）:
```
Error: Invalid override in '<file>': Invalid SHA1 hash '<key>'
```

パターン3（無効な UUID）:
```
Error: Invalid override in '<file>': Invalid UUID '<key>'
```

パターン4（不明なマッピング型）:
```
Error: Invalid override in '<file>': unknown mapping type for '<key>': <type>
```

パターン5（parse_mapping 内 - 無効なエントリ値）:
```
Error: Invalid override in '<file>': entry '<name>' must map to an absolute path or SHA1 hash!
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| override_file | Overrides.toml ファイルのパス | `artifacts_dirs("Overrides.toml")` | Yes |
| k | エントリのキー（SHA1 ハッシュまたは UUID） | TOML ファイルのキー | Yes |
| name | アーティファクト名（parse_mapping 内） | TOML エントリの名前 | Yes |
| typeof(mapping) | マッピングの型名 | `typeof()` で取得 | 条件付き |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | `load_overrides()` 呼び出し | TOML エントリのパースまたはバリデーションに失敗した場合 | 不正なオーバーライドエントリの検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `ARTIFACT_OVERRIDES[]` が既にセットされており `force=false` | キャッシュが有効な場合はファイルを再読み込みしない |
| `Overrides.toml` が存在しない場合 | `!isfile(override_file)` ならスキップ |
| 全エントリが有効な場合 | 不正なエントリがなければエラーは出力されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[load_overrides 呼び出し] --> B{キャッシュ有効?}
    B -->|Yes| C[キャッシュ返却]
    B -->|No| D[artifacts_dirs で Overrides.toml パスを取得]
    D --> E[各ファイルをループ]
    E --> F{ファイル存在?}
    F -->|No| G[次のファイルへ]
    F -->|Yes| H[parse_toml でファイル読み込み]
    H --> I[各エントリをループ]
    I --> J[parse_mapping 実行]
    J --> K{mapping == nothing?}
    K -->|Yes| L["@error Invalid override: failed to parse"]
    K -->|No| M{mapping の型判定}
    M -->|String/SHA1| N[SHA1 キーのバリデーション]
    M -->|Dict| O[UUID キーのバリデーション]
    M -->|その他| P["@error unknown mapping type"]
    N --> Q{有効な SHA1?}
    Q -->|No| R["@error Invalid SHA1 hash"]
    Q -->|Yes| S[overrides_hash に追加]
    O --> T{有効な UUID?}
    T -->|No| U["@error Invalid UUID"]
    T -->|Yes| V[overrides_uuid に追加]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| Overrides.toml | アーティファクトオーバーライド設定の読み取り | 各デポの `artifacts/Overrides.toml` |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| ARTIFACT_OVERRIDES（メモリ内キャッシュ） | UPDATE | パース結果をキャッシュに保存（不正エントリはスキップ） |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| パース失敗 | `parse_mapping` が `nothing` を返した場合 | `@error` を出力し `continue` |
| 無効な SHA1 | `tryparse(SHA1, k)` が `nothing` の場合 | `@error` を出力し `continue` |
| 無効な UUID | `tryparse(UUID, k)` が `nothing` の場合 | `@error` を出力し `continue` |
| 不明なマッピング型 | マッピングが String/SHA1/Dict のいずれでもない場合 | `@error` を出力 |
| 不正なエントリ値 | `parse_mapping` 内で絶対パスでも SHA1 でもない場合 | `@error` を出力し `nothing` を返す |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（不正エントリはスキップされる） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

## セキュリティ考慮事項

`Overrides.toml` のファイルパスとエントリのキー（SHA1 ハッシュや UUID）がログに出力される。これらは一般に機密情報ではないが、カスタムパスが含まれる場合はログの取り扱いに注意が必要。

## 備考

- `load_overrides` はキャッシュ機構を持ち、`ARTIFACT_OVERRIDES` がセットされている場合は再読み込みを行わない（`force=true` で強制再読み込み可能）。
- 複数のデポに `Overrides.toml` が存在する場合、逆順（`reverse`）でループされ、後のデポの設定が優先される。
- `parse_mapping` 関数は再帰的に Dict 内のエントリも検証する。

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | `ARTIFACT_OVERRIDES` 定数（行111）。オーバーライドキャッシュ |
| 1-2 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | `parse_mapping` 関数（行76-89）。マッピング値のパース |

**読解のコツ**: `parse_mapping` は3つのメソッドを持つ多重ディスパッチ関数。`String` 版は絶対パスか SHA1 ハッシュかを判定し、`Dict` 版は再帰的に各値を検証する。フォールスルー版は `nothing` を返す。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | `load_overrides` 関数（行112-193）。**本通知の発生箇所（行80, 137, 146, 160, 180）** |

**主要処理フロー**:
1. **行113-115**: キャッシュチェック
2. **行124-125**: `overrides_uuid` と `overrides_hash` の初期化
3. **行127**: Overrides.toml パスリストの取得（逆順）
4. **行131**: TOML ファイルのパース
5. **行133-182**: 各エントリの処理
6. **行135-139**: `parse_mapping` とパース失敗チェック - **行137 で `@error`**
7. **行142-155**: String/SHA1 マッピング処理 - **行146 で無効 SHA1 の `@error`**
8. **行156-178**: Dict マッピング処理 - **行160 で無効 UUID の `@error`**
9. **行179-181**: 不明型処理 - **行180 で `@error`**
10. **行80**: `parse_mapping(String)` 内 - **不正値の `@error`**

### プログラム呼び出し階層図

```
load_overrides(; force=false)                      [Artifacts.jl:112]
    |
    +-- artifacts_dirs("Overrides.toml")            [Artifacts.jl:65]
    |
    +-- parse_toml(override_file)                   [Artifacts.jl:31]
    |
    +-- for (k, mapping) in depot_override_dict
            |
            +-- parse_mapping(mapping, k, file)     [Artifacts.jl:76]
            |       |
            |       +-- (String 版) SHA1/絶対パス検証 [Artifacts.jl:76-83]
            |       |       +-- @error "entry must map to..." [行80]
            |       |
            |       +-- (Dict 版) 再帰的検証          [Artifacts.jl:85-87]
            |       +-- (フォールスルー版) nothing      [Artifacts.jl:89]
            |
            +-- mapping == nothing?
            |       +-- @error "failed to parse entry" [行137]
            |
            +-- mapping 型判定
                    +-- String/SHA1: tryparse(SHA1, k)
                    |       +-- @error "Invalid SHA1 hash" [行146]
                    |
                    +-- Dict: tryparse(UUID, k)
                    |       +-- @error "Invalid UUID"       [行160]
                    |
                    +-- その他: @error "unknown mapping type" [行180]
```

### データフロー図

```
[入力]                          [処理]                              [出力]

Overrides.toml files   ------>  parse_toml              ------>  Dict
                                    |
                                    +-- parse_mapping    ------>  mapping or nothing
                                    |
                                    +-- バリデーション
                                            |
                                            +-- 失敗: @error  ---->  エラーログ (stderr)
                                            |                         continue
                                            +-- 成功          ---->  overrides_hash / overrides_uuid
                                                                      ARTIFACT_OVERRIDES キャッシュ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | ソース | `load_overrides` と `parse_mapping`。本通知の発生元（複数箇所） |
