技術仕様・セキュリティ
開発者・サイト管理者向けに、保存するデータ・外部通信・バックグラウンド処理・セキュリティ対策をまとめます。
保存するデータ
| 場所・キー | 中身 |
wp_options: kashiwazaki_seo_related_posts_options | 共通設定・投稿タイプ別のカスタム設定(post_type_settings_{投稿タイプ})・関連記事の選び方・モデル・暗号化した APIキー |
wp_options: kashiwazaki_seo_related_posts_embedding_models | OpenAI から取得したモデルの一覧(1 日 1 回更新) |
wp_options: kashiwazaki_seo_related_posts_api_logs ほか | API の呼び出しの記録(GPT と Embedding に分けて、成功・失敗) |
post_meta: _kashiwazaki_seo_related_posts_enabled | 「この記事で関連記事を表示する」の ON/OFF |
post_meta: _kashiwazaki_seo_related_posts_*(max_posts / display_method / target_post_types など) | 記事ごとの設定 |
post_meta: _kashiwazaki_seo_related_posts_cached_results / _cached_timestamp | 関連記事のキャッシュ |
post_meta: _kashiwazaki_seo_related_posts_embedding | 記事のベクトル(モデル名・本文のハッシュ・次元数・base64 のベクトル) |
カスタムテーブルは使いません。アンインストール時は上のデータをすべて削除し、予約済みのバックグラウンド処理も取り消します(マルチサイト対応)。
外部通信(OpenAI)
| エンドポイント | 用途 |
POST /v1/embeddings | 記事のベクトル作成(最大 20 記事ずつ、本文は先頭 3,000 文字) |
GET /v1/models | モデル一覧の取得・APIキーテスト(トークンを使わない) |
POST /v1/chat/completions | GPT を使う方式での関連記事の選定、GPT モデル保存時の確認 |
訪問者のページ表示中には OpenAI を呼びません。OpenAI でエラーが出たときは 10 分間呼び出しを止めます。
バックグラウンド処理(WP-Cron)
| イベント | 内容 |
kashiwazaki_seo_related_posts_embed_missing | 未作成のベクトルを作る単発イベント。1 回に 60 記事まで作り、残りがあれば続きを予約します。 |
kashiwazaki_seo_related_posts_gpt_select | GPT を使う方式で、記事ごとに GPT の選定を行う単発イベント(同じ記事は 10 分に 1 回まで)。 |
どちらもプラグインの無効化・削除時に取り消します。DISABLE_WP_CRON を設定している場合は、サーバーの cron で wp-cron.php を定期的に呼んでください。
ベクトルの比較
- OpenAI の返すベクトル(正規化済み)を base64 のまま保存し、比べるときに復元してコサイン類似度を計算します。
- 比べる候補は最大 3,000 記事です。記事の内容(ハッシュ)が変わったときだけ作り直します。
セキュリティ
v1.0.4 での対応
| 対策 | 内容 |
| APIキーの暗号化 | libsodium の secretbox で暗号化して保存します。鍵は wp-config.php の認証用ソルト(wp_salt('auth'))から作ります。暗号化できない環境では平文で保存しません。 |
| APIキーを画面に出さない | 保存済みのキーを入力欄の value に出力しません。表示は先頭と末尾の数文字だけです。 |
| 定数での設定 | KASHIWAZAKI_SEO_RELATED_POSTS_OPENAI_API_KEY を wp-config.php に書くと、データベースにキーを置かずに使えます。 |
| 旧 OpenRouter のキーの削除 | 使わなくなった OpenRouter 関連の処理を削除し、アップデート時にデータベースに残っていたキーを自動で削除します。 |
| 外部 CDN を使わない | 管理画面の Chart.js(3.9.1、MIT)を同梱し、外部から読み込みません。 |
| 費用の暴走を防ぐ | 訪問者の表示中に OpenAI を呼ばない、GPT は記事ごとに 10 分に 1 回まで、エラー時は 10 分停止、管理画面で GPT をその場で使えるのは管理者だけ。 |
| 入力の制限 | 関連記事プレビューの対象を公開投稿タイプに限り、表示件数を 1〜20 件に制限しています。OpenAI のエラーはメッセージ部分だけを表示します。 |
v1.0.3 での対応
| 対策 | 内容 |
| CSRF 対策 | 設定保存のすべての送信に nonce 検証と manage_options の権限チェックを入れています。 |
| 格納型 XSS 対策 | 見出しタグを許可リスト(h1〜h6 / div / p)で検査し、保存時・表示時の両方で適用します。 |
| カテゴリの絞り込み | カテゴリの絞り込みをすべての選び方に一律に適用しています。 |
AJAX ハンドラー
| アクション | 用途 |
kashiwazaki_fetch_related_posts | 記事の編集画面の「関連記事を取得」 |
kashiwazaki_clear_cache | 記事のキャッシュクリア |
kashiwazaki_reset_all_posts_to_defaults | 投稿タイプの全記事を現在の設定値に合わせる |
kashiwazaki_enable_all_posts | 投稿タイプの全記事を「表示する」にする |
kashiwazaki_embedding_backfill | 未作成の記事のベクトルをまとめて作る |
kashiwazaki_refresh_embedding_models | モデル一覧の取得 |
すべて nonce 検証と権限チェックを行います。
動作要件
| 項目 | 要件 |
| WordPress | 5.0 以上 |
| PHP | 7.4 以上(libsodium) |
| フロントエンド | CSS 約 24KB、JS 約 7.6KB(JSON-LD は出力しません) |