技術仕様・セキュリティ

開発者・サイト管理者向けに、保存するデータ・外部通信・バックグラウンド処理・セキュリティ対策をまとめます。

このページの内容
  1. 保存するデータ
  2. 外部通信(OpenAI)
  3. バックグラウンド処理(WP-Cron)
  4. ベクトルの比較
  5. セキュリティ
  6. AJAX ハンドラー
  7. 動作要件

保存するデータ

場所・キー中身
wp_options: kashiwazaki_seo_related_posts_options共通設定・投稿タイプ別のカスタム設定(post_type_settings_{投稿タイプ})・関連記事の選び方・モデル・暗号化した APIキー
wp_options: kashiwazaki_seo_related_posts_embedding_modelsOpenAI から取得したモデルの一覧(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/completionsGPT を使う方式での関連記事の選定、GPT モデル保存時の確認

訪問者のページ表示中には OpenAI を呼びません。OpenAI でエラーが出たときは 10 分間呼び出しを止めます。

バックグラウンド処理(WP-Cron)

イベント内容
kashiwazaki_seo_related_posts_embed_missing未作成のベクトルを作る単発イベント。1 回に 60 記事まで作り、残りがあれば続きを予約します。
kashiwazaki_seo_related_posts_gpt_selectGPT を使う方式で、記事ごとに GPT の選定を行う単発イベント(同じ記事は 10 分に 1 回まで)。

どちらもプラグインの無効化・削除時に取り消します。DISABLE_WP_CRON を設定している場合は、サーバーの cron で wp-cron.php を定期的に呼んでください。

ベクトルの比較

セキュリティ

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 検証と権限チェックを行います。

動作要件

項目要件
WordPress5.0 以上
PHP7.4 以上(libsodium)
フロントエンドCSS 約 24KB、JS 約 7.6KB(JSON-LD は出力しません)