黑盒视角下,PSE 牌照博彩前端的三种工程范式:现代化自研 / 模板加速 / 老技术债 + 商业堆叠。焦点:哪个工程做得最好。
2026-05-13 补:克隆 ptgaming.ph 时发现它属于另一个范式 ── Cocos H5 游戏引擎站点(canvas WebGL UI,不是 DOM/Vue/React SPA)。10 维评分大部分不适用,单独成节论述,不并入三家排名。
window.dcodeIO = object),但实际用途仍待抓 WS 帧验证。
误差带 ±5。注意:错误监控维度仅 tablegame 经 runtime 实测,ArionPlay/BingoPlus 仅静态推断,证据强度不对称——这一维度的横比不严格。运行时验证后 tablegame 错误监控扣分(0 上报已证实)+ token 安全扣分(plain LS 已证实)+ PWA 离线加分(已证实可用),净微降到 60。tablegame 与 ArionPlay 在误差内不区分胜负——不同工程哲学的平手。BingoPlus 与前两家有真实代差。
tablegame 和 ArionPlay 实质平手(差 1 分在评分误差内),是不同工程哲学:tablegame 走自研深度路线——同源反代 + PWA primitives + 自定义 stale-asset 弹窗 + 顶层显式引入 protobuf runtime。ArionPlay 走克制路线——总 JS 仅 tablegame 的 1/3 (756 KB vs 2.28 MB)、外部 SDK 最少(仅 Adjust + CF Turnstile)、子域分离规范、路由 UUID 加固。两者各有上限。
BingoPlus 工程代差明显——Webpack 4 + Vue 2 + 15+ 第三方 SDK 堆叠 + 4 套 URL 前缀碎片化(路径中可见固定前缀 C66FM,归属/供应关系未证实)。从黑盒工程视角,与 tablegame / ArionPlay 有清晰代差;其商业表现与工程评分是不同维度的问题。
⚠ 本报告已经过多轮 codex 独立审稿(P1 收敛 5→3→2→2→1→1→1→0)+ 真登录 CloakBrowser 运行时实证。原"待验证"项现状:错误监控 0 上报 = 已证实 CRITICAL / PWA 离线 shell 可用 / token 落 plain localStorage = XSS 暴露面证实。
/api/* · 静态 82 / 热路径 5 ✓C66FM(归属未证实)<canvas id="GameCanvas"> 上的 WebGL 画布里 ── 没有 DOM 树可查、没有 CSS layout、没有 Vue/React Reactivity、bundle 系统是 Cocos 自家的 UUID 资产管理而非 webpack/vite chunks。强行打入 10 维雷达图 = 类别错位错误。本节单独论述。
PTGaming runtime evidence · cloakbrowser logged-in lobby boot引擎: Cocos Creator 2.4.9 (2020 年代版本, 当前主线 3.x)
渲染: WebGL canvas 1792×828, 全 UI 在 GameCanvas 内, DOM 几乎空
JS payload: cocos2d-js-min 1.17 MB + 9 jsList scripts + 8 plugin JS + 11 模块 JS
≈ 3.5 MB JS 总和 (压缩前)
Bundle 系统: 4 Cocos bundles (internal / main / resources / MoreGameIcons)
每个含 config.json + 134 packs + imports + natives (PNG/MP3/TTF)
UUID 22-char base64 compact 运行时解码为 36-char hex hyphenated
LocalStorage: 37 keys, 含 game_list 1.96 MB (整个游戏目录前端缓存!)
+ kSessionId 54 字符 (明文) + 字节跳动 TEA tokens
API host: io.playgame.zone 单 host
/api/v2/* (28 endpoints) + /bmp-*/v1/* (6) + /gray/v1/* (1)
── 3 套前缀 (BingoPlus 是 4 套)
第三方 SDK: 字节跳动 TEA + Geetest v4 + Adjust + AIHelp + Facebook
+ Google GSI + dgames + aisecurius = 8 个
灰度发布: index.<version>.html 切版 (2.7.1 / 2.7.2 / 2.7.2.3 / 2.7.2.4)
── 工程上是 staged rollout
PWA: 未观察到 manifest / SW
错误监控: 未观察到 Sentry / Bugsnag / DataDog
(有字节跳动 TEA 数据分析, 但不是错误上报)
| 维度 | tablegame | ArionPlay | BingoPlus | PTGaming | 说明 |
|---|---|---|---|---|---|
| Token / XSS 防护 | 3 | 4 | 3 | 3 | 四家都不防 XSS 读 LS。PTGaming kSessionId 54 字符落 plain localStorage,与 tablegame 同款暴露面 |
| 依赖卫生 (第三方 SDK 数) | 6 | 8 | 3 | 3 | PTGaming 8 个 SDK,与 BP 同量级,且含字节跳动 TEA 大量数据外流 |
| 错误监控 SDK | 1 | 3 | 4 | 2 | PTGaming 有 TEA 分析但无错误上报。PT/TG 同款 0 错误监控盲区 |
| API 设计纪律 | 5 | 7 | 4 | 6 | PT 单 host + 3 前缀版本化 (比 BP 4 前缀干净, 不如 AP 子域分离 + TG 全 /api/*) |
| PWA 离线能力 | 8 | 5 | 2 | 2 | PT 与 BP 同款无 PWA |
| 状态持久化重量 | 5 | 5 | 4 | 2 | PT 异常重:单 LS key (game_list) 占 1.96 MB ── localStorage 当数据库用。OFFLINE-first 思路但牺牲 LS 5MB 配额一半 |
| 灰度 / staged rollout | 3 | 3 | 3 | 7 | PT 唯一有 index.<version>.html 切版机制 (2.7.1 → 2.7.2.4 四档) |
/ index.html 是版本选择器,根据 LS 中 Gray_version 路由到 index.2.7.2.4.html 等具体 build。其他三家没看到这种机制。/home/devuser/ptgaming-clone/),cloakbrowser 真登录态启动,9/9 audit ALL PASS。源码与截图:data/audit_stage2/。
CasinoPlus runtime evidence · cloakbrowser logged-in /home boot框架: Next.js + React (useEffect 426x / useState 545x / createElement 237x) + next/router (1) + useRouter (2x) 状态管理: Redux-style central store (lt.store.getState() 54x) UI 库: Material-UI (MUI) ── MuiButton 25x / MuiAppBar 5x / MuiTypography 6x 构建: Webpack 4-era + content-hash chunk splitting runtime.69b51f9b5ce09691.js 包含 50 个 lazy chunk hash map 主 bundle: f2a29b21af0cfcde.js (8.0 MB) + main.4e7eb36ce9f4cbd6.js (8.0 MB) CSS: main.223f76fdd82c65af.css (963 KB) + 4 个小 chunk mirror 总大小: mobile 425 MB + desktop 467 MB ≈ 1 GB (两套独立!) RPC: 双层 ── ① @bufbuild/connect-es 1.6.1 (gRPC-Web binary, +proto) ② 自家 _fetch JSON wrapper (functionName + requestId + RQ99 envelope) client-es 用 protobuf-es 生成 typed message class (Ca extends l) 这是五家唯一用 protobuf binary 序列化 环境: bundle 内硬编码 4 个 env baseUrl PROD: fpms-nt.casinoplus.top INTERNAL: fpms-nt.fpms99.me TEST: fpms-nt-public.fpms88.me TEST_CF: fpms-nt-cf.fpms88.me (5 家中唯一 build-time multi-env, 其他家 runtime env detection) WebSocket: 14 个候选 WS host (cp-ws.casinoplus.top / cp-ws-qat / platform10/88/99 / client-api-uat/qat-stable/cf / casinoplus-test-dev.bewen.me 等) auto-fallback chain, 含 RetryLimit + "weak connection" popup LS auth: token (648-char JWT) + player (1760 chars) + sessionId (22 chars) + uKey + fingerPrint (38 KB) + cgRTN + jackpotRealTimeList 全 plain 无 SecureLS, 无 vuex-persistedstate 加密 ── XSS 直拿 第三方 SDK: 25+ 个 (5 家最重!) 静态 src: Taboola eid + Yahoo ytc + Twitter Ads uwt + Criteo dyn+ssl + Liftoff cdn-public + AppLovin s.axon + Cloudflare RUM beacon + Telegram WebApp = 8 src inline init: TikTok pixel × 11 (重复) + Snowplow + fbq + Liftoff + Criteo + axon AppLovin + gtag = ~17 inline 额外: PostHog (posthog.casinoplus.top) 全程 event 上报 错误监控: PostHog (analytics 类) ── 无 Sentry / Bugsnag / DataDog 自家 _httpStatusFromError 包装把 connect-es code 映射成 400/401/403/404 PWA: 有 /home/service-worker.js + manifest.json (manifest 配置不全: start_url / scope 被浏览器忽略, 不构成真 PWA installable) Cloudflare: 全栈托管 (CF Pages + Workers + RUM beacon) fpms-nt 上游 ACAO:* 对服务器 IP 开放, 真用户 IP CORS 行为不一致 (Cloudflare IP rule 区分) 移动适配: UA 切分两套独立 bundle (mobile + desktop 不同 hash, 总大小 ~1 GB) 其他四家是 responsive design 单 bundle
| 维度 | tablegame | ArionPlay | BingoPlus | PTGaming | CasinoPlus | 说明 |
|---|---|---|---|---|---|---|
| Token / XSS 防护 | 3 | 4 | 3 | 3 | 2 | 5 家全部裸 LS。CasinoPlus 最差:JWT 648 字符 + fingerPrint 38KB + player profile 全 plain,且无任何 SecureLS / 加密层。XSS 一拿到底 |
| 依赖卫生 (第三方 SDK 数) | 6 | 8 | 3 | 3 | 1 | CasinoPlus 5 家最差:25+ tracker SDK,含 TikTok 11 个重复 pixel + Snowplow + fbq + Liftoff + Criteo + AppLovin axon + Taboola + Yahoo + Twitter Ads + Cloudflare RUM + Telegram WebApp + PostHog + gtag。ad-tech 堆叠灾难 |
| 错误监控 SDK | 1 | 3 | 4 | 2 | 2 | CasinoPlus 有 PostHog event tracking 但不是错误上报。无 Sentry/DD/Bugsnag。和 TG/PT 同款 critical 盲区 |
| API 设计纪律 | 5 | 7 | 4 | 6 | 9 | CasinoPlus 5 家最佳:@bufbuild/connect-es 1.6.1 gRPC-Web binary + protobuf-es 生成 typed client + 多 env baseUrl 配置 (PROD/INTERNAL/TEST/TEST_CF)。唯一 type-safe protobuf binary 协议 |
| PWA 离线能力 | 8 | 5 | 2 | 2 | 4 | CasinoPlus 有 SW + manifest 但配置不完整 (start_url/scope 被忽略),半成品 PWA |
| 状态持久化重量 | 5 | 5 | 4 | 2 | 3 | CasinoPlus 20 个 LS key, fingerPrint 单 key 38KB + cgRTN 13KB + jackpotRealTimeList 6.6KB。比 PT 1.96MB 单 key 好但比 TG/AP/BP 重 |
| 灰度 / staged rollout | 3 | 3 | 3 | 7 | 4 | CasinoPlus 不像 PT 有 index.<version>.html 切版,但 bundle 内有 4 env 硬编码可 build-time switch |
application/grpc-web+proto 框架二进制,message class 由 .proto 自动生成 (class Ca extends l { static typeName="CMS.CpmsGetTicketEventRequest"; static fields=Ue.util.newFieldList(()=>[...]) })。序列化错误 schema 不匹配会在编译时挡掉,比 JSON-only 三家工程纪律高一档。fpms-nt.casinoplus.top / INTERNAL fpms99.me / TEST fpms88.me / TEST_CF cf-fpms88.me),不需要 runtime env-var。这意味着可以一份 build 切多环境部署。其他四家是 runtime 检测。SyntaxError: 'maxDepth' has already been declared)+ Snowplow + fbq + Liftoff + Criteo + AppLovin axon + Taboola eid + Yahoo ytc + Twitter Ads uwt + Cloudflare RUM beacon + Telegram WebApp + PostHog + gtag。页面加载 25+ 个第三方域 = 性能 / 隐私 / 兼容性三杀。setLocalItem("wsRetryLimit", true) + Lc() 弹整屏遮罩 + REFRESH + CONTACT CS 按钮。移动端 4G/5G 切换、Wi-Fi 弱信号、应用切前后台 全会触发。克隆站第一轮就被这个弹窗卡住,必须 bundle patch 杀掉。d.l = (e, r, t, n) => {...})。同期 industry standard 是 Webpack 5 module federation 或 Vite Rollup。技术债与 BingoPlus Webpack 4 / Cocos 2.x 同代。/home/devuser/casinoplus-clone/),cloakbrowser 真登录态启动 ZIPHEA CONTENTO MIRANO / ID:1059170117 / ₱10.10。bundle patch 杀 wsStatus + 22 inline tracker 剥离 + 9 src tracker 剥离 + DOM script.src 拦截 + 静态资源 upstream 代理 + demo login (/__demo_login) 一键登录。E2E 测试 PASS:0 page errors / 0 chunk 4xx / 263 image / React appChildCount=6。预览部署:casinoplus.preview.candygame.cloud。
tablegame.ph / ArionPlay / BingoPlus / PT Gaming / CasinoPlus · 16 维度 + 7 维加权评分(codex-validated) · 每个 claim 都有 evidence boundary 标注(runtime 实证 / 静态推断 / 推断未实测)
本节经 7 轮 codex-anywhere 对抗性 review 修订(4P1+4P2+1P3 → 0P1+0P2+1P3 PASS)。查看完整 review 历史 →
| 项目 | URL | 测试账号 | 关系 | 证据基础 |
|---|---|---|---|---|
| tablegame.ph (TG) | tablegame.ph |
9627550835(用户授权) | 自家产品 | cloakbrowser 真登录 2026-05-12, 4813 outbound / 11 routes / 3 错误注入 / 1 Sentry probe |
| ArionPlay (AP) | arionplay.com |
9627550835 / ₱15 | 第三方克隆 | 17 路由 audit ALL PASS (Vue mount ✓ / 0 4xx / 0 console err) |
| BingoPlus (BP)* | bingoplus.com |
(template 源头, 未实测登录) | 第三方克隆(模板源头) | 静态 bundle 分析(runtime 未验证) |
| PT Gaming (PT) | ptgaming.ph |
9627550835 (OTP only) | 第三方克隆 | 阶段 2 logged-in lobby 9/9 audit PASS |
| CasinoPlus (CP) | casinoplus.com.ph |
9629120357 / casinoplus | 第三方克隆 | 5/14 E2E PASS (0 page err / 0 chunk 4xx / 263 image) |
| 项目 | 框架 | 构建 | 状态管理 | UI 库 | 代际 |
|---|---|---|---|---|---|
| TG | Vue 3 | Vite | Pinia | (自研 / 未确认) | 2024 主流 |
| AP | Vue 3 | Vite | Pinia + SecureLS AES | Vant + vben-admin-pro 模板 | 2024 主流 |
| BP | Vue 2 | Webpack 4 | Vuex + vuex-persistedstate + SecureLS fingerprint | vue-element-admin(EOL) | 2018-2020 老技术 |
| PT | Cocos Creator 2.4.9 | cocos2d-js 自家 bundle | LS 当数据库 | canvas WebGL(无 DOM UI) | 2020 老引擎 |
| CP | Next.js + React | Webpack 4-era | Redux 风格(lt.store) | Material-UI (MUI) | 2022-2023 主流但 build 老 |
<canvas id="GameCanvas"> 里渲染)| 项目 | 主 JS bundle | CSS | 总 mirror | 注释 |
|---|---|---|---|---|
| TG | ~2-3 MB(未实测原始大小) | ~500 KB | (无 mirror) | Vite tree-shake 较干净 |
| AP | ~3 MB main + lazy chunks | ~600 KB | ~200 MB | Vite + 路由级 lazy load |
| BP | ~5 MB main + 多 lazy chunk | ~1 MB | (模板,未完整克隆) | Webpack 4 content-hash |
| PT | cocos2d-js-min 1.17 MB + 9 jsList + 8 plugin = ~3.5 MB JS + 4 bundles 资产 | 0(CSS 在 atlas) | 48 MB / 687 文件 | UUID-coded 资产管理 |
| CP | f2a29b21af0cfcde.js 8.0 MB + main.4e7eb36ce9f4cbd6.js 8.0 MB = 16 MB 主路径 | 963 KB + 4 chunk | mobile 425 MB + desktop 467 MB ≈ 1 GB | 双 mirror UA-split |
| 项目 | 协议 | wire 格式 | URL 风格 | 客户端代码生成 | endpoint 数量 |
|---|---|---|---|---|---|
| TG | REST + JSON | application/json | /api/* 单 namespace | 手写 | 82 静态定义(本次 11 路由 audit 触达 5) |
| AP | REST + JSON | application/json | 子域分离: apih5.arionplay888.com API / static.arionplay.com 资产 | 手写 | 未数 |
| BP | REST + JSON | application/json | 4 套并存: /cdn/C66FM/ + /_glaxy_c66_/ + /_front_api_/ + /api/v*/ | 手写 | 未数 |
| PT | REST + JSON + 自家 token | application/json | 3 套前缀: /api/v2/* + /bmp-*/v1/* + /gray/v1/* | 手写 | 35+ |
| CP | gRPC-Web + JSON wrapper 双层 | application/grpc-web+proto (binary) + application/json | Twirp 风格 <package>.<Service>/<Method> | @bufbuild/protobuf-es 自动生成 typed class | 50+ chunks |
@bufbuild/connect-es 1.6.1 + @bufbuild/protobuf-es 自动生成 typed client class,编译时挡 schema 错配。5 家工程纪律最高的协议层选择。/bmp-*/v1/* + /gray/v1/* 灰度通道)/api/* namespace 最简洁,但 11 路由 audit 触达 5/82 endpoint = 6% audit 覆盖率。未触达 ≠ dead,需 reachability/ownership 分析才能下结论| 项目 | 环境切换机制 | 硬编码 env 数 |
|---|---|---|
| TG/AP/BP/PT | runtime env detection(域名匹配) | N/A |
| CP | build-time 4 env baseUrl 硬编码(PROD fpms-nt.casinoplus.top / INTERNAL fpms99.me / TEST fpms88.me / TEST_CF cf-fpms88.me)+ runtime switch | 4 |
| 项目 | LS 加密 | token 暴露 | XSS 后果 |
|---|---|---|---|
| TG | plain LS(authStore) | 直接可读 | 账号被盗 |
| AP | SecureLS AES(encryptionSecret 硬编码 UUID E35E2975-...) | 加密,但 secret 在 bundle 里 grep 可拿 | 需先 reverse bundle,仍可解 |
| BP | SecureLS + 浏览器指纹动态 key | AES + key 漂移 | 强一些,但指纹漂移 = 用户体验灾难(清缓存/换设备/浏览器升级触发强制登出) |
| PT | plain LS(kSessionId 54 字符直接落 LS) | 直接可读 | 账号被盗 |
| CP | plain LS + 还塞 fingerPrint 38 KB | 全套用户身份明码 | 5 家最差:token (648 char JWT) + player (1760 字符) + uKey + sessionId + fingerPrint 38 KB 一锅端 |
| 项目 | 静态 <script src> | 内联 init 块 | 总 SDK 估算 |
|---|---|---|---|
| TG | 6 | 少 | 6 |
| AP | 2(Adjust + CF Turnstile) | 0 | 2(5 家最克制) |
| BP | 15+ (sensorsdata, Adjust, AIHelp, Facebook, ...) | 多 | 15+ |
| PT | 8 (字节 TEA, Geetest, Adjust, AIHelp, Facebook, Google GSI, dgames, aisecurius) | 0 | 8 |
| CP | 9 (Taboola + Yahoo + Twitter Ads + Criteo + Liftoff + AppLovin + CF RUM + Telegram WebApp + ...) | 22(TikTok pixel × 11 + Snowplow + fbq + Liftoff + Criteo + axon + gtag) | 25+(5 家最重) |
Identifier 'maxDepth' has already been declared SyntaxError 实测)| 项目 | Sentry/DD/Bugsnag | analytics SDK | 实际错误上报 | evidence |
|---|---|---|---|---|
| TG | 0(无 onerror/onunhandledrejection 监听) | (未确认) | 0 | runtime 实证 ✓ |
| AP | 0 | Adjust | 0 | runtime 实证 ✓ |
| BP* | 0 | sensorsdata 4 个 | 未观测(runtime 未验证) | static inference |
| PT | 0 | 字节 TEA(分析非错误) | 0 | runtime 实证 ✓ |
| CP | 0 | PostHog + Snowplow + gtag | 0 | runtime 实证 ✓ |
| 项目 | WS host | fallback 数 | 上游策略 |
|---|---|---|---|
| TG | (未公开) | (未确认) | (未确认) |
| AP | (未观察到 WS) | - | 推测全 HTTP |
| BP | 1-2 个(推测) | - | 标准 |
| PT | (Cocos 内部, 无 wss 流量) | - | 走 HTTP 拉 game_list |
| CP | 14 个 host fallback chain | 14 | cp-ws / cp-ws-backup / cp-ws-qat / qat-backup / uat-backup / client-api-uat/qat/qat-stable/cf / fpms-nt-http.platform10/88/99 / casinoplus-test-dev.bewen.me / dos88.me |
| 项目 | 移动/桌面策略 | 资产 CDN | 优化 |
|---|---|---|---|
| TG | Responsive 单 bundle | 同域 | 标准 |
| AP | Responsive 单 bundle | static.arionplay.com 子域 | Vite tree-shake |
| BP | Responsive 单 bundle | 同域 | Webpack content-hash |
| PT | Responsive (Cocos 自适应 canvas) | static.playtime.ph | UUID-coded packs |
| CP | UA-split 双独立 bundle | cp-images.casinoplus.live 独立 CDN | webp / svg + chunk split |
2018-2020 主流,2024 一般主推 responsive + dynamic import + container queries。
| 项目 | SW | manifest | 离线 reload | 评价 |
|---|---|---|---|---|
| TG | ✓ | ✓ | ✓(has_app=true) | 5 家最完整(runtime 实证) |
| AP | (部分) | ✓ | (未实测) | 半成品 |
| BP | × | × | × | 无 PWA |
| PT | × | × | × | Cocos 走 native WebView 模式 |
| CP | ✓ (有 service-worker.js) | ✓ (但 start_url + scope 被浏览器忽略) | (未实测) | 半成品(配置不全无法 installable) |
| 项目 | 机制 | 评价(基于当前证据) |
|---|---|---|
| TG/AP/BP | 未观察到 | 证据不足,不能确认 absence |
| PT | index.<version>.html 切版(2.7.1 / 2.7.2 / 2.7.2.3 / 2.7.2.4 四档),根 / index.html 是版本选择器读 LS Gray_version 路由 | runtime 实证 ✓ 5 家唯一确认存在 |
| CP | bundle 内硬编码 4 env baseUrl,可 build-time switch(非 runtime 灰度) | 半 — 配置维度有,但缺路由级流量分流证据 |
| 项目 | 反爬手段 | 我们的应对 |
|---|---|---|
| TG | (未观察到) | 直接抓 |
| AP | CF Turnstile | 普通 cloakbrowser 找不到 iframe checkbox → 切 Scrapling.StealthyFetcher + solve_cloudflare=True(camoufox 引擎自带求解器),1 次过 |
| BP | (未观察到) | 直接抓 |
| PT | Geetest v4 + aisecurius | 用户提供 OTP 登录后的 storage_state.json 绕过 |
| CP | (主要靠 Cloudflare IP rate / CORS by IP) | Server IP curl 通,真用户 IP 走代理桥 |
| 项目 | API | XSS | 错误 | 依赖 | Bundle | PWA | 灰度 | 加权得分 |
|---|---|---|---|---|---|---|---|---|
| TG | 5 | 3 | 1 | 6 | 7 | 8 | 3 | 4.55 |
| AP | 7 | 4 | 1 | 8 | 7 | 5 | 3 | 5.25 |
| BP* | 4 | 3 | 1 | 3 | 4 | 2 | 3 | 2.95 |
| PT | 6 | 3 | 1 | 3 | 6 | 2 | 7 | 3.85 |
| CP | 9 | 2 | 1 | 1 | 3 | 4 | 4 | 3.85 |
计算公式(AP 为例)0.25×7 + 0.20×4 + 0.15×1 + 0.15×8 + 0.10×7 + 0.10×5 + 0.05×3
= 1.75 + 0.80 + 0.15 + 1.20 + 0.70 + 0.50 + 0.15
= 5.25
Tie-break PT vs CP: 两家在不同维度互有胜负 —— CP 赢 API (9 vs 6),PT 赢灰度 (7 vs 4),其余接近。3.85 是 honest tie,强行排序不增加信息量。
反直觉:CP 协议层最先进(API 9)但 XSS(2)+ 依赖卫生(1)双拖累,跟老技术 PT 持平。"现代化协议 + 重广告堆叠" 双面性是 CP 的画像。
| 项目 | 团队规模推断 | 工程文化 | 决策来源 |
|---|---|---|---|
| TG(自家) | 中等 | 务实,本次 audit 仅触达 5/82 endpoint(覆盖率 6%,实际使用率需 reachability 分析) | 偏产品驱动,工程慢 |
| AP | 中等 + 模板加速 | 5 家最克制(2 SDK + AES 加密 + 子域分离),可能受 vben-admin-pro 团队影响 | 工程驱动 |
| BP | 大团队 + 长历史 | 4 套 URL prefix 并存 = 多代际叠加未合并(缺乏 consolidation 证据) | 历史包袱 |
| PT | 中等 + 游戏团队 | OFFLINE-first + 灰度切版表明运维成熟,但 Cocos 2.x = 老技术 | 运维驱动 |
| CP | 大 + 市场强势 | 协议先进 + 25+ tracker = 市场拍板装一堆 SDK | 市场驱动,工程妥协 |
| 维度 | 最佳 | 最差 | 备注 |
|---|---|---|---|
| API 协议设计 | CP (protobuf binary type-safe) | BP (4 套并存) | CP 唯一 type-safe |
| XSS 防护 | AP (SecureLS AES) | CP (plain LS 全套身份) | 但 AP 也只挡被动 dump |
| 错误监控 | (现有证据均未显示上报能力) | 4 家 runtime 实证 = 0 上报;BP 仅静态推断未见痕迹(runtime 待验证) | §10 rubric: 不做基建成熟度猜测式排序,仅按直接观测;BP 为低置信度暂定 |
| 依赖卫生 | AP (2 SDK) | CP (25+ SDK + TikTok×11) | AP 最克制 |
| Bundle 健康 | TG (Vite tree-shake) | CP (16 MB main) | CP 失控 |
| PWA | TG (运行时实证完整) | BP / PT (无) | CP 半成品 |
| 灰度发布 | PT (index.version.html 切版, runtime 实证) | TG/AP/BP/CP 未观察到 client-side 灰度机制(不等于不存在) | PT 是唯一直接观测到的 |
| 移动适配 | AP / TG (Responsive 简洁) | CP (UA-split 1 GB 双倍) | 2018-2020 老 pattern |
| WS 设计 | (无明显赢家) | CP (14 host fallback 过度工程) | CP 内部域名泄漏 |
<script src> 或 document.createElement('script') 注入,无 iframe sandbox / Trusted Types CSP。任何一个 SDK 被劫持 = full page 受控integrity= 属性 ✓):5 家第三方 <script src> 标签均未带 integrity= SHA hash 属性。CDN 被劫持时恶意脚本直接生效Manifest: property 'start_url' ignored)| 维度 | 当前 5 家中谁最近 | 理想做法 |
|---|---|---|
| 框架 | TG/AP (Vue 3 + Vite) | 二选一: React 18 + Next.js App Router + RSC 或 Vue 3 + Vite/Nuxt 3(CP 已选 Next.js 但仍跑 Webpack 4-era build,未升 RSC) |
| RPC | CP (protobuf type-safe) | gRPC-Web + protobuf-es + Connect protocol |
| 状态加密 | AP (SecureLS AES UUID secret) | httpOnly refresh cookie + memory-only access token + 敏感 auth data 不落 LS —— 客户端加密(SecureLS/WebCrypto)只防被动 LS dump,不防主动 XSS,不能作为敏感数据的护身符;WebCrypto 只能用于本地非敏感偏好/缓存数据 |
| 错误监控 | (无) | Sentry + onunhandledrejection + Performance API |
| 依赖卫生 | AP (2 SDK) | ≤ 5 SDK, 每个 SRI 校验, CSP strict |
| Bundle | TG/AP (~3 MB) | < 500 KB initial, route-level lazy load |
| PWA | TG | full SW + manifest installable + offline fallback |
| 灰度 | PT (index.version.html) | feature flag (GrowthBook/LaunchDarkly) + CDN A/B |
/home/devuser/tablegame-clone-research/data/monitoring_test/ ← TG runtime /home/devuser/arionplay-clone/ ← AP source /home/devuser/bingoplus-monitor/ ← BP source /home/devuser/ptgaming-clone/data/audit_stage2/ ← PT logged-in audit /home/devuser/casinoplus-clone/ ← CP source + storage_state + serve_full_clone.py ~/.claude/projects/-home-devuser/memory/clone-sites-overview.md ← 跨项目沉淀
| Pass | P1 | P2 | P3 | Verdict | Key findings |
|---|---|---|---|---|---|
| 1 | 4 | 4 | 1 | FAIL | weighted score 算错 4/5; TG error 单独最差矛盾 §4.1; "Vue+RSC" 不存在; AP SecureLS UUID 不解决 XSS |
| 2 | 2 | 2 | 0 | FAIL | §15 "清 77 dead" 重现; §15 "CP 加 SecureLS" 自相矛盾; rubric 编造 "Sentry-ready"; BP runtime claims 未标静态 |
| 3 | 1 | 3 | 0 | FAIL | §14 PWA "4 家 manifest 不全" vs §7 BP/PT 无 manifest 矛盾; "6% 命中率" = 系统事实重复; SRI evidence 写成 header 实测; 30-40% 数字无依据 |
| 4 | 1 | 2 | 1 | FAIL | §2 table cell 还是 "热路径仅 5"; §15 WebCrypto 列入 auth 方案; §8 "没有" vs "未观察到"; §10 "5 维" 实际 7 维 |
| 5 | 2 | 1 | 0 | FAIL | §15 给 AP 仍带 `+ WebCrypto subtle`; §13 仍说 "6% 热路径命中率"; §4.1 末段 BP 推断当 observation value |
| 6 | 1 | 1 | 0 | FAIL | BP `实际错误上报 = 0` 应改 `未观测`; §6 CDN 流量翻倍 / cache 命中率错标为已实测 |
| 7 | 0 | 0 | 1 | PASS | 仅剩摘要层 BP runtime/静态分级 P3 表述 |
| 维度 | tablegame.ph | ArionPlay | BingoPlus | 说明 |
|---|
tablegame.ph:/assets/index.CvP0IUjf.1778578846276.js。Vite content-hash + 毫秒 timestamp。修订:Vite 本身就是 content-hash 输出,timestamp 不是"修复 Vite 缺陷",而是"每次 release 全量失效"的版本化策略——副作用是每次发版旧 chunk 立刻 404(这也是为什么需要 stale-asset 弹窗,见 #5)。属于策略选择不是技术突破。
ArionPlay:/js/index-B2rCSkPk.js。同样 Vite content-hash,不带 timestamp = 保留旧版本兼容性(哪些没变的 chunk 旧 URL 仍可用)。两种策略各有利弊。
BingoPlus:/cdn/C66FM/static/js/chunk-vantUI.fd376545.js。Webpack 4 vendor split 命名(vendors~A~B 是 webpack-cli 2017 风格)。Webpack 4 已 EOL,安全更新 2022 年停止——这是真问题。
tablegame.ph main.js · 关键字 grepcreateApp: 1 ✓
provide(): 6 ✓ (Composition API)
onUnmount: 1
watch(): 29
computed(): 7
try{: 140 ✓ (错误处理密度极高)
await: 117 ✓ (async-first)
localStorage: 50
IndexedDB: 18 ✓ (大量结构化客户端存储)
console.log: 0 ✓ (production 清干净)
console.error: 1
tablegame:Vue 3 Composition + 140 try / 117 await / 0 console.log(grep 旁证,不严格 — 已在方法论局限说明)。可观察事实:bundle 体现 async-first + 防御性编码风格。
ArionPlay:Vue 3,用 vben-admin-pro 开源模板,SecureLS 2 次出现做 Pinia 持久化加密。模板红利让基础不差,但你也只能拿到模板的天花板。
BingoPlus:Vue 2 + Vuex + vue-element-admin 血统。Vue 2 已 EOL(2024 年起停安全更新)。2026 年还在 ship Vue 2 = 主动累积技术债。
tablegame:bundle 内出现 82 个 /api/* 端点,全部同源。配置 apiHost:"/lobby", baseURL:"/state"——意味着 nginx/反代层做了路径切分(lobby = 大厅,state = 状态),前端不感知后端拓扑。浏览器零跨域、无 CORS、无第三方 cookie 问题。
tablegame /api endpoints 节选 (82 个)/api/user/{login,register,balance,withdraw,refreshToken,tokenLogin,...}
/api/game/{detail,getGameUrl,getState,getGameListWithCache}
/api/jackpot/{amount,games,info,ranking,winning_info,...}
/api/mail/{list,read,readAll,deleteAllMail,...}
/api/luck_wheel/{info,list,my_list,receive_reward}
/api/payment/list /api/wallet /api/bet_task
/api/fcm/auth_push /api/fb/pixel /api/preload
ArionPlay:API 走 apih5.arionplay888.com 子域,静态走 static.arionplay.com。注:arionplay888.com 与主 arionplay.com 是不同注册域(同 .com TLD),是否用于流量切换 / 灾备需运维信息验证。三段式 CDN 切分干净,但跨子域 cookie/CORS 是要处理的成本。
BingoPlus:4 套前缀同时跑——/cdn/C66FM/ + /_glaxy_c66_/ + /_front_api_/ + /api/v*/。C66FM 作为固定前缀出现,归属未证实。本节结论仅基于 "4 个 URL 前缀并存" 这一可观察事实。
C66FM 的具体性质如何,BingoPlus 前端 URL 路径碎片化(4 个前缀)反映出架构演进缺整体设计。tablegame 每个端点都在 /api 下,路径语义至少统一。tablegame:没有 localStorage 加密(bundle 0 个 SecureLS / CryptoJS 引用)。[已运行时验证] 真登录后查 localStorage 实际有 authStore key(plain text,未加密)。本次会话未观察到 httpOnly auth cookie,但不能完全排除存在并行 cookie/session 路径——可证伪的下一步是抓所有 outbound 请求 header 的 cookie 字段。即便如此,auth token material 已确认暴露在 plain localStorage——任何 XSS 漏洞能直接读走。最佳实践应该是 httpOnly cookie + 严格 CSP + 降权 token。这是真问题不是优点。
ArionPlay:SecureLS AES 加密 Pinia store。但 encryptionSecret 是 bundle 里硬编码 UUID E35E2975-8A3E-43F0-89F9-4F3FE8B85E07——可 grep 拿到。实际等于 obfuscation 不是 encryption,对 XSS 同样无防护,且付出 AES 性能开销。
BingoPlus:SecureLS + 浏览器指纹动态 key——理论上更难破解,但实际埋雷:用户清缓存/换设备/浏览器升级 → 指纹漂移 → AES key 变化 → 旧 token 解不开 → 强制登出。"我什么都没干怎么就要重新登录"工单的来源。
authStore key 真落在 plain localStorage,未观察到 httpOnly auth cookie ——三家都不防 XSS 读 LS 已证实。真正的解法在 httpOnly cookie + 严格 CSP + 降权 token。tablegame:HTML 头部 inline 一段精致代码:
tablegame index.html · 自动刷新弹窗function isAssetJsFile(url) { /* 严格匹配 /assets/*.js */ }
window.addEventListener("error", (event) => {
if (event.target.tagName === "SCRIPT" && isAssetJsFile(event.target.src)) {
showUpdateModal(); // 弹"有新版本,需刷新"
event.stopPropagation();
}
}, true);
window.addEventListener("unhandledrejection", (event) => {
const url = event.reason?.target?.src
|| event.reason?.message?.match(/(https?:\/\/[^\/]+\/assets\/.*?\.js)/)?.[1];
if (isAssetJsFile(url)) showUpdateModal();
});
// sessionStorage 防循环刷新
解决一个真实问题:用户长时间停留 + 后端发版 = lazy chunk 404。直接在 HTML 头部 inline,不等 Vue 启动,用户体验损失最小。是面向线上场景而设计的细节。
window.addEventListener('error',...)),不存在通用错误上报 SDK / window.onerror property hook / reporting pipeline。这两者是不同概念——asset-404 监听只 catch 资源加载失败并弹窗,不会把 JS 异常 / unhandled rejection / 业务异常上报到任何后端。ArionPlay:未发现等价 stale-asset 恢复机制;lazy chunk 失败时的用户体验需运行时验证。
BingoPlus:依靠 sensorsdata + GTM 做行为分析,但 JS 错误监控薄弱。15+ 第三方 SDK 本身就是错误源。
tablegame:[已运行时验证] ServiceWorker registration scope = https://www.tablegame.ph/,state = activated,script = sw.js。IndexedDB 实际有 2 个数据库(sw-storage + ss_plugin_cache_pro)。离线 reload 实测成功 — 断网后页面 title 保留、#app.__vue_app__ 仍存在(SPA shell 可离线启动,业务数据当然没有)。这是三站里唯一有真离线 shell 的。
ArionPlay:有 manifest,ServiceWorker 注册较弱,bundle 内未发现 IndexedDB API 调用。
BingoPlus:未发现 manifest / SW / IDB 集成。完全是"网页式"打开。
tablegame · 6 个业务/功能性 SDK + 1 个调试工具 = 7 个外部集成:
ArionPlay:最简——Adjust + CF Turnstile + 自家 SDK。
BingoPlus:15+ SDK 堆叠——getblue、trafficwisehub(3 个脚本!)、Bing Ads、Criteo、Yahoo Analytics、Yahoo Ads、Zoho SalesIQ、Google ReCaptcha、Google identity、apis.google.com、sensorsdata、vrtxdata、CloudflareInsights、readerescape、imgscache.com 独立图片 CDN……
tablegame:同源 favicon + apple-touch-icon 9 种尺寸打满,PWA icon 9 个尺寸,本站 /share/seo.jpg?v=2 做 OG。
ArionPlay:static.arionplay.com 独立资产域名,CDN 解耦。
BingoPlus:用户头像走 pub.imgscache.com 第三方图片缓存服务,invite-share 图走 bingoplus.ph 备域名,多处 googleusercontent.com 直接 hotlink。
tablegame:HTML 单独引入 /js/protobufjs.min.js(111KB Long.js + protobuf 编解码核心),bundle 主体里有 wsUrl 字段。[已运行时验证] 登录后 window.dcodeIO = object(Long.js 真挂载到 window),但 window.protobuf 仍是 undefined(protobuf namespace 未暴露)。这意味着 Long.js 被加载但 protobuf 的实际使用未在 window 域可见。继续不能证明是自研协议还是某个上游游戏 SDK 内置的 protobuf 依赖。需要抓 WS 帧才能定论。
ArionPlay 和 BingoPlus:未发现 protobufjs。但同样不能证明是否在 iframe 内部引入。
tablegame:单一 codebase + responsive + PWA standalone 模式(HTML 头 viewport-fit=cover)。
ArionPlay:桌面 UA 与移动 UA 返回的 asset graph 与 bundle 命名不同,提供两套独立 build。重,但移动端体验更精细化。
BingoPlus:同样的双 build 模式(PC bundle game_bp_pc_1_1000_*.js vs 移动 bundle game_bp_mobile_*),多个 game-runtime bundle。
/assets/*.js 触发。被 lazy chunk 404 投诉打过脸的设计。这是真亮点(虽然只覆盖 .js)。/lobby /state 切分。注:CSP 仍需独立设计,不因同源而自动解决。端点命名设计另一回事(见下文真问题)。set_offline(true) 后 reload,has_app=true + title 保留,离线 SPA shell 可启动(业务数据当然没有)。剩余未知:多路由离线覆盖范围 / Workbox 缓存策略未深入。但起码 ArionPlay 弱、BingoPlus 无。/js/protobufjs.min.js 111KB + 运行时 wsUrl 字段。注意:能 confirm 的是"交付产物中存在 protobuf runtime"。无法 confirm 是自研协议还是某游戏 SDK 内置依赖(很多游戏 SDK 用 protobuf)。runtime probes (登录后)window.Sentry : undefined
window.__SENTRY__ : object (空 SDK 占位 carrier, sentryClient: false)
window.DD_RUM : undefined
window.Bugsnag / Rollbar : undefined
window.newrelic / LogRocket : undefined
window.heap : undefined
window.onerror property hook : NOT set (注 1)
window.onunhandledrejection hook : NOT set (注 1)
注 1: 站点存在 asset-404 专用 addEventListener (用于 stale-asset 弹窗),
但 (a) 只 catch 资源 404 (b) 只触发"刷新"UI (c) 不向任何后端上报。
缺失的是: 通用错误上报 SDK / 全局 onerror property hook / reporting pipeline。
诱饵错误后 8s 内的新 outbound 请求4 种诱饵 probe:
1. throw new Error("CANARY_SYNC_001") ← 用 dispatchEvent 再触发 error
2. Promise.reject(new Error("CANARY_002")) ← 不 catch, 触发 unhandledrejection
3. window.__undefined_xyz__.foo() ← reference error
4. 调 window.Sentry.captureException (若 Sentry 存在)
← 由于 window.Sentry = undefined, 这步即跳过 (探针本身验证 Sentry API 不可达)
→ 8s 内新增 8 个 outbound 请求, 全部是 salesmartly 资源加载
→ 0 个匹配 RUM/error-host 模式
→ 全程 outbound 总数 4813 / RUM 匹配数 0
SLA 红线 critical fail 已证实。线上前端报错完全黑盒,只能靠用户截图反馈。必须接 Sentry / DataDog RUM。
chunk_eruda.*.js import 自主 bundle index.CvP0IUjf.*.js。知道触发手势的人就能拉到 500KB 调试工具检查 prod localStorage / 网络请求——是 reverse engineering / 攻击面的 free attack surface。真正的做法是:构建时 NODE_ENV=production 完全剥离 eruda,或服务端 flag 控制能否拉取。
/api/* 热路径只有 5 个:/lobby/api/{preload, preloadcheck, game/getGameListWithCache, jackpot/games, fb/pixel}。82 个 endpoint 是 bundle 静态定义上限,不是冷启动热路径。原报告把"82 个累积"作为攻击点偏重了——降级为"静态定义里有 82 个,包括单复数并存等遗留"。
bundle 内仍有 endpoint 命名遗留问题/api/user/login /api/user/login_register /api/user/tokenLogin
/api/user/recents /api/user/game/recents ← 重复
/api/user/favorite /api/user/favorites ← 单复数并存
需要 audit 全 82 个 endpoint 删除真冗余(单复数 / 重复 recents 这类),并不是热路径全部失控。
"start_url":"./?pwa=true&isApp=true" 的 isApp=true 参数暗示同一份 SPA 可能也被原生 App 的 WebView 引用过,但不能据此推断"团队战略"。可观察事实:manifest 里 9 个 icon size 全部指向同一个 /512x512.png 让浏览器自己缩——是产物打磨不足的明确证据(专业 PWA 实施会做完整 sizes 矩阵 + maskable 适配)。结论收敛为:PWA 投入深度待进一步验证。
/assets/*.js 加载失败。但同样 hash + timestamp 命名规则下,CSS chunk / 图片 / 字体 / lazy worker 文件 404 不会触发,用户看到的可能是样式错乱或图标缺失。根因是发版时旧 chunk 立刻 404——更系统的做法是 CDN 保留旧版本 24-72 小时 + ServiceWorker stale-while-revalidate 策略,从根本上避免 404,而不是弹窗求用户刷新。
| 类别 | 请求数 | 说明 |
|---|---|---|
同源 tablegame.ph | 4518 | 主站 SPA + lazy chunk + 业务 API + 静态资源 |
| SalesMartly (客服浮窗) | 188 | 客服 SDK 自己的资源 + 心跳 + 日志 |
| Google (GA / GTM) | 61 | analytics 上报 |
| Facebook (Pixel) | 46 | 广告归因 |
| RUM / 错误监控 | 0 | ✗ 完全为空 — 这就是 CRITICAL |
window.* probewindow.Sentry : undefined ✗
window.__SENTRY__ : object (空 carrier, sentryClient: false)
window.DD_RUM : undefined ✗
window.Bugsnag : undefined ✗
window.Rollbar : undefined ✗
window.newrelic : undefined ✗
window.LogRocket : undefined ✗
window.heap : undefined ✗
window.onerror property hook : NOT set ✗
window.onunhandledrejection hook : NOT set ✗
注:站点存在 asset-404 专用 addEventListener('error',...) (stale-asset 弹窗用),
但这只覆盖资源加载失败 → 弹窗刷新, 不上报任何后端。
缺失的是: 通用错误上报 SDK / property hook / reporting pipeline。
→ 没有任何主流前端错误监控 SDK 接入
→ 3 错误注入 + 1 Sentry API 探针后 8s 内 0 个 RUM-pattern outbound 请求
SW statenavigator.serviceWorker.controller : 存在
SW scope: https://www.tablegame.ph/
SW state: activated
SW script: https://www.tablegame.ph/sw.js
IndexedDB databases:
- ss_plugin_cache_pro (v2) ← salesmartly 客服的
- sw-storage (v1) ← Service Worker 缓存存储
离线 reload 测试:
context.set_offline(true) → page.reload()
→ has_app: true ✓
→ title: "Table Game" ✓ (保留)
→ 业务数据 chars: 448 (仅 SPA shell)
localStorage 登录后authStore: "tablegame 业务 auth state" ← plain text, 未加密
salesmartly_p_g1nxbu9_token: "客服自己的 token"
salesmartly_p_g1nxbu9_token_date: "..."
→ 已确认 auth token material 暴露在 plain localStorage
→ 本次会话未观察到 httpOnly auth cookie (不完全排除并行 session 路径)
→ XSS 一旦命中 → 至少能拖走 LS 中的 auth material
11 路由 + 登录后实际访问的 /api/* (热路径)GET /lobby/api/preloadcheck
GET /lobby/api/preload
GET /lobby/api/game/getGameListWithCache
GET /lobby/api/jackpot/games
POST /lobby/api/fb/pixel body={"cid":1}
→ 只有 5 个 endpoint 在常规浏览路径上被实际触发
→ 82 个静态定义是 bundle 内 audit-able 上限, 不是热路径
→ apiHost:"/lobby" 反代路径已验证
| 指标 | tablegame.ph | ArionPlay | BingoPlus |
|---|---|---|---|
| 代表性入口/核心 chunk (不可横比) | main.js 1,076,949 B | vue chunk 96,713 B | webpack split 无单一入口 |
| ⚠ 三种打包策略本质不同 — tablegame Vite single-entry / ArionPlay 多 chunk 拆分 (vue + utils + comp + ...) / BingoPlus webpack vendor split。请勿用这一行做"首屏体积"对比;横比口径请用下面 "总 JS(含 lazy)"。 | |||
| Lazy chunk 数 | 36 | 38 | 多 (未统计) |
| 总 JS(含 lazy) | ~2.28 MB | ~756 KB | 大 (多 vendor split) |
| API 暴露形态 | 静态 82 endpoints / 热路径 5 (runtime) · 全在同源 /api/* | 独立 API 子域 apih5 · 端点数未独立计数 | 4 套前缀混用 (含 C66FM 等) |
| localStorage 操作数 | 50 | 少 | SecureLS 包裹 |
| IndexedDB 操作数 | 18 | 0 | 0 |
| try-catch 块 | 140 | 少 (模板默认) | 未统计 |
| await 表达式 | 117 | 少 | 主要回调风格 |
| console.log (prod) | 0 | 0 | 不可知 |
| 外部 SDK 集成数 | 6 业务 + 1 调试 (eruda) = 7 | 2 (Adjust / CF Turnstile) + 自家 SDK | 15+ (含广告网络多家) |
| PWA manifest | ✓ 存在 (图标矩阵打磨不足) | ✓ 基础 | ✗ |
| ServiceWorker | ✓ | 弱 | ✗ |
| protobuf runtime 引用 | ✓ (用途待验证) | 顶层未观察到 | 顶层未观察到 |
| Vue 版本 | 3.x · Composition | 3.x | 2.x · Options + Vuex |
| 构建工具 | Vite | Vite | Webpack 4 |
| 状态管理 | 未发现 (mangled) | Pinia + SecureLS | Vuex + SecureLS |
tablegame.ph 走自研深度路线——做了 ArionPlay 没做的 PWA primitives(已 runtime 实测可离线)+ 自定义 stale-asset 弹窗 + 显式 protobuf runtime 引入。但代价是 2.28 MB 总 JS(ArionPlay 3 倍)、API 静态 endpoint 定义偏多且存在命名遗留(热路径并未失控,runtime 仅 5 个)、错误监控 = 0 已 runtime 证实(当前最高优先级问题)。
ArionPlay 走克制路线——756 KB 总 JS、仅 2 个外部 SDK(Adjust + CF Turnstile)+ 自家 SDK、子域 + UUID 加固。但代价是建在开源模板上,缺 PWA 投资 / 缺错误恢复 UI / 工程 ownership 评分明显较低。
BingoPlus 工程代差明显——Webpack 4 + Vue 2 已 EOL,15+ SDK 堆叠 + 4 套 URL 前缀(含固定前缀 C66FM,归属未证实)。其商业表现与工程评分属独立维度。
tablegame.ph 急需做的事(已经过运行时验证,按优先级):(1) 立刻接 Sentry / DataDog RUM — 运行时已证实 4813 个 outbound 请求里 0 个错误上报,window.onerror/onunhandledrejection 都未设;(2) token 改为 httpOnly cookie — authStore key 已确认是 plain localStorage,任何 XSS 漏洞拖走 token;(3) main bundle 减重 audit(首屏 1.32 MB);(4) API endpoint 命名清理(单复数并存、3 个 login 端点);(5) eruda 从 prod build 完全剔除。