diff --git a/.env.example b/.env.example index d1b6796..f9ee77a 100644 --- a/.env.example +++ b/.env.example @@ -510,8 +510,9 @@ ELEPHANT_ALPHA_HERMES_LLM_PREFETCH_ENABLED=false # [選填] 外部 BI 連結(模板全域變數) METABASE_URL=https://mo.wooo.work/metabase -GRIST_URL=https://grist.wooo.work +GRIST_URL=https://mo.wooo.work/grist MB_SITE_URL=https://mo.wooo.work/metabase +GRIST_APP_HOME_URL=https://mo.wooo.work/grist GRIST_ADMIN_EMAIL=admin@wooo.work GRAFANA_PASSWORD=change-me PGADMIN_EMAIL=admin@wooo.work diff --git a/TODO_NEXT_STEPS.txt b/TODO_NEXT_STEPS.txt index 36d9ccf..17f5811 100644 --- a/TODO_NEXT_STEPS.txt +++ b/TODO_NEXT_STEPS.txt @@ -4,6 +4,7 @@ ================================================================================ 【已完成】 + - V10.439 收斂外部 BI / 資料協作入口:`/metabase`、`/grist` 正式頁維持 momo-pro 內部診斷 bridge,`.env.example` 與 bi profile Grist 預設改回 `https://mo.wooo.work/grist` / `GRIST_APP_HOME_URL`,並補測試禁止 `grist.wooo.work` / `awoooi` 回流到導覽設定;外部工具頁標題字級改用新版 token 與手機 media query。 - V10.414 補市場情報 MCP fetch run readiness gate:新增 `mcp_fetch_run_readiness` read-only builder、GET/POST endpoint、UI run readiness 審核面板與 deployment readiness smoke target,在 run package 後檢查 command preview、receipt path、artifact path、節流/timeout/dry-run-first 與操作員 shell-only 邊界;API/UI 不執行 CLI、不抓外站、不寫檔、不開 DB、不掛 scheduler,只放行到人工 shell dry-run 與後續 receipt gate。 - V10.412 補市場情報 MCP fetch run package gate:新增 `mcp_fetch_run_package` read-only builder、route extension、GET/POST endpoint、UI run package 審核面板與 deployment readiness smoke target,將已通過的 target review 轉成操作員可覆核的 command argv preview 與 receipt path 契約;API/UI 不執行 CLI、不抓外站、不寫檔、不開 DB、不掛 scheduler,只放行到後續 run readiness review。 - V10.409 補市場情報 MCP fetch target review gate:新增 `mcp_fetch_target_review` read-only builder、GET/POST endpoint、UI target review 審核面板與 deployment readiness smoke target,讓 manual fetch handoff 通過後,先人工審核 adapter registry 公開入口、每平台節流、樣本數、timeout 與 rollback plan;API/UI 不保存 payload、不發外部 request、不開 DB、不寫入、不掛 scheduler,也不會自動打開 manual fetch。 diff --git a/config.py b/config.py index 3d9b513..d0c1041 100644 --- a/config.py +++ b/config.py @@ -325,7 +325,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.438" +SYSTEM_VERSION = "V10.439" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docker-compose.yml b/docker-compose.yml index 4b14e68..45ecf15 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -780,7 +780,7 @@ services: - GRIST_SUPPORT_ANON=true - GRIST_FORCE_LOGIN=false - GRIST_HIDE_UI_ELEMENTS=helpCenter,billing,templates,multiSite,multiAccounts - - APP_HOME_URL=https://grist.wooo.work + - APP_HOME_URL=${GRIST_APP_HOME_URL:-https://mo.wooo.work/grist} - TZ=Asia/Taipei networks: - momo-network diff --git a/docs/AI_INTELLIGENCE_MODULE_SOT.md b/docs/AI_INTELLIGENCE_MODULE_SOT.md index 173c0ad..27a8d9c 100644 --- a/docs/AI_INTELLIGENCE_MODULE_SOT.md +++ b/docs/AI_INTELLIGENCE_MODULE_SOT.md @@ -2,7 +2,7 @@ > **最後更新**: 2026-05-24 (台北時間) > **狀態**: 🟢 四 AI Agent 自動化閉環已落地;LLM 路由紅線升級為 Ollama-first 三主機級聯,Gemini 備援預設關閉 -> **適用版本**: V10.438 +> **適用版本**: V10.439 --- diff --git a/docs/memory/history_logs.md b/docs/memory/history_logs.md index 9fa60fb..6b3e560 100644 --- a/docs/memory/history_logs.md +++ b/docs/memory/history_logs.md @@ -13,6 +13,7 @@ ## 📅 詳細更新日誌 (考古存檔) ### 2026-05-24:PChome 近門檻身份回收第二輪 +- **V10.439 外部 BI / 資料協作入口收斂**: `/metabase`、`/grist` 保持在 momo-pro 內部診斷 bridge,不再出現空白頁或錯連其他專案;`.env.example` 與 bi profile 的 Grist 預設 URL 改為 `https://mo.wooo.work/grist` / `GRIST_APP_HOME_URL`,測試同步守住 `grist.wooo.work` 與 `awoooi` 不再回到 app/template/env/compose 導覽設定。外部工具頁 H1 移除 viewport font scaling,改用新版 token 與手機 media query。 - **V10.438 PPT QA 失敗重跑精準化**: `/observability/ppt_audit_history` 的 QA 失敗與 issue triage 卡片會從 PPT 檔名前綴推回原始 `report_type`,不再把所有視覺 QA 失敗硬編成 daily 重跑;單筆「重跑」會以 `force=true` 呼叫補齊 API,並在產生前只失效同一 `report_type + parameters` 的 active `ppt_reports` cache,避免重新產出仍命中舊簡報。頁面也把 audit lane 的預覽按鈕補上,讓失敗檔案可直接站內回放 PDF/PPTX 預覽。 - **V10.437 業績圖表載入韌性與 QA 升級**: `analysis-chart-theme.js` 的 Chart.js loader 加入 4.5 秒 timeout 與 jsDelivr → unpkg → cdnjs 三來源 fallback;若外部 CDN 卡住或失敗,`/daily_sales`、`/growth_analysis` 會切到既有 HTML snapshot / fallback 圖表,不再留下空白圖表框。`check_sales_charts_runtime.js` 也從「canvas 有墨點」升級為檢查非零 dataset、可見元素、彩色資料筆跡與 canvas ink,避免只有座標軸的假通過。 - **V10.436 daily_sales snapshot_date 型別修復**: `/daily_sales` 日期窗口查詢改為依 DB dialect 明確 cast:PostgreSQL 使用 `"snapshot_date"::date` 並把參數 `CAST(:start_date AS date)` / `CAST(:end_date AS date)`,SQLite 使用 `date("snapshot_date")`;metadata / fingerprint 查詢同步引用 cast 後日期,避免正式庫 `snapshot_date` 為 text 時出現 `text = date` / `text >= date` 類型錯誤。後台 `chart_generator_service.monthly_overview_chart()` 的月業績 SQL 也改為 `snapshot_date::date`,防止報表圖表因 text 欄位而空白。 diff --git a/routes/system_public_routes.py b/routes/system_public_routes.py index 409d429..763c012 100644 --- a/routes/system_public_routes.py +++ b/routes/system_public_routes.py @@ -57,6 +57,14 @@ def _configured_url_label(configured_url): return candidate +def _is_blocked_external_url(configured_url): + candidate = (configured_url or '').strip() + if not candidate or candidate.startswith('/') and not candidate.startswith('//'): + return False + parsed = urlparse(candidate) + return parsed.scheme in {'http', 'https'} and parsed.hostname != 'mo.wooo.work' + + def _external_tool_payload(kind): if kind == 'metabase': launch_url = _safe_launch_url(METABASE_URL, '/metabase') @@ -83,11 +91,12 @@ def _external_tool_payload(kind): } launch_url = _safe_launch_url(GRIST_URL, '/grist') + blocked_external = _is_blocked_external_url(GRIST_URL) return { 'key': 'grist', 'eyebrow': 'Data Collaboration', 'title': '資料協作入口', - 'status_label': '錯鏈已攔截' if not launch_url else '可開啟', + 'status_label': '錯鏈已攔截' if blocked_external else ('可開啟' if launch_url else '待接上協作服務'), 'summary': '資料協作入口已回到 momo-pro 內部,不會再連到其他專案站台。', 'detail': 'Grist 的正式 momo-pro 專案隔離尚未接上 Gateway;在完成專屬服務前,本頁會提供資料作業入口與目前設定狀態。', 'launch_href': launch_url, @@ -95,7 +104,7 @@ def _external_tool_payload(kind): 'configured_label': _configured_url_label(GRIST_URL), 'checks': [ {'label': '導覽路由', 'value': '/grist', 'state': 'ok'}, - {'label': '錯站攔截', 'value': '已啟用', 'state': 'ok'}, + {'label': '錯站攔截', 'value': '已攔截外部錯鏈' if blocked_external else '未偵測錯鏈', 'state': 'ok'}, {'label': '協作服務', 'value': '尚未接入 proxy', 'state': 'warn'}, ], 'actions': [ diff --git a/tests/test_external_tool_entrypoints.py b/tests/test_external_tool_entrypoints.py index 1006f32..1c09d6a 100644 --- a/tests/test_external_tool_entrypoints.py +++ b/tests/test_external_tool_entrypoints.py @@ -9,14 +9,19 @@ def test_metabase_and_grist_navigation_stays_inside_momo_pro(): shell = (ROOT / "templates/components/_ewoooc_shell.html").read_text(encoding="utf-8") tabs = (ROOT / "templates/components/_analysis_report_tabs.html").read_text(encoding="utf-8") legacy_nav = (ROOT / "templates/components/_navbar.html").read_text(encoding="utf-8") + env_example = (ROOT / ".env.example").read_text(encoding="utf-8") + compose = (ROOT / "docker-compose.yml").read_text(encoding="utf-8") assert "'metabase_url': '/metabase'" in app_source assert "'grist_url': '/grist'" in app_source assert "['sales', 'daily_sales', 'monthly', 'growth', 'metabase', 'grist']" in shell + assert "GRIST_URL=https://mo.wooo.work/grist" in env_example + assert "APP_HOME_URL=${GRIST_APP_HOME_URL:-https://mo.wooo.work/grist}" in compose - combined = "\n".join([app_source, shell, tabs, legacy_nav]) + navigation_sources = "\n".join([app_source, shell, tabs, legacy_nav]) + combined = "\n".join([navigation_sources, env_example, compose]) assert "grist.wooo.work" not in combined - assert "awoooi" not in combined.lower() + assert "awoooi" not in navigation_sources.lower() def test_external_tool_bridge_pages_are_diagnostic_not_blank(): @@ -26,6 +31,7 @@ def test_external_tool_bridge_pages_are_diagnostic_not_blank(): assert "def _external_tool_payload(kind)" in route_source assert "parsed.path.rstrip('/') == bridge_path.rstrip('/')" in route_source + assert "def _is_blocked_external_url(configured_url)" in route_source assert "external-tool-checks" in template assert "external-tool-diagnostics" in template assert "external-tool-action-grid" in template diff --git a/web/static/css/page-external-tools.css b/web/static/css/page-external-tools.css index 6e8bb28..b80416f 100644 --- a/web/static/css/page-external-tools.css +++ b/web/static/css/page-external-tools.css @@ -45,7 +45,7 @@ } .external-tool-hero h1 { - font-size: clamp(32px, 4vw, 48px); + font-size: var(--momo-text-display, 40px); line-height: 1.08; } @@ -203,6 +203,11 @@ align-self: flex-start; } + .external-tool-hero h1 { + font-size: var(--momo-text-headline, 24px); + line-height: 1.18; + } + .external-tool-checks, .external-tool-diagnostics, .external-tool-action-grid {