# Proof Finder API/MCP契約

更新日: 2026-05-13

## 1. 共通ルール

- サーバーはクライアントから渡された件数、根拠レベル、金額合計を信用しない。
- メール本文、Slack原文、チャンネル名、ワークスペース名、添付、スクショ原本、注文番号、予約番号、座席番号は保存しない。
- 公開レスポンスは redacted データだけを返す。
- ユーザーは証拠を追加できない。除外、除外解除、再スキャンだけ許可する。
- `self_submitted` は公開レジュメ発行不可。
- `agent_collected_metadata` はAIエージェントが接続済みデータソースから取得したメタデータ。
- `sealed_app_batch` は高信頼、`provider_verified` は将来対応。
- 公開ページは完全な実在証明ではなく、取得経路つきの活動レジュメとして表示する。
- 直近だけで活動レジュメ化しない。職務経歴書は全経歴が対象なので、AIエージェント側には接続ソースの最古履歴から現在までの検索を求める。API上限がある場合だけ年次・複数年ウィンドウへ分割する。
- 職務経歴/ポートフォリオ用途を主対象にする。レジュメ種類を固定リストから選ばせず、AIエージェントがメール、Slack/プロジェクト管理、文書、PR/コード履歴から作った短い要約ラベルとメタデータから、最適なレジュメタイトルを動的に推定する。
- Web制作、開発、PM、イラスト、提案/請求などは内部シグナルとして扱うが、公開候補のカテゴリは `ai_inferred_activity` を基本にする。
- 送信履歴を重視する。送信済みの納品、修正、実装、公開、提案、見積、注文書、発注書、請求、請求書送付、議事録、レビュー依頼、ラフ提出、資料提出、業務報告、改善案、完成データ送付は活動シグナルとして扱う。送信済み見積書/提案書は開始・範囲の候補証拠だが、それだけでは受注済み案件として公開しない。注文書/発注書/契約書/承認返信は開始境界、納品書/請求書/公開報告は完了・クローズ証拠として扱う。承認待ち、受注未定、開始前、未開始、着手前は開始境界にも終了境界にも使わない。
- プロジェクト終了日は、`period_to` が根拠付きである、`period_status=ongoing`、`period_status=unknown` の3状態で扱う。`last_seen` は接続済み証拠の最終確認日であり、終了日の代用にしない。
- `period_to` は請求/クローズ、検収/承認、納品書、公開/リリースなど終了根拠がある場合だけ採用する。注文書、発注書、契約書、承認返信、`accepted_start` は開始境界であり終了根拠にしない。承認待ち、受注未定、開始前、未開始、着手前は開始境界にも終了境界にも使わない。「完了しました」「納品」「提出」「テスト環境アップ」「デモ環境」「確認依頼」「公開前確認」だけでは終了にせず、`no_invoice` / `no_launch` / `no_delivery` / 未確認 / なし / 公開前 / 確認中など否定・未確定の終了語も終了扱いにしない。レビュー中/公開前/進行中/次回対応/引き続き等の流れがあれば `ongoing`、終了根拠が弱い場合は `unknown` にする。
- 同じ会社やグループの中でも、成果物ごとにライフサイクルが違う場合は分割する。例: グループサイトは公開済み、学校サイトは継続中なら、別 `project_key` または `parent_child` 関係として扱い、`merge_split_notes` と `period_end_basis` に根拠を残す。
- AIエージェントは `get_started` の後に `get_analysis_harness` を呼び、接続ソース棚卸し、解析対象ソース選択、ソース別取得クエリ設計、長期検索、本文/ログ読解前のノイズ除外、ソース別深掘り、メール/Slack/文書の証拠単位分解、名称・別名解決、プロジェクト候補グラフ解決、時系列復元、本文/文書/Slack読解、証拠ロール網羅表、複合ソース照合、証拠ロール分類、会社/URL探索、成果物/キャプチャ候補整理、メール/Slack例外処理、過剰結合・過剰分割監査、公開安全フィルタ、整合性チェック、職務経歴書項目完全性監査、職務経歴書本文品質パス、records品質レポート、カバレッジ不足点レポート、全履歴カバレッジ補完試行、抽象パターン学習フィードバックを終えてから `analyze_evidence_metadata` を呼ぶ。現在の依頼に公開URL/URL公開/公開までの意図がある場合は `publication_intent=publish_url_requested` とし、未解消gapを記録して証明レベルに反映しつつ、追加ドラフト確認で止めず `publish_certificate` へ進む。
- 複数ソース統合では、`project_source_anchor_map` を先に作り、URL/ドメイン/パス、サービス/サイト/プロダクト名、成果物名、会社+時期、ソース内スレッド文脈、弱い件名/チャンネルヒントの順で照合する。`boundary_evidence_by_project` は開始、受注、終了、完了、公開の判断に使う境界証拠、`context_evidence_by_project` は要件、レビュー、意思決定、進行状況、担当範囲の文脈補強として分ける。Slack/プロジェクト管理ログだけで `period_to` や受注/完了を確定しない。境界証拠が不足する場合は `integration_backfill_queries` を作り、Gmail/メール、請求/見積、文書、公開URLを追加検索する。
- `source_noise_filter` では `source_noise_filter_policy.source_matrix` を使い、各ソースで実際に取れるメタデータだけで本文/ログ読解前に除外する。Gmail/メールは件名、送受信方向、送信元/宛先、ラベル、List-Unsubscribe、Slack/チャットはsubtype、bot user、reaction、thread、Drive/文書はmime、owner、folder、GitHubはevent、merge状態、file summary、Notionはstatus/relation、Figmaはdiscovered file metadata、制作プラグイン成果物はrender/export metadata、Calendarはrecurrence/attendee、請求会計はdocument role/status、generic MCP/pluginはadapter hintを使う。受信側のスパム、メルマガ、ニュースレター、広告/プロモーション、SNS通知、自動通知、アカウント/セキュリティ通知、配送追跡、セミナー/イベント参加通知、購入/予約/領収書のみ、求人/面接連絡、Slack bot通知、リアクション、雑談、CI通知、定例リマインド、Drive template/export/backup、GitHub CI/lockfile-only、Notion personal note、Figma sandbox/design-system-only、制作プラグインのdraft/raw素材、個人予定、経理/税務/支出管理、generic MCP test/sampleを、強い職務アンカーがなければ除外する。サブスク、継続課金、月額/年額、自動更新、recurring/renewal 系の受信請求書・領収書は、制作アンカーがなければ `subscription_billing` として除外する。送信済みメールはこの段階で捨てない。除外したメール本文、Slack原文、件名詳細は送らず、`source_noise_profile` / `prefilter_decision` / `noise_confidence` / `deep_read_gate` と、`skipped_noise_count` / `noise_categories` / `token_savings_notes` だけをカバレッジに残す。
- `record_filter_learning` は、除外/強証跡の抽象パターンだけを保存する。v3では学習を事例集にせず、`learning_layer=universal` と `learning_layer=source_specific` を分け、複数例を `pattern_family` + `compact_signature` + `compact_rule` へ圧縮する。受け取れるのは `outcome`、`learning_layer`、`source_kind`、`source_object_type`、`pattern_family`、方向、source_type、sender/recipient category、document_type、evidence_role、phase_hint、keyword_family、has_project_anchor、has_work_url、confidence だけで、件名、本文、メールアドレス、URL、会社名、プロジェクト名、個人名、請求番号、注文番号、文書ID、制作プラグイン成果物のraw asset URLやraw captionは拒否する。広すぎるsignature、会社名・日付・番号・ドメインを含む具体的すぎるsignature、1回限りの事例は候補にも昇格させない。汎用除外パターンは `subscription_billing` / `account_security_notification` / `delivery_tracking_noise` / `event_registration_noise`、汎用強証跡は `sent_estimate_start` / `sent_order_start` / `sent_proposal_start` / `sent_contract_start` / `sent_invoice_completion` / `sent_delivery_completion` / `sent_launch_report_completion`、ソース固有パターンは `github_pr_implementation_evidence` / `figma_design_artifact_evidence` / `plugin_motion_artifact_evidence` / `plugin_artifact_publication_evidence` / `drive_delivery_artifact_evidence` / `notion_decision_context_evidence` などの抽象familyだけを許可する。
- Figma由来の `source_file_last_modified_at` / `source_file_last_touched_at` / `source_version_created_at` / `source_metadata_status` / `source_version_history_status` は、発見済みFigmaリンクから取得できた場合だけ受け取る。raw file key、node ID、private URL、private file/frame名は拒否し、日付は存在・工程の文脈証拠としてのみ扱う。
- GitHub/code host由来の `first_contribution_at` / `last_contribution_at` / `contribution_kind` / `contribution_count` / `commit_count` / `merged_pr_count` / `review_count` / `release_count` / `repository_scope` / `repository_visibility` / `language_stats_summary` / `verified_commit_status` / `skill_evidence_matrix` / `tool_evidence_matrix` / `experience_signal_type` / `skill_inference_basis` / `skill_evidence_confidence` は、scope済みrepoから取得できた場合だけ受け取る。private repo名、private repo URL、raw commit hash、PR/issue ID、branch名は拒否し、`github_repo_key_hash` / `github_pr_key_hash` / `github_issue_key_hash` / `github_commit_key_hash` / `github_release_key_hash` に変換する。repository language alone、stars、forks、watch、raw contribution countは弱い証拠であり、経験年数は `skill_evidence_confidence=high/medium` の場合だけ表示する。
- 制作プラグイン成果物由来の `plugin_name` / `plugin_capability` / `composition_file_hash` / `artifact_key_hash` / `artifact_url_host` / `public_artifact_url_candidates` / `artifact_created_at` / `artifact_modified_at` / `thumbnail_status` / `render_job_status` / `export_status` / `artifact_metadata_status` は、接続済みソースまたは公開成果物ホストから取得できた場合だけ受け取る。private project ID、raw asset URL、storage URL、private/unlisted artifact URL、raw captions/transcripts、private file nameは拒否し、非公開情報は `artifact key hashes` または `non_public_anchor_fingerprints` に変換する。制作プラグイン成果物ソース単独では受注、完了、`period_from`、`period_to` を確定しない。
- 実績URLは接続済みソースの本文要約またはメタデータから確認できる公開 `https` URLだけを採用する。ユーザー貼り付けURL、`http`、ローカル/社内/プライベートホスト、クエリ/フラグメント付きURLは公開根拠にしない。
- 採用した実績URLは、AIエージェント側が公開URLを開ける場合に小さな `work_url_captures[].screenshot_data_url` として渡す。サーバーは外部ページを開かず、最大8件まで保存する。キャプチャは実績ページの文脈表示であり、URL所有権の証明ではない。キャプチャできない場合でも `capture_status=capture_failed|capture_unavailable|capture_not_supported|capture_attempted_no_image` を渡し、公開URL発行フローは追加確認で止めない。

## 1.1 現在の実装状態

本番の `xserver/api/index.php` と、ローカル参照実装の `server.mjs` で実装済み:

- `GET /healthz`
- `GET /api/healthz`
- `POST /api/public/analyze`
- `POST /api/certificate-preview`
- `GET /api/me/certificates`
- `POST /api/certificates`
- `GET /api/certificates/{publicId}`
- `GET /api/mcp`
- `POST /api/mcp` の `initialize` / `prompts/list` / `prompts/get` / `tools/list` / `tools/call`
  - `record_filter_learning`
- `GET /.well-known/oauth-protected-resource`
- `GET /.well-known/oauth-authorization-server`
- `POST /oauth/register`
- `GET /oauth/authorize`
- `POST /oauth/token`
- 保存/発行系の401境界
- MVP用デモOAuth。Authorization Code + PKCEでBearerを発行する。`tools/list` には `publish_certificate` を常に表示し、未認証で呼ばれた場合は401 + OAuthチャレンジを返す
- 本番ログイン前のため、REST確認用に `x-proof-demo-user` によるデモログイン境界も残す
- 接続済みソース内URLの正規化、AIエージェント側キャプチャの保存、公開レジュメページでの表示
- 解析手順を固定するMCP `get_analysis_harness`
- URL-only入口向けに、`initialize.instructions` と `prompts/get` の `start_resume_generation` で接続後の初回案内を返す

未実装:

- 本番OAuth同意UI
- 実署名検証つき `sealed_app_batch`
- 本番ユーザー向けの発行確認UI

## 2. Public REST API

### `POST /api/public/analyze`

ログイン不要。永続保存しない。MCP/AIエージェント経由の活動レジュメ候補分析用。Webフォーム、CSV、手入力の入口としては使わない。

Request:

```json
{
  "source": "mcp_agent_metadata",
  "records": [
    {
      "date": "2026-02-11",
      "direction": "sent",
      "sender": "me@example.com",
      "recipient": "client.example",
      "subject": "LPコーディング完了版を納品しました",
      "source_type": "gmail",
      "source_message_key": "msg_anon_001",
      "source_thread_key": "thread_anon_001",
      "source_channel_key": "",
      "channel_category": "",
      "author_role": "self",
      "work_item_key": "work_item_001",
      "query_family": "web_build",
      "date_window": "2026-01..2026-03",
      "evidence_role": "delivery",
      "relationship_type": "same_project",
      "relationship_notes": "同じ公開URL、成果物、納品フェーズに基づき同一プロジェクトとして扱う",
      "content_summary": "LPコーディング初稿を取引先へ納品した",
      "project_name": "LPリニューアル制作プロジェクト",
      "project_key": "lp-renewal-client-a",
      "client_label": "クライアント/企業",
      "project_overview": "本文解析からLP制作の依頼、実装、納品を同一プロジェクトとして整理",
      "body_evidence_summary": "本文でLPコーディング完了版の納品と公開前確認依頼が示されている",
      "client_request_summary": "レスポンシブ対応と公開前確認",
      "response_summary": "HTML/CSS実装済みの成果物を納品",
      "decision_summary": "公開前確認へ進行",
      "deliverable_summary": "LPデザインとHTML/CSSコーディング",
      "artifact_summary": "LPデザインとHTML/CSS実装一式",
      "role_summary": "制作、納品、確認依頼を担当",
      "outcome_summary": "公開前確認まで進行",
      "project_phase": "納品",
      "period_from": "2026-01",
      "period_status": "ongoing",
      "period_end_basis": "公開前確認へ進行しており、終了根拠はまだない",
      "confidence": "high",
      "url_search_status": "found_public_url",
      "activity_label": "納品",
      "tags": ["Web制作", "コーディング", "納品"],
      "work_url": "https://example.com/work/lp"
    }
  ],
  "options": {
    "locale": "ja-JP"
  }
}
```

Validation:

- `records` は1-5000件
- `subject` は最大500文字
- `sender` / `recipient` はメールアドレスまたはドメイン文字列。公開保存時はカテゴリ化し、個別メールアドレスは出さない
- `direction` は `sent` / `received` / `unknown`
- `source_type` / `evidence_role` / `confidence` / `source_confidence` / `coverage_notes` / `quality_notes` は、AIエージェントが解析ハーネスの自己監査結果を短く渡すフィールド。公開品質判定や不足点表示に使う
- `source_message_key` / `source_thread_key` / `source_channel_key` / `source_workspace_key` / `work_item_key` は、1通のメール、1つのSlackスレッド、1文書を0件/1件/複数件の証拠単位に分解した結果を追跡するための公開安全なキー。生のGmail ID、Slack ID、スレッドID、チャンネル名、ワークスペース名は送らず、AIエージェント内のハッシュや一時キーにする
- `github_repo_key_hash` / `github_pr_key_hash` / `github_issue_key_hash` / `github_commit_key_hash` / `github_release_key_hash` は、非公開または公開不要なコードホスト項目の結合用fingerprint。公開repo URLはpublicかつプロジェクト関連が確認できる場合だけ公開フィールドにできる
- `selected_sources` / `source_selection` / `source_selection_reason` / `cross_source_strategy` は、初回にユーザーが選んだ解析対象ソースと複合解析方針を残すためのフィールド。未選択ソースは検索しない
- `channel_category` / `author_role` は、Slack/プロジェクト管理ログを公開安全に抽象化するためのフィールド。チャンネル名、ワークスペース名、ユーザー名、メンションは含めない
- `period_from` / `period_to` / `period_status` / `period_end_basis` は、プロジェクト期間と終了状態を分けて扱うためのフィールド。`period_to` は終了根拠がある場合だけ使い、`last_seen` や一般的な完了文言だけから補完しない
- `query_family` / `date_window` は、どの検索方針と期間から拾った証拠かを残すためのフィールド。検索漏れの検出と短期スキャン判定に使う
- `relationship_type` / `relationship_notes` は、同一プロジェクト、親子関係、長期休止後の再開、保守バッチ、細かい作業イベント、重複、無関係の判定を短く残すフィールド。件名一致だけを根拠にしない
- `entity_aliases` / `company_aliases` / `project_aliases` / `domain_aliases` / `artifact_titles` は、略称、サイト名、公開URL、成果物名などを正規化するための公開安全な別名台帳。会社名だけ、同じ件名だけ、同一スレッドだけで結合しないために使う
- `project_source_anchor_map` / `candidate_merge_decisions` / `candidate_split_decisions` / `unmatched_source_items` / `integration_backfill_queries` は、Gmail、Slack、文書、コード履歴などを統合する前に、どのアンカーで同一プロジェクトと見なしたか、何を分割したか、何を追加検索すべきかを残すフィールド
- `evidence_role_matrix` / `boundary_evidence_by_project` / `context_evidence_by_project` / `source_corroboration_matrix` / `source_conflicts` / `status_resolution` / `phase_coverage` / `missing_evidence_roles` は、各プロジェクトでどの証拠ロールやフェーズが埋まっているか、メール/請求/契約の境界証拠とSlack/文書/コードの文脈証拠がどう照合されているか、矛盾時にどの保守的な状態へ解決したかを確認するためのフィールド
- `skill_evidence_matrix` / `tool_evidence_matrix` / `experience_signal_type` / `skill_inference_basis` / `skill_evidence_confidence` は、GitHub/Figma/制作プラグイン成果物/Drive/Slack/メールなどから一般的な職務スキル・使用ツールを履歴書向けに証拠化するためのフィールド。プロジェクト内の `tools` には年数を入れない
- `merge_split_notes` / `project_completeness` / `missing_fields` / `quality_level` は、過剰結合、過剰分割、職務経歴書項目の不足をAIエージェントが自己監査した結果を渡すフィールド
- `content_summary` / `activity_label` / `tags` / `skills` / `tools` はAIエージェントが接続済みメール内容、Slack/プロジェクト管理ログ、接続済み文書、PR、プロジェクト更新などを読んで作った短い公開安全な要約ラベル。本文原文、Slack原文、個人情報、番号、添付内容は含めない
- `project_name` / `project_key` / `client_label` / `company_name` / `service_name` / `product_name` / `site_name` / `campaign_name` / `project_overview` / `body_evidence_summary` / `client_request_summary` / `response_summary` / `decision_summary` / `deliverable_summary` / `artifact_summary` / `role_summary` / `outcome_summary` / `constraints_summary` / `feedback_summary` / `acceptance_summary` / `maintenance_summary` / `collaboration_summary` / `budget_summary` / `project_phase` は、AIエージェントが接続済みソースを読んで関連証拠をプロジェクト単位にまとめるための公開安全フィールド。証明書ページはこれを使い、期間、会社/クライアント表示、サービス/サイト/プロジェクト識別子、本文解析要約、制作内容、担当範囲、成果、実績キャプチャをプロジェクトカードとして表示する
- `company_name` / `client_label` は表示属性であり、グルーピングキーではない。同じ会社でも、サイト名、URL/ドメイン/パス、成果物、スレッド、フェーズ、時期が違う場合は別 `project_key` として送る
- Proof Finderは本文原文を受け取らない。本文を読む処理は接続済みデータソースを扱えるAIエージェント内で行い、MCPへ渡すのは短い構造化要約だけにする
- 会社名・クライアント名・サービス名・サイト名・プロジェクト名は接続済み証拠から確認できる場合は含める。職務経歴書の本人名は `resume_owner_name` として公開可能。相手方の個人名、担当者名、メールアドレス、電話番号は含めない。正確な案件名が公開安全か不明な場合、AIエージェントは推測せず「採用LP制作」「コーポレートサイト改修」のような中立だが具体的なラベルを使う
- `url` / `work_url` / `workUrl` / `work_urls` / `website_url` / `site_url` / `portfolio_url` / `public_url` / `production_url` / `launch_url` / `urls` / `links` / `work_links` は接続済みソースから見つかった公開実績URLだけ。`https` の公開ホストだけを採用し、クエリとフラグメントは保存しない
- body/attachment/rawScreenshotが含まれていたら400

Response:

```json
{
  "analysis_id": "guest_01HY...",
  "persisted": false,
  "candidates": [
    {
      "candidate_id": "guest_cand_ai_web",
      "title": "Web制作・実装活動レジュメ",
      "category": "ai_inferred_activity",
      "category_scope": "ai_inferred",
      "inferred_focus": ["Web制作", "開発・実装"],
      "source_template_categories": ["web_design_coding", "engineering"],
      "score": 86,
      "proof_level": "verified_candidate",
      "period": {
        "from": "2022-04-10",
        "to": "2026-02-11"
      },
      "evidence_count": 8,
      "strong_evidence_count": 6,
      "work_url_count": 1,
      "project_count": 2,
      "analysis_depth": "body_summarized_by_agent",
      "body_summarized_evidence_count": 4,
      "project_summaries": [
        {
          "project_id": "proj_...",
          "title": "LPリニューアル制作プロジェクト",
          "client_label": "クライアント/企業",
          "period": { "from": "2019-04-12", "to": "2020-01-18" },
          "evidence_count": 4,
          "analysis_depth": "body_summarized_by_agent",
          "project_overview": "本文解析からLP制作の依頼、実装、納品を同一プロジェクトとして整理",
          "body_evidence_summary": "本文でLPコーディング完了版の納品と公開前確認依頼が示されている",
          "client_request_summary": "レスポンシブ対応と公開前確認",
          "response_summary": "HTML/CSS実装済みの成果物を納品",
          "decision_summary": "公開前確認へ進行",
          "deliverable_summary": "LPデザインとHTML/CSSコーディング",
          "role_summary": "制作、納品、確認依頼を担当",
          "outcome_summary": "公開前確認まで進行",
          "work_url_count": 1
        }
      ],
      "source_integrity": "agent_collected_metadata",
      "recommended_modules": [
        "timeline",
        "stats_summary",
        "activity_frequency",
        "money_spent",
        "source_breakdown",
        "verification_method"
      ],
      "inference_basis": {
        "mode": "ai_inferred_resume",
        "top_signals": [
          { "id": "web_design", "label": "Web制作", "count": 3, "score": 8 }
        ],
        "safe_content_fields": ["subject", "content_summary", "activity_label", "tags", "project_name", "client_label", "project_overview", "body_evidence_summary", "client_request_summary", "response_summary", "decision_summary", "deliverable_summary", "role_summary", "outcome_summary", "work_url"]
      },
      "evidence_preview": [
        {
          "evidence_hash": "ev_8cf9...",
          "date": "2026-02-11",
          "sender_category": "other",
          "subject_label": "納品",
          "inferred_labels": ["Web制作", "開発・実装"],
          "work_url_count": 0,
          "strength": "strong"
        }
      ],
      "next_action": "login_to_save"
    }
  ]
}
```

### `POST /api/evidence-batches/challenge`

ログイン必須。公式アプリ用nonceを発行する。

Request:

```json
{
  "client": "android",
  "app_version": "0.1.0"
}
```

Response:

```json
{
  "challenge_id": "ch_01HY...",
  "nonce": "base64url...",
  "expires_at": "2026-05-06T04:00:00Z"
}
```

### `POST /api/evidence-batches`

ログイン必須。公式アプリから編集前バッチを送る。

Request:

```json
{
  "challenge_id": "ch_01HY...",
  "batch_hash": "sha256:...",
  "signature": "base64url...",
  "source_integrity": "sealed_app_batch",
  "records": [
    {
      "date": "2026-02-11",
      "sender_domain": "example.com",
      "subject_label": "入場案内",
      "evidence_type": "entry_notice_metadata",
      "normalized_hash": "sha256:..."
    }
  ],
  "app_check_token": "..."
}
```

Server checks:

- nonce未期限切れ
- App Check / Play Integrity検証
- Android Keystore署名検証
- `batch_hash` 再計算一致
- 証明候補をサーバー側で再計算

Response:

```json
{
  "batch_id": "bat_01HY...",
  "source_integrity": "sealed_app_batch",
  "candidate_ids": ["cand_01HY..."]
}
```

## 3. Authenticated REST API

### `POST /api/proof-candidates/{candidateId}/save`

候補をユーザーアカウントに保存する。入力候補をそのまま保存せず、サーバー再計算結果だけを保存する。

### `POST /api/proof-candidates/{candidateId}/exclude-evidence`

Request:

```json
{
  "evidence_hashes": ["ev_8cf9..."],
  "reason": "hide_from_public_page",
  "confirmation": "exclude_selected_evidence"
}
```

Response:

```json
{
  "candidate_id": "cand_01HY...",
  "excluded_evidence_count": 1,
  "recalculated_evidence_count": 7,
  "proof_level": "supported_candidate"
}
```

### `POST /api/certificates`

ログイン必須。証明書を作成し、共有URLを発行する。現MVPではデモログインで公開まで行う。

Request:

```json
{
  "records": [
    {
      "date": "2026-02-11",
      "sender": "me@example.com",
      "subject": "LPコーディング完了版を納品しました",
      "work_url": "https://example.com/work/lp",
      "work_url_captures": [
        {
          "url": "https://example.com/work/lp",
          "screenshot_data_url": "data:image/jpeg;base64,...",
          "captured_at": "2026-05-08T00:00:00Z",
          "viewport": "desktop"
        }
      ]
    }
  ],
  "category": "ai_inferred_activity",
  "excluded_evidence_keys": [],
  "source_integrity": "agent_collected_metadata",
  "publish_amount": false
}
```

Server behavior:

- サーバー側で候補を再分析する
- クライアントの件数、期間、スコア、金額合計は信用しない
- `self_submitted` は422で拒否する
- 保存対象は公開安全な要約と `evidence_preview` のみ
- 生の送信元メールアドレス、本文、添付、注文番号、座席番号は保存しない
- 接続済みソース内の公開実績URLがある場合だけ `workSamples` を生成する。AIエージェント側から渡されたキャプチャは最大8件の小さな画像data URLに限定して保存し、ない場合はURLのみ表示する

Response:

```json
{
  "certificate": {
    "publicId": "pf_...",
    "status": "published",
    "title": "Web制作・実装活動レジュメ",
    "proofLevel": "supported_candidate",
    "evidenceCount": 3,
    "sourceIntegrity": "agent_collected_metadata",
    "workSamples": [
      {
        "url": "https://example.com/work/lp",
        "displayHost": "example.com",
        "captureStatus": "captured",
        "captureSource": "agent_collected_capture"
      }
    ]
  },
  "url": "https://.../cert.html?id=pf_..."
}
```

### `GET /api/certificates/{publicId}`

ログイン不要。公開証明書ページ用のredactedデータだけを返す。

### `GET /api/me/certificates`

ログイン必須。本人の発行済み証明書一覧を返す。現MVPでは `x-proof-demo-user: demo-akira` で確認できる。

### `POST /api/certificates/{certificateId}/publish`

将来API。ドラフト作成と公開を分離する場合に使う。現MVPでは `POST /api/certificates` が公開URL発行まで行う。

### `POST /api/certificates/{certificateId}/revoke`

将来API。公開URLを取り下げ状態にする。削除ではなく状態変更。

## 4. Remote MCP Tools

Initial guidance:

```text
initialize.instructions
prompts/list
prompts/get start_resume_generation
```

Web UIがコピーするのはMCP URLだけにする。接続後の開始案内、`get_started` 呼び出し、解析ハーネス参照はMCPサーバー側が返す。ただし初回のユーザー向け表示はハーネス本文ではなく、接続完了、情報源の接続確認、接続済み/未接続/追加可能な情報源一覧、どの情報源を使うかの確認までを1セットにする。

Public:

```text
get_started
get_analysis_harness
list_supported_proof_types
analyze_evidence_metadata
create_certificate_preview
record_filter_learning
```

OAuth required:

```text
get_account_status
create_certificate_draft
publish_certificate
```

MVPでは `save_candidate` / `exclude_evidence` / `revoke_certificate` は認証境界だけを固定し、公開URL発行は `publish_certificate` に集約する。

MCP tool guard:

- `analyze_evidence_metadata` は本文/添付原本を受け付けない
- `get_analysis_harness` は、AIエージェントが毎回同じ順序で解析できるように `source_inventory` / `source_check` / `source_selection` / `source_query_matrix` / `broad_metadata_scan` / `source_noise_filter` / `source_specific_deepening` / `source_normalization_ledger` / `message_atomization` / `entity_alias_resolution` / `public_anchor_discovery` / `cross_source_anchor_scoring` / `project_cluster` / `project_graph_resolution` / `project_identity_specificity_audit` / `timeline_reconstruction` / `targeted_body_read` / `evidence_role_matrix` / `cross_source_reconciliation` / `integration_backfill_loop` / `evidence_role_labeling` / `company_url_pass` / `artifact_url_capture_pass` / `exception_reconciliation` / `false_merge_split_audit` / `privacy_filter` / `consistency_dedup_pass` / `project_completeness_audit` / `resume_narrative_quality_pass` / `record_quality_gate` / `coverage_gap_report` / `coverage_backfill_loop` / `pattern_learning_feedback` / `publish_gate` を返す
- `get_analysis_harness.setup_output_contract` は、MCP接続直後の初回表示を固定する。AIエージェントは `get_started` / `get_analysis_harness` を内部確認し、`source_inventory` / `source_check` の低負荷カナリア後に、接続済み、未接続・認証が必要、現在利用不可、追加接続候補を分けて表示し、どの情報源を使うかまたは追加接続するかを確認する。ハーネス本文を初回ユーザー表示としてそのまま出さない
- `get_analysis_harness.flow_contract.phase_handoffs[]` は各フェーズの `id` / `required_inputs` / `required_outputs` / `next_phase` / `handoff_gate` を返す。`source_selection` は `source_check` の後に実行し、複数の接続済みソースを選択できる形で誘導する。クライアントが対応している場合はCodexチャットのmulti-select choice UIを使い、非対応なら通常チャットの番号付きリストにフォールバックする。Gmail/メール + Slack/プロジェクト管理を推奨初期値とし、メールは境界証拠、Slackは要件・意思決定・レビュー・承認・進行状況・引き継ぎの文脈証拠、制作プラグイン成果物は成果物実在・公開文脈・スキル補強として扱う。`public_anchor_discovery` は `entity_alias_resolution` と `cross_source_anchor_scoring` の間で公開 `https` URL、公開成果物URL、非公開URL fingerprint、URL anchor mapを作り、scopeなしGitHub/code host検索や `business_admin_noise`、private/unlisted artifact URLを証拠化しない。`cross_source_reconciliation` で同じプロジェクトグラフに照合し、`integration_backfill_loop` で不足証拠の追加探索を消化する。`candidate_analysis_order` は `resume_narrative_quality_pass`、`record_quality_gate`、`coverage_gap_report`、`coverage_backfill_loop`、`pattern_learning_feedback` で終わり、その後にだけ `analyze_evidence_metadata` を呼ぶ。`publish_gate` は `analyze_evidence_metadata` の後、現在のユーザー依頼に公開URL/URL公開/公開までの意図がある場合は `publication_intent=publish_url_requested` とし、未解消gapを `quality_report` と proof level に反映しながら、追加ドラフト確認で止めず `publish_certificate` へ進む分岐として扱う。`analyze_evidence_metadata` の候補は `quality_report` と `deferred_project_summaries` を返し、提案止まり、単発更新、開始/完了証拠不足、会社・サービス・成果物不足を深掘りまたは除外できるようにする
- 全経歴が対象のため、`source_query_matrix`、`coverage_gap_report`、`coverage_backfill_loop` は固定年数で止めない。API制限で年次・月次・ページ単位に分割する場合も、接続ソースの `oldest_available_at` まで到達し、ページングが尽きたことを `source_scan_coverage` に記録する。`source_scan_coverage.mode=all_available_history`、`oldest_available_at`、`scanned_from`、`scanned_to`、`query_windows`、`oldest_reached=true`、`per_source`、`pagination_exhausted` または `page_tokens_exhausted` がない解析は短期/部分スキャンとして扱い、候補の `quality_report.warnings` に `all_available_history_not_confirmed` を返し、`verified_candidate` にはしない
- `list_supported_proof_types` は固定タイプ一覧ではなく、AI推定モード、安全な入力フィールド、内部シグナルテンプレートを返す
- MCPサーバーは、AIエージェントに「メールをプロジェクト台帳ではなく証拠素材として扱い、Slack/プロジェクト管理は文脈証拠として扱い、長期の送信履歴と関連Slackスレッド/ステータス/レビュー/承認を検索し、本文/ログ読解前にメタデータだけで受信ノイズとチャットノイズを除外し、送信済み請求書を完了/クローズ証拠として扱い、1通/1スレッドを0件/1件/複数件の `work_item` に分解し、件名やチャンネル名ではなくURL/成果物/会社/サービス/サイト/スレッド/フェーズ/時期で `project_source_anchor_map` を作り、本文と署名とSlack文脈をAIエージェント内で読んだうえで各recordへ `selected_sources` / `source_selection` / `source_message_key` / `source_thread_key` / `source_channel_key` / `channel_category` / `author_role` / `work_item_key` / `entity_aliases` / `company_aliases` / `project_aliases` / `domain_aliases` / `artifact_titles` / `project_source_anchor_map` / `relationship_type` / `relationship_notes` / `candidate_merge_decisions` / `candidate_split_decisions` / `unmatched_source_items` / `integration_backfill_queries` / `evidence_role_matrix` / `boundary_evidence_by_project` / `context_evidence_by_project` / `source_corroboration_matrix` / `cross_source_project_links` / `source_conflicts` / `status_resolution` / `merge_split_notes` / `project_completeness` / `missing_fields` / `quality_level` / `project_name` / `project_key` / `client_label` / `company_name` / `service_name` / `product_name` / `site_name` / `campaign_name` / `project_overview` / `body_evidence_summary` / `client_request_summary` / `response_summary` / `decision_summary` / `deliverable_summary` / `role_summary` / `outcome_summary` / `completion_signal` / `completion_summary` / `project_phase` / `tools` / 公開実績URLを入れる」よう指示する
- 保存/発行/取り下げ系は `confirmation` 必須
- RESTの未認証時は401 + `WWW-Authenticate`
- MCPの未認証 `tools/list` にも `publish_certificate` を表示する。未認証で呼ばれた場合は401 + `WWW-Authenticate` を返し、AIエージェントがOAuthログインへ進めるようにする
- `publish_certificate` は同じメタデータを `records` として受け取り、サーバー側で再分析してから保存する
- `publish_certificate` は接続済みソース内の公開実績URLだけを `workSamples` 化する。AIエージェント側キャプチャが渡された場合は保存し、渡されない場合も `capture_status` にキャプチャ試行結果を残してURLを表示する。MCPレスポンスには公開URL、本人名、経歴要約、プロジェクト要約、実績URL、キャプチャ状態を返すが、画像data URLは返さない
- ツール出力は公開安全な要約だけ

## 5. 保存モデル

```text
certificates/{certificateId}
users/{userId}/certificates/{certificateId}
oauthClients/{clientId}
oauthGrants/{grantId}
```

`certificates/{certificateId}` の保存フィールドと公開APIフィールド:

```json
{
  "publicId": "pf_8k29aq",
  "ownerId": "uid_...",
  "ownerDisplayName": "Akira",
  "resumeOwnerName": "Akira",
  "title": "Web制作・実装活動レジュメ",
  "status": "published",
  "proofLevel": "verified_candidate",
  "sourceIntegrity": "agent_collected_metadata",
  "evidenceCount": 8,
  "analysisDepth": "body_summarized_by_agent",
  "bodySummarizedEvidenceCount": 8,
  "projectCount": 2,
  "projectSummaries": [
    {
      "projectId": "proj_...",
      "title": "LPリニューアル制作プロジェクト",
      "clientLabel": "クライアント/企業",
      "period": { "from": "2022-04-10", "to": "2022-06-01" },
      "evidenceCount": 4,
      "analysisDepth": "body_summarized_by_agent",
      "projectOverview": "本文解析からLP制作の依頼、実装、納品を同一プロジェクトとして整理",
      "bodyEvidenceSummary": "本文でLPコーディング完了版の納品と公開前確認依頼が示されている",
      "deliverableSummary": "LPデザインとHTML/CSSコーディング",
      "artifactSummary": "LPデザインカンプ、HTML/CSS一式、公開前修正",
      "roleSummary": "制作、納品、確認依頼を担当",
      "outcomeSummary": "公開前確認まで進行",
      "workSamples": []
    }
  ],
  "workSamples": [
    {
      "url": "https://example.com/work/lp",
      "displayHost": "example.com",
      "captureStatus": "captured",
      "captureSource": "agent_collected_capture",
      "capturedAt": "2026-05-07T00:00:00Z",
      "viewport": "960x640"
    }
  ],
  "excludedEvidenceCount": 0,
  "period": {
    "from": "2022-04-10",
    "to": "2026-02-11"
  },
  "modules": [],
  "createdAt": "2026-05-06T00:00:00Z",
  "publishedAt": "2026-05-06T00:00:00Z",
  "revokedAt": null
}
```

公開API `/api/certificates/{publicId}` では `ownerId` と `ownerDisplayName` は返さず、表示用の `resumeOwnerName` だけを返す。職務経歴書の本人名、会社名、サービス名、サイト名、プロジェクト名は公開対象、相手方の個人名、メールアドレス、本文原文、添付、案件番号、請求番号は非公開対象。

## 6. 開発開始基準

- このAPI契約でXserver PHP APIとRemote MCPのルーティングを実装できる
- UIは `index.html` / `cert.html` の静的プロトタイプを本番配信できる
- 保存対象と非保存対象が分離されている
- Xserver本番では保存JSONを `public_html` 外に置き、直URLで内部保存データを読めない
- MCP public/auth境界が明確である
- Gmail API本連携なしでMVPを出せる



