{
  "run_id": "sj88_full_system_qa_20260801_152500",
  "started_at": "2026-08-01T08:51:53.334Z",
  "finished_at": "2026-08-01T08:56:02.711Z",
  "duration_ms": 249378,
  "user": "sj88",
  "site": "https://adsfb.namnan.co.th",
  "testcases": [
    {
      "tc_id": "TC01_login_sj88",
      "pair_id": "pair_576af5b4",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc01_01_login_page.png",
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc01_02_filled_form.png",
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc01_03_after_login.png"
      ],
      "api": {
        "request": "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/api/tc01_login_request.json",
        "response": "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/api/tc01_login_response.json",
        "timing": "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/api/tc01_login_timing.json"
      },
      "ui_state": {
        "form_fields": [
          {
            "name": "username",
            "type": "text",
            "placeholder": "admin"
          },
          {
            "name": "password",
            "type": "password",
            "placeholder": ""
          },
          {
            "name": "rememberMe",
            "type": "checkbox",
            "placeholder": ""
          }
        ],
        "session_cookie": "wa_session",
        "post_login": {
          "ok": true,
          "loginRequired": true,
          "authenticated": true,
          "user": "sj88",
          "role": "admin",
          "rememberMe": false,
          "expiresAt": "2026-08-01T12:51:57.000Z",
          "expiresInSeconds": 14395
        }
      },
      "api_state": {
        "status": 200,
        "user": "sj88",
        "role": "admin"
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC02_live",
      "pair_id": "pair_4bc83e9b",
      "page": "/live",
      "desc": "Live Dashboard (live.html)",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC02_live.png"
      ],
      "ui_state": {
        "title": "🌸 Live — WepAppOpusApi (Public)",
        "h1": "",
        "body_length": 6693,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1286
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC03_app",
      "pair_id": "pair_3c838a3a",
      "page": "/app",
      "desc": "Workspace SPA (app.html)",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC03_app.png"
      ],
      "ui_state": {
        "title": "WepAppOpusApi · Workspace",
        "h1": "",
        "body_length": 1173,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1033
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC04_analytics",
      "pair_id": "pair_684172dc",
      "page": "/analytics",
      "desc": "Analytics Dashboard",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC04_analytics.png"
      ],
      "ui_state": {
        "title": "📈 Analytics & Charts — WepAppOpusApi",
        "h1": "📈 Analytics & Forecast Accuracy",
        "body_length": 1839,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 819
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()",
        "console.error: Failed to load resource: the server responded with a status of 404 ()",
        "console.error: Failed to load resource: the server responded with a status of 404 ()",
        "console.error: stats Error: /live/dashboard: 404\n    at api (https://adsfb.namnan.co.th/analytics:181:20)\n    at async loadStats (https://adsfb.namnan.co.th/analytics:420:18)\n    at async Promise.all (index 0)\n    a"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC05_scale",
      "pair_id": "pair_521b8bc6",
      "page": "/scale",
      "desc": "Scale Page",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC05_scale.png"
      ],
      "ui_state": {
        "title": "🚀 Scale Campaigns — WepAppOpusApi",
        "h1": "🚀 Scale Campaigns",
        "body_length": 29757,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1047
      },
      "ui_errors": [],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC06_ads-chats",
      "pair_id": "pair_39f53fb5",
      "page": "/ads-chats",
      "desc": "Ads + Chats Workspace",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC06_ads-chats.png"
      ],
      "ui_state": {
        "title": "Ads + Chats Workspace · WepAppOpusApi",
        "h1": "💬 Ads + Chats Workspace",
        "body_length": 1467,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 783
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC07_hourly-dashboard",
      "pair_id": "pair_70ca81b0",
      "page": "/hourly-dashboard",
      "desc": "Hourly Metrics Dashboard",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC07_hourly-dashboard.png"
      ],
      "ui_state": {
        "title": "🌸 Hourly Dashboard | ภาพรวม 24 ชั่วโมง + รายชั่วโมง",
        "h1": "Hourly Dashboard",
        "body_length": 19141,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1078
      },
      "ui_errors": [],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC08_budget-analysis",
      "pair_id": "pair_3253f52f",
      "page": "/budget-analysis",
      "desc": "Budget Decision Lab",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC08_budget-analysis.png"
      ],
      "ui_state": {
        "title": "🌸 Budget Decision Lab | วิเคราะห์การเพิ่มงบ + ผลต่อยอดขาย",
        "h1": "Budget Decision Lab",
        "body_length": 17882,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 839
      },
      "ui_errors": [],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC09_admin-control",
      "pair_id": "pair_fefcbd06",
      "page": "/admin-control",
      "desc": "Admin Control Panel",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC09_admin-control.png"
      ],
      "ui_state": {
        "title": "🛡️ Admin Control · WepAppOpusApi",
        "h1": "🛡️ Admin Control",
        "body_length": 1631,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 786
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC10_campaign",
      "pair_id": "pair_dec01ce5",
      "page": "/campaign",
      "desc": "Campaign Page",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC10_campaign.png"
      ],
      "ui_state": {
        "title": "Campaign Detail · Opus",
        "h1": "",
        "body_length": 41,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 867
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC11_V1-live-dashboard",
      "pair_id": "pair_71615c1a",
      "page": "/V1/live-dashboard",
      "desc": "V1 Live Dashboard (new URL pattern)",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC11_V1-live-dashboard.png"
      ],
      "ui_state": {
        "title": "🌸 Live — WepAppOpusApi (Public)",
        "h1": "",
        "body_length": 6687,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1283
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC12_V1-app",
      "pair_id": "pair_e40adcf7",
      "page": "/V1/app",
      "desc": "V1 Workspace SPA",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC12_V1-app.png"
      ],
      "ui_state": {
        "title": "WepAppOpusApi · Workspace",
        "h1": "",
        "body_length": 1173,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1024
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC13_V1-hourly",
      "pair_id": "pair_a5b84aaa",
      "page": "/V1/hourly",
      "desc": "V1 Hourly Dashboard",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC13_V1-hourly.png"
      ],
      "ui_state": {
        "title": "🌸 Hourly Dashboard | ภาพรวม 24 ชั่วโมง + รายชั่วโมง",
        "h1": "Hourly Dashboard",
        "body_length": 19141,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1075
      },
      "ui_errors": [],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC14_live-manual",
      "pair_id": "pair_3274f499",
      "page": "/live-manual",
      "desc": "Live User Manual",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC14_live-manual.png"
      ],
      "ui_state": {
        "title": "คู่มือการใช้งาน /live · Live User Manual",
        "h1": "📖 คู่มือการใช้งาน /live",
        "body_length": 10362,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1160
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c",
        "console.error: Failed to load resource: the server responded with a status of 500 ()",
        "console.error: [anomaly-expl] load failed: Error: 500 {\"ok\":false,\"error\":\"Invalid time value\"}\n    at api (https://adsfb.namnan.co.th/assets/live-core.js:139:11)\n    at async loadAnomalyExpl (https://adsfb.namnan.c"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC15_debug-manual",
      "pair_id": "pair_d67bc9ac",
      "page": "/debug-manual",
      "desc": "Debug Tool + Manual",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc_TC15_debug-manual.png"
      ],
      "ui_state": {
        "title": "📖 คู่มือ Debug Tool — WepAppOpusApi",
        "h1": "📖 คู่มือ Debug Tool",
        "body_length": 24035,
        "http_status": 200,
        "redirected_to_login": false
      },
      "api_state": {
        "duration_ms": 1025
      },
      "ui_errors": [
        "console.error: Failed to load resource: the server responded with a status of 404 ()"
      ],
      "verdict": "PASS"
    },
    {
      "tc_id": "TC16_health_endpoints",
      "pair_id": "pair_921f3e3e",
      "api": {
        "request": "/health, /ready, /bridge/status",
        "response": "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/api/tc16_health.json"
      },
      "api_state": {
        "health": 200,
        "ready": 200,
        "bridge": 200,
        "db_backend": "mysql"
      },
      "verdict": "PASS"
    },
    {
      "tc_id": "TC17_public_apis",
      "pair_id": "pair_92e674a2",
      "api": {
        "request": "multiple public APIs",
        "response": "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/api/tc17_public_apis.json"
      },
      "api_state": {
        "results": [
          {
            "name": "campaigns",
            "path": "/public/campaigns",
            "status": 200,
            "expect": 200,
            "pass": true,
            "duration_ms": 1723,
            "size": 44892,
            "sample": "{\"ok\":true,\"publicMode\":true,\"accountId\":\"2807991909289645\",\"campaigns\":[{\"id\":\"120239590971390590\",\"name\":\"UFO 50000w click ในวันที่ [8/3/2026] -\",\"status\":\"PAUSED\",\"effectiveStatus\":\"PAUSED\",\"dailyB"
          },
          {
            "name": "trends",
            "path": "/public/trends",
            "status": 200,
            "expect": 200,
            "pass": true,
            "duration_ms": 257,
            "size": 2453,
            "sample": "{\"ok\":true,\"days\":7,\"dateKeys\":[\"2026-07-26\",\"2026-07-27\",\"2026-07-28\",\"2026-07-29\",\"2026-07-30\",\"2026-07-31\",\"2026-08-01\"],\"topBySpend\":[{\"campaignId\":\"120230799572200590\",\"campaignName\":\"1 [buy]tsm "
          },
          {
            "name": "forecast",
            "path": "/public/forecast",
            "status": 200,
            "expect": 200,
            "pass": true,
            "duration_ms": 275,
            "size": 2904,
            "sample": "{\"ok\":true,\"total\":1,\"period\":{\"month\":\"2026-08\",\"daysInMonth\":31,\"daysElapsed\":1,\"daysRemaining\":30},\"historical\":{\"dates\":[\"2026-07-01\",\"2026-07-02\",\"2026-07-03\",\"2026-07-04\",\"2026-07-05\",\"2026-07-0"
          },
          {
            "name": "chats",
            "path": "/public/chats",
            "status": 200,
            "expect": 200,
            "pass": true,
            "duration_ms": 1285,
            "size": 4292,
            "sample": "{\"ok\":true,\"publicMode\":true,\"days\":7,\"source\":\"local\",\"totalConversations\":170,\"totalMessages\":1512,\"totalUnread\":1512,\"perPage\":[{\"pageId\":\"118404589562229\",\"pageName\":\"SJ88 Studio\",\"count\":110,\"unr"
          },
          {
            "name": "chat-inbox",
            "path": "/public/chat-inbox?limit=5",
            "status": 200,
            "expect": 200,
            "pass": true,
            "duration_ms": 301,
            "size": 4579,
            "sample": "{\"ok\":true,\"count\":5,\"totalUnread\":151,\"family\":\"all\",\"conversations\":[{\"conversationId\":\"t_1946759656035119\",\"pageId\":\"561567250563833\",\"pageName\":\"เรื่องเงินมีปัญหาใส่ชุดนักศึกษามาหาพี่\",\"senderId\":"
          },
          {
            "name": "hourly-metrics",
            "path": "/public/hourly-metrics?days=2",
            "status": 200,
            "expect": 200,
            "pass": true,
            "duration_ms": 1219,
            "size": 3460073,
            "sample": "{\"params\":{\"days\":\"2\",\"campaignId\":null,\"hourOfDay\":null,\"dow\":null,\"hasConversions\":false,\"minSpend\":null},\"summary\":{\"spend\":345.0099999999999,\"revenue\":4696,\"conversions\":4,\"clicks\":267,\"impression"
          },
          {
            "name": "chat-funnel",
            "path": "/public/hourly-metrics/chat-funnel?days=7",
            "status": 200,
            "expect": 200,
            "pass": true,
            "duration_ms": 876,
            "size": 480,
            "sample": "{\"days\":7,\"stages\":[{\"stage\":\"Welcome View\",\"count\":17,\"pct\":100},{\"stage\":\"Depth 2 Message\",\"count\":6,\"pct\":35.294117647058826},{\"stage\":\"Depth 3 Message\",\"count\":4,\"pct\":23.52941176470588},{\"stage\":"
          },
          {
            "name": "auth-session-noauth",
            "path": "/auth/session",
            "status": 401,
            "expect": 401,
            "pass": true,
            "duration_ms": 775,
            "size": 55,
            "sample": "{\"ok\":false,\"loginRequired\":true,\"authenticated\":false}"
          }
        ],
        "all_ok": true
      },
      "verdict": "PASS"
    },
    {
      "tc_id": "TC18_chat_poller_auth",
      "pair_id": "pair_a7d6faa1",
      "api": {
        "request": "admin/chat-poller/*",
        "response": "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/api/tc18_chat_poller.json"
      },
      "api_state": {
        "results": [
          {
            "name": "no-auth",
            "method": "GET",
            "status": 401,
            "expect": 401,
            "pass": true,
            "response": "{\"ok\":false,\"error\":\"unauthorized\"}"
          },
          {
            "name": "wrong-key",
            "method": "GET",
            "status": 401,
            "expect": 401,
            "pass": true,
            "response": "{\"ok\":false,\"error\":\"unauthorized\"}"
          },
          {
            "name": "correct-key",
            "method": "GET",
            "status": 200,
            "expect": 200,
            "pass": true,
            "response": "{\"ok\":true,\"running\":false,\"lastRunAt\":\"2026-08-01T08:14:29.547Z\",\"lastResult\":{\"pagesScanned\":67,\"pagesPersisted\":67,\"conversationsFound\":30,\"messagesInserted\":799,\"attributionsResolved\":0,\"durationM"
          },
          {
            "name": "stats",
            "method": "GET",
            "status": 200,
            "expect": 200,
            "pass": true,
            "response": "{\"ok\":true,\"pages\":{\"total\":67,\"active\":\"67\"},\"messages\":{\"total\":3673,\"convs\":102,\"pages\":13,\"latest\":\"2026-08-01T08:05:39.000Z\"},\"attribution\":{\"links\":3,\"camps\":2,\"pages\":2},\"daily\":{\"row_count\":32"
          },
          {
            "name": "sync-pages",
            "method": "POST",
            "status": 200,
            "expect": 200,
            "pass": true,
            "response": "{\"ok\":true,\"pages\":67,\"upserted\":67,\"deactivated\":0}"
          }
        ],
        "all_pass": true
      },
      "verdict": "PASS"
    },
    {
      "tc_id": "TC19_session_cookie_admin",
      "pair_id": "pair_f378f433",
      "screenshots": [
        "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/screenshots/tc19_session_admin.png"
      ],
      "api_state": {
        "session_status": 200,
        "session_user": "sj88",
        "session_role": "admin",
        "admin_status": 200
      },
      "verdict": "PASS"
    },
    {
      "tc_id": "TC20_logout_clears_session",
      "pair_id": "pair_a5c47a3e",
      "api": {
        "request": "/auth/logout + /auth/session",
        "response": "/workspace/sj88-verify/docs/reports/sj88_full_system_qa_20260801_152500/api/tc20_logout.json"
      },
      "api_state": {
        "logout_status": 200,
        "session_after_authenticated": false
      },
      "verdict": "PASS"
    }
  ],
  "summary": {
    "total": 20,
    "passed": 20,
    "failed": 0
  }
}