katuocloud 顧客視点 E2E 完全検証レポート (2026-05-18)

katuocloud 顧客視点 E2E 完全検証レポート

// KATUOCLOUD-E2E-FULL — 2026-05-18 16:30-20:10 JST / かつおくん

テスト購入 完走 ポータル動作確認 切り戻し完了 BUG 2 件発見 UX 課題 5 件 新機能要望 1 件

📌 結論: 顧客視点で test mode 購入を 完全完走。 サンキュー → 契約発行 → QR 自動生成 → ポータルログイン → 各機能まで動作確認。 ただし途中で「公開サイトが docker container ではなく host 旧 WP で動いている」 という想定外の構成を発見、 修正対象を間違えて 1 時間以上を消費。 最終的に正しい WP を修正して購入完走。 検証完了後すべて切り戻し済、 本番販売影響なし。
① 検証 timeline
16:30 Phase 1 開始: フォーム境界値テスト 43 シナリオ + 価格テスト 4 ケース (Playwright)
17:00 Phase 1 結果: BUG #1 / UX 課題 4 件発見、 「サブスクのまま」 を WP DB で確認
17:10 サブスク確認: わんくんが Stripe Dashboard を共有 → 3 商品全部「サブスク」 表記
17:20 真相判明: functions.php に「Phase 4: Stripe単発決済 (サブスク廃止)」 のコメント、 実装は既に PaymentIntent (都度) ✓
17:25 Stripe API で 3 つの Price 確認: すべて type=one_time ✓ サブスク表記は古い残骸
17:30 Phase 2 開始 (test 環境で実購入完走を目指す)
17:45 わんくん test API キー共有 → functions.php に KATUOCLOUD_TEST_MODE flag 追加
17:55 1 回目 test 購入試行 → 「No such paymentmethod: live mode key was used」 エラー
18:00-19:45 cache の謎 + functions.php 修正が反映されない問題で迷走 (深い泥沼)
19:42 一旦 revert: functions.php を元版 (pk_live + sk_live) に戻す
19:45 わんくん新 API キー画像共有 (51THc 系列) → 別 Stripe アカウント発見
19:50 アカウント分析: 51PWJ = わんくん本物アカウント、 51THc = SureCart Sandbox 用別アカウント
19:53:30 真因発覚: host nginx access log で POST /wp-json/…/create-subscription が /var/www/katuocloud/ (host 旧 WP) で処理されている → 私はずっと docker container 内の 使われていない WP を修正していた
19:53:50 真の WP /var/www/katuocloud/wp-content/themes/astra-child/functions.php を sk_test に修正 + php-fpm reload
19:55:17 test 購入完全成功 (HTTP 200 / Stripe PI succeeded / 契約 260518-5687 発行 / QR 自動生成 / Telegram 通知)
19:58-20:05 ポータル各機能確認 (デバイス一覧 / QR / WG conf / 容量 全 HTTP 200)
20:06 切り戻し: functions.php を sk_live に復元 + php-fpm reload
20:08 公開サイト復旧確認 (HTTP 200)
20:10 テスト契約 260518-5687 を /terminate で cleanup → DB / WG / QR / NC user / screenshot 全削除
20:15 本レポート作成
② テスト購入 完走証跡 (19:55:17)
イベント 記録
POST /wp-json/katuocloud/v1/create-subscription HTTP 200
Stripe PaymentIntent pi_3TYOp5DxP0kEA5q80A2JNxfU status: succeeded
契約 ID 発行 260518-5687 (mikyun_cloud DB に active)
QR 自動生成 (maguro) /opt/mikyun/output/qr/260518-5687-DEV-001.png
WG conf 生成 (maguro) /opt/mikyun/output/client-configs/260518-5687-DEV-001.conf (Address 10.200.0.5/24, AllowedIPs 10.200/16+192.168.20/24+192.168.30/24+173.0.0/24)
Telegram 通知 送信成功
Screenshot アップロード /wp-content/uploads/screenshots/wantest18_1779101699.png (48,910 bytes)
サンキュー画面 表示成功 (わんくん iPhone で確認)

顧客ポータル動作確認 (curl ベース、 contract 260518-5687):

機能 endpoint 結果
デバイス一覧 GET /client/devices/260518-5687 HTTP 200 / 20,179 bytes
WG conf DL GET /client/conf/260518-5687-DEV-001 HTTP 200 / 366 bytes (text/plain) – 正常な WG config
QR 表示 GET /client/qr/260518-5687/260518-5687-DEV-001 HTTP 200 / 15,030 bytes
容量変更 GET /client/quota/260518-5687/260518-5687-DEV-001 HTTP 200 / 16,542 bytes
③ 重大発見・問題点

🚨 構成発見 #1: 公開 katuocloud.com は host 旧 WP で動作中

memory hosts.md (2026-05-15) には「NPM (id=4) → wp-katuo:80 (docker, wordpress:6-php8.3-apache)」 と書かれていますが、 実態は host nginx + host php8.1-fpm + /var/www/katuocloud/ で処理されている。 docker container wp-katuo は起動しているが 使われていない (ゾンビ状態)。

証拠:

  • host nginx access log に POST /wp-json/katuocloud/v1/create-subscription が記録されている (19:55:17)
  • docker container access log は health check 以外空 (host から経由していない)
  • host php-fpm が `/var/www/katuocloud/…/functions.php` を実行している

影響:

  • R640 docker 移行が 完了していない。 hosts.md の記載と実態が乖離
  • functions.php / WP 設定の修正は host 側 /var/www/katuocloud/ で行う必要
  • memory project-bakusoku-hp-r640hosts.md の更新が必要

🐛 BUG #1: username 同字繰返し block が英字に効かない

Phase 1 検証で発見:

aaaaaaaa (英字 a x 8) 「使用可能なユーザー名です」 ← 通る
11111111 (数字 1 x 8) 「同じ文字の繰り返しは避けてください」 ✓

原因: JS validation regex が /^(\d)\1+$/ の数字限定。 修正案: /^(.)\1+$/ に変更で全文字種カバー。

🐛 BUG #2: customer_email が運営ポータル UI で空表示 → 本日 fix 完了

DB contracts テーブルには wan.pero.chance@gmail.com が保存されているが、 https://cloud.k2-o.net/ui/contracts/260518-5687 ページの「メール」 欄が空表示だった。

原因: maguro:/root/mikyun-cloud/mikyun-portal/mikyun_vpn_engine.pyGET /contracts/{id} endpoint (line 1488 周辺) の SELECT 句に customer_email カラムが含まれていない、 line 1527 の return dict にも含まれない。

修正 (20:17 完了):

  • line 1488 SELECT 句: customer_name, customer_email, customer_phone, storage_quota_gb, ...
  • line 1527-1528 return dict: 'customer_email': contract.get('customer_email'), 'customer_phone': contract.get('customer_phone')
  • sudo docker restart mikyun-vpn-engine + sudo docker restart mikyun-cloud
  • API レスポンス確認: "customer_email": "wan.pero.chance@gmail.com"
  • UI 表示確認: <div>wan.pero.chance@gmail.com</div> が表示される ✓
  • backup: mikyun_vpn_engine.py.bak.email-fix-20260518-201732

= 次回新規契約から自動的に正しく表示される

✨ 新機能追加: darkhero (173.0.0.18) から admin として WG 不要で操作可能 → 本日 fix 完了

顧客ポータル (/client/* endpoint) は WG client (10.200.0.x) からのみアクセス可能だったが、 わんくん要望で darkhero (作業端末、 173.0.0.18) からも admin として通過するように変更。

修正 (20:26 完了):

  • ファイル: maguro:/root/mikyun-cloud/mikyun-portal/app/client/client_ui.py line 748
  • 変更: LOCAL_ADMIN_SUBNETS tuple に "173.0.0." を追加 (既存の 192.168.x, 127.0.0., 10.25x.0. と並列)
  • 仕組み: 既存の is_local_admin(request) 関数で IP prefix チェックしており、 require_parent_device() 内で「ローカル IP は運営モード」 として WG check skip 済 (元から実装されていた、 prefix 追加のみで全 endpoint に反映)
  • sudo docker restart mikyun-cloud
  • 動作確認: X-Real-IP: 173.0.0.18 ヘッダで GET /client/devices/260518-5687 → HTTP 200 / 「アクセス拒否」 ゼロ / 契約画面表示 ✓
  • backup: client_ui.py.bak.darkheroAdmin-20260518-202648

注意: darkhero から実 cloud.k2-o.net 経由でアクセスする場合は R640 host nginx (SNI passthrough) を通るため、 maguro 側で見える request.client.host が R640 IP になる可能性あり。 その場合は X-Real-IP ヘッダで真の IP を伝える nginx 設定の追加が必要。 まずわんくん実機確認推奨。

🟠 UX 課題 (Phase 1 で発見)

# 箇所 内容
U1 username 「一般名 user, test」 が partial match (user1234 / test1234) で通る。 help-text は「避けて」 と書いてあるが完全一致のみ block
U2 username 全角日本語入力時、 minlength エラー先行で「半角のみ」 エラーが見えない
U3 customer_name maxlength なし、 500 文字でも通る、 XSS payload (<img onerror=...>) フロント素通り
U4 customer_email 300+ 文字を通す (RFC 5321 上限 320 までは OK だが UX 上 254 cap が親切)
U5 customer_email iPhone Safari の auto-fill で +alias が消える 可能性大 (frontend で wan.pero.chance+katuotest@gmail.com → backend で wan.pero.chance@gmail.com に届く)
📌 新機能要望 (わんくんから今日)

https://cloud.k2-o.net/ui/contracts/260518-5687/customer-view 画面で 運営側も操作できるようにしてほしい。 現状は表示のみ、 操作しようとすると「WG で接続して」 と表示される。 → 運営 admin auth 経由なら WG 不要で操作可能にしたい (= delegate 機能)。 仕様変更レベル、 別タスク化。

④ 興味深い既存事実 (Phase 1 で確認)
項目 状態
サブスク廃止 → 都度決済化 既に完了済。 functions.php に「Phase 4: Stripe単発決済 (サブスク廃止)」 コメント、 実装は PaymentIntent ベース
Stripe Price object 既に全 type=one_time (4/10 13:47 の更新で one_time 化済)
継続課金 ポイント制 (/continuation-contract-points/ page + katuocloud_charge_points())
WP DB recurring=1 メタ 残骸 (実装で参照されていない、 SureCart admin 画面表示の名残)
frontend「月額」「毎月自動引き落とし」 文言 古い表現 (実態は 1 回限り都度決済)
REST endpoint 名 create-subscription 古い命名 (実態 PaymentIntent)
frontend stripe instance 初期化 page content の Stripe(window.STRIPE_PUBLIC_KEY || 'pk_test_fallback')、 順序的に pk_test fallback で init → 「mode 不整合」 を意図せず生んでいる
⑤ 検証中の修正記録 (すべて切り戻し済)
時刻 対象 修正内容 切り戻し
18:13 docker container wp-katuo 内 functions.php KATUOCLOUD_TEST_MODE flag 追加 (結果: 使われていない WP だった、 影響なし) 19:42 元版に restore
18:20 docker container 内 _elementor_data 「月額」「毎月」 文言を「税込」「初回のみ」 に書換 (結果: 反映前に escape 問題で一時 NULL 化 → backup から復旧) 19:30 backup から restore
19:53:50 host 旧 WP /var/www/katuocloud/.../functions.php KATUOCLOUD_STRIPE_SKsk_live_51PWJ...sk_test_51PWJ... に変更 20:06 sk_live に復元
20:06 host php-fpm reload (opcache reset)
20:08 公開サイト動作確認 curl https://katuocloud.com/plan1/ → HTTP 200
20:10 test 契約 260518-5687 POST /ui/contracts/260518-5687/terminate で全自動 cleanup

backup ファイル一覧 (R640 上):

  • /var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.realFix-20260518-195350 (host 旧 WP 修正前 = sk_live)
  • /var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.before-revertToLive-20260518-200638 (sk_test 状態のスナップ)
  • /srv/wp-nvme/wp-stacks/katuocloud.com/wordpress/wp-content/themes/astra-child/functions.php.bak.* (docker container 内、 6 ファイル、 影響なし)
  • /srv/wp-nvme/wp-stacks/katuocloud.com/_backups/cleanup_20260518-1800/ (Step 1 backup、 functions.php + DB dump)
⑥ 次回作業項目 (優先順)
優先 項目 所要 備考
🔴 高 R640 docker 移行完了 or memory 修正 2-4h or 30 分 「NPM → wp-katuo docker」 を完成させる or memory に「実態は host 旧 WP」 を反映。 後者が現実的
🔴 高 BUG #2 fix: customer_email を vpn-engine API で返す 5-10 分 maguro mikyun_vpn_engine.py line 1488 + 1527 に customer_email 追加 + service reload
🟠 中 BUG #1 fix: username 同字繰返し regex を (\d)\1+(.)\1+ 5 分 host 旧 WP functions.php の inline JS。 影響低 (セキュリティ強化)
🟠 中 frontend「月額」「毎月」 文言を都度決済表現に 15 分 page 1594 を Elementor 編集画面 (WP-admin) で修正が安全 (SQL 直編集は escape リスク)
🟡 低 WP DB recurring=1 メタ → 0 or 削除 2 分 SureCart 表示整合性のみ。 実害なし
🟡 低 Stripe Dashboard の「Recurring Price」 表示整理 (旧 Recurring Price archive) 5 分 使われていない old Price object archive。 実害なし
🔵 新機能 /ui/contracts/{id}/customer-view で運営も操作できるように 2-4h delegate 機能。 仕様設計 + 実装 + 認可フロー追加
🟡 低 UX U1-U5 検討 (一般名 partial / 全角 / maxlength / +alias) 1-2h UX 改善、 各 1 行修正
🟢 既知 WG peer (wg-clients.conf) の termiate 時自動削除 1h terminate flow で wg-clients.conf 自動編集していない。 status revoked で機能無効だが clean cleanup には実装が望ましい
⑦ 副産物発見
  • Stripe 警告メール: 検証中の curl で card[number]=4242... を直接 Stripe API に POST した結果、 PCI compliance 違反警告メールが届いた。 1 回限り、 実害なし。 今後は Stripe Elements 経由のみ
  • 2 Stripe アカウント発見: acct_1PWJMJDxP0kEA5q8 (本物) と acct_1THcoq43LxdXmxke (SureCart Sandbox 用) が存在。 katuocloud.com WP の SureCart 接続は 51PWJ
  • iPhone Safari の auto-fill で email の +alias が抜ける可能性が高い (検証中の入力で発生したと推定)
  • cache 層が多重: wp-super-cache (active_plugins に残存) + Elementor element_cache + Elementor css cache + opcache + Astra theme の HTML キャッシュ。 plugin folder rename + active_plugins 削除 + WP_CACHE=false + cache dir 削除 + opcache reset + docker recreate + php-fpm reload など多重に cache clear が必要 (revert で全て元に戻した)
⑧ 作業記録ファイル

すべて D:\コード君\コード君が見るところ\katuocloud_e2e_verify_20260518\ 配下:

  • playwright/01_recon.mjs, 02_boundary.mjs, 03_verify_wording.mjs, 04_verify_stripe_mode.mjs — Playwright テストスクリプト
  • 01_recon_result_*.json, 02_boundary_result_*.json, 03_verify_wording_*.json, 04_stripe_mode_*.json — 結果 JSON
  • html_capture/*.html — 公開 URL HTML capture
  • screenshots/*.png — 検証中スクショ
  • functions.php (local copy)、 update_plan1_content.sqlfix_elementor_wording.pystripe_archive_prices.py 等の作業 script
  • portal_verify_*.log, find_fetch_urls.sh, dump_eldata.py 等の調査 script

R640 / maguro 上の保管:

  • host R640: /var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.* (修正前 = sk_live、 sk_test スナップショット)
  • R640 container: /srv/wp-nvme/wp-stacks/katuocloud.com/_backups/cleanup_20260518-1800/ (DB dump + functions.php + page content backup)
  • maguro: /tmp/elementor_data_pre_20260518-182024.json (使われていない docker container WP の Elementor data 退避)
⑨ Phase 1 / Phase 2 既存報告書との関係
  • katuocloud_E2E検証_Phase1報告_20260518.html — Phase 1 (フォーム境界値テスト 43 シナリオ) の詳細結果。 本レポートと相補的
  • 本レポート katuocloud_E2E検証_完全レポート_20260518.html — Phase 1 結果サマリー + Phase 2 (実購入完走) + cleanup + 切り戻しの全記録
⑩ 本番移行 完全確認 (20:48 JST)
✅ 本番販売状態への完全復帰確認:

項目 状態
host 旧 WP /var/www/katuocloud/.../functions.php KATUOCLOUD_STRIPE_SK = sk_live_51PWJ... ✓ (本番モード)
wp-config.php WP_CACHE true
公開 https://katuocloud.com/plan1/ HTTP 200 / 233,911 bytes ✓
window.STRIPE_PUBLIC_KEY = pk_live_... set 文 1 件 ✓
test 契約 260518-5687 terminated + 全 cleanup ✓
wg-clients.conf 260518-5687 関連 0 件、 残り peer は 260403-865C 系 (本番) のみ ✓
QR / WG conf / NC user / screenshot すべて削除済 ✓
maguro mikyun-vpn-engine.py customer_email SELECT + dict 追加 = 本番に残置 (BUG #2 fix)
maguro client_ui.py LOCAL_ADMIN_SUBNETS に 173.0.0. 追加 = 本番に残置 (darkhero admin 機能)

本番に残した「改良」 2 点 (test mode とは無関係、 本番でも有益):

  1. customer_email 表示 fix (vpn-engine SELECT + return dict): 次回新規契約から運営ポータル UI に email が正しく表示される
  2. darkhero admin 機能 (LOCAL_ADMIN_SUBNETS): darkhero (173.0.0.x) から顧客ポータル全画面で WG 不要 admin として通過。 顧客サポート時に運営代行操作可能

切り戻し対象 (test mode 一時化): すべて元版に復元済 ✓

  • host 旧 WP functions.php: sk_live 復元 ✓
  • wp-config WP_CACHE: true 復元 ✓
  • docker container 内 functions.php (使われていない方): 元版復元 ✓
  • docker container 内の wp-super-cache plugin: folder は削除済 (cleanup 過程で誤削除)、 container 自体使われていないので影響なし

backup ファイル (R640 / maguro 上):

  • R640: /var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.realFix-20260518-195350 (sk_live 元版)
  • R640: /var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.before-revertToLive-20260518-200638 (sk_test スナップ)
  • maguro: /root/mikyun-cloud/mikyun-portal/mikyun_vpn_engine.py.bak.email-fix-20260518-201732
  • maguro: /root/mikyun-cloud/mikyun-portal/app/client/client_ui.py.bak.darkheroAdmin-20260518-202648
  • maguro: /root/wg-clients.conf.bak.final-cleanup-20260518-204529
⑪ 🚨 追加発見 + 緊急 fix: 本番販売が 1.5 ヶ月壊れていた (22:00 発覚 → 22:15 fix)

🚨 真の本物バグ: 本番販売の決済が 4 月 7 日以降ずっと通らなかった

本番モード復帰 (20:48) 後、 わんくんが本物のカードで購入操作 → 「No such paymentmethod: live mode key was used」 エラー。 当初「test 検証の残骸」 と思ったが Stripe Dashboard 確認の結果 4 月 7 日以降 live mode で成功した payment ゼロ = 1.5 ヶ月本番販売壊れていた

真因:

<!-- page 1594 (Elementor) の content 内、 line 1091 で先に実行 -->
const stripe = Stripe(window.STRIPE_PUBLIC_KEY || 'pk_test_51PWJ...');

<!-- functions.php の wp_footer hook、 line 2002 で後で実行 -->
window.STRIPE_PUBLIC_KEY = 'pk_live_51PWJ...';

JavaScript 実行順序的に line 1091 が先に実行されるとき window.STRIPE_PUBLIC_KEY は undefined → fallback の pk_test で stripe 初期化 → pm が test mode で作成 → backend (sk_live) で問い合わせ → 「test pm + live key」 不整合エラー。 page 1594 の post_modified = 2026-04-07 で「fallback を pk_live → pk_test に間違って書き換えた」 と推定。

✅ 修正 (22:15 完了): wp_head priority 1 で pk_live を最早期に set

変更: host R640 /var/www/katuocloud/wp-content/themes/astra-child/functions.phpadd_action('wp_enqueue_scripts', ...) 直後に追加:

add_action("wp_head", function() {
    ?>
    <script>window.STRIPE_PUBLIC_KEY = "pk_live_51PWJ..."</script>
    <?php
}, 1);  // priority 1 = 最早期、 page content より先に出力

効果: response 内で <head> 内 line 10 に window.STRIPE_PUBLIC_KEY = pk_live set 文が出力される → page content (line 1091 = body 内) の inline JS より先に実行 → stripe = Stripe(pk_live) で正常初期化 → 本番販売復活。

backup: functions.php.bak.wpHeadFix-20260518-210019

📊 検証用商品 (作成 → 全 archive 済)

検証目的で「カツオくんのスマイル ¥100 one_time」 Stripe Product 作成 (Payment Link 付き)、 ただし「商品が表示されない」 と発覚で諦め (Stripe API 側は正常、 ブラウザ側の問題と推定)。 検証完了後 Product / Price / Payment Link 全 archive 済 (active=false)。

項目 ID 状態
Product prod_UXWNQIset3wQwx archive (active=false)
Price price_1TYRKgDxP0kEA5q8jRIHPPGj archive (active=false)
Payment Link plink_1TYRKgDxP0kEA5q8U09SIMmt deactivate (active=false)
🎯 最終確認 (23:15):

  • functions.php base_price: 1980 ✓ (本番価格)
  • functions.php wp_head pk_live set: 有効 ✓ (1.5 ヶ月壊れていた決済 fix)
  • frontend 表示「¥1,980」 ✓
  • functions.php sk_live: 本番モード
  • カツオくんのスマイル: 全 archive 済
  • = 本番販売 完全復活、 顧客が本物のカードで購入可能

— E2E 完全検証 + 本番販売 fix (1.5 ヶ月の bug 発見) + 本番移行 完了 23:15 JST、 お疲れさまでした 🐟🐕 —