Commit Graph

13 Commits

Author SHA1 Message Date
ogt
b37658f7be fix: 修復 growth_analysis/abc_analysis 全表掃描 hang + elephant_alpha Blueprint stub
Some checks failed
CD Pipeline / deploy (push) Failing after 51s
- growth_analysis: 改用 SQL 月度聚合 (3 個 targeted queries) 取代讀取 748k 行進 pandas
- _get_filtered_sales_data: 冷快取補載時 months=0 改為 months=12,避免全表掃描 hang
- elephant_alpha_routes: 補建 Blueprint stub 解除啟動 import 失敗警告

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:41:06 +08:00
ogt
74de1dc68a fix: add python-pptx to requirements + fix BCG empty name filter
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
- requirements.txt: 加入 python-pptx(ADR-014 PPT 系統必要依賴,前次漏加)
- openclaw_bot_routes.py: BCG SQL 補 brand_name/area_name IS NOT NULL 過濾

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:38:04 +08:00
ogt
48804553cd feat: PPT 簡報系統 V2 — 新增 growth/vendor/bcg 三種報告 + 原生圖表升級
All checks were successful
CD Pipeline / deploy (push) Successful in 1m15s
- ppt_generator.py: 新增 generate_growth_ppt(6頁)、generate_vendor_ppt(5頁)、generate_bcg_ppt(5頁)
- openclaw_bot_routes.py: 新增 query_growth_data()、query_vendor_bcg_data()、_generate_ppt_cmd 三路分支、_submenu_reports 4顆新按鈕、type_labels、await:date_ppt_vendor 流程
- ADR-014: 記錄 V2 完整架構(9種報告類型、圖表技術方案、callback_data 格式)
- CLAUDE.md: 新增 PPT 簡報系統索引表

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:26:47 +08:00
ogt
e0d3b54527 feat: add PPT shortcut buttons after sales & trend query results
Some checks failed
CD Pipeline / deploy (push) Failing after 1m1s
Previously after querying sales or trend data, there were no direct
PPT generation buttons — users had to navigate back to 簡報報表 menu.

Changes:
1. sales_quick_kb(date_str):
   + [📊 產出日報 PPT]  → cmd:ppt:daily <date>
   + [📄 策略簡報]      → cmd:ppt:strategy <date>

2. trend ≤35 days (weekly/monthly view):
   + [📊 產出趨勢簡報] → cmd:ppt:strategy <start_date>
   + [📅 產出日報 PPT] → cmd:ppt:daily <end_date>
   + [← 返回業績查詢]  → menu:sales

3. trend >35 days (quarterly/half-year/yearly view):
   + [📊 產出趨勢簡報] → cmd:ppt:strategy <period>
   + [📅 月報 PPT]     → cmd:ppt:monthly <month>
   + [← 返回業績查詢]  → menu:sales
2026-04-20 06:14:39 +08:00
ogt
043ad3e6d9 fix: /menu@BotName in group chat not parsed correctly
All checks were successful
CD Pipeline / deploy (push) Successful in 1m21s
Root cause: Telegram appends @BotUsername to commands in group chats:
  /menu@OpenClawAwoool_Bot

The parser did:
  q = question.lstrip('/')   → 'menu@OpenClawAwoool_Bot'
  cmd = q.split()[0].lower() → 'menu@openclawawoool_bot'

This did NOT match 'menu' in KNOWN set, so the command fell through
to openclaw_answer() (natural language mode) → no menu appeared.

Fix: cmd = raw_cmd.split('@')[0]
  → strips @mention suffix before KNOWN lookup
  → /menu@OpenClawAwoool_Bot now correctly dispatches to handle_cmd('menu')

Affects all slash commands in group chat mode.
2026-04-20 05:55:00 +08:00
ogt
38586deff1 security: harden alert_routes.py — auth coverage + input validation
All checks were successful
CD Pipeline / deploy (push) Successful in 1m19s
Issues fixed:

1. [CRITICAL] /api/alert/fix unauthenticated (CWE-306)
   POST /api/alert/fix had no @check_alert_auth and was CSRF-exempt.
   Any unauthenticated caller could trigger docker restart or
   docker exec on arbitrary container names (container_name is validated
   by is_valid_container_name but restart of any valid name is still
   a DoS vector). Fix: @check_alert_auth added.

2. [HIGH] Hardcoded ALERT_WEBHOOK_PASSWORD fallback (CWE-798)
   Default 'wooo_alert_2026' exposed in source. Fix: default='',
   startup warning if unset. check_alert_auth now fail-secure:
   returns 503 if password not configured.

3. [MEDIUM] /api/alert/history and /api/alert/analyze unauthenticated
   Both endpoints expose container names, memory usage, CPU stats,
   system recommendations. Fix: @check_alert_auth added to both.

4. [MEDIUM] issue_type unvalidated in manual_fix (CWE-20)
   Any string value could be passed through to auto_fix_container.
   Fix: ALLOWED_ISSUE_TYPES frozenset — only memory/cpu variants allowed.

5. [LOW] limit parameter unbounded in get_alert_history
   Arbitrarily large limit → large list slice → memory pressure.
   Fix: clamped to [1, 200].

NOTE: L177 docker stats command (original report) is SAFE as-is —
list argv, fixed arguments, no user input. nosec B603 correctly placed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:49:04 +08:00
ogt
96e19b6b72 security: harden system_routes.py — auth + input validation
All checks were successful
CD Pipeline / deploy (push) Successful in 1m18s
Issues fixed:

1. [CRITICAL] No authentication on destructive routes (CWE-306)
   POST /api/system/cleanup/docker was unauthenticated (system_bp is
   CSRF-exempt, before_request only refreshes session, no login check).
   Any unauthenticated HTTP client could trigger docker system prune.
   Fix: _require_internal_key() checks X-Internal-Key header against
   INTERNAL_API_KEY env var on all 4 routes; fail-secure if key unset.

2. [MEDIUM] Unvalidated numeric inputs in find commands (CWE-20)
   max_size_mb / older_than_hours came from POST body and were
   interpolated into find -size / -mmin args. Negative/huge values
   could cause unexpected behavior.
   Fix: _validate_int() clamps to [1..10000] / [1..8760] with defaults.

3. [LOW] find -mmin arg missing leading '+' (logic bug)
   '-mmin 168' matches FILES EXACTLY 168 min old, not older-than.
   Fix: '-mmin', f'+{older_than_hours * 60}' (+ = older than)

4. [LOW] subprocess(['date', ...]) in health_check replaced
   with Python datetime.now(UTC).isoformat() — no subprocess needed.

INTERNAL_API_KEY added to .env.example with generation instructions.
Generate with: openssl rand -hex 32

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:47:04 +08:00
ogt
1c03d213ac security: fix shell injection + hardcoded credentials in cicd_routes.py
All checks were successful
CD Pipeline / deploy (push) Successful in 1m22s
CVE-class issues fixed:

1. [HIGH] Shell Injection in gitlab_api_via_ssh (CWE-78)
   endpoint and json_data were interpolated into f-string cmd and passed
   as a single SSH remote command string → shell parses it → injection.
   Fix: build remote_argv as list; each curl argument is a separate item,
   SSH receives them as independent argv (no shell parsing of user data).

2. [HIGH] Hardcoded credentials in source code (CWE-798)
   GITLAB_TOKEN, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID all had live
   secrets as default fallback values. Tokens are now '' (empty) with a
   startup warning if env vars are missing.

3. [MEDIUM] Missing pre-validation allowlist on fix_action (CWE-20)
   ALLOWED_FIX_ACTIONS frozenset added before route handler; any unknown
   action is rejected with 400 before reaching execution logic.

Note: fix_registry/fix_pods/execute_*_rollback use static SSH commands
(no user input in cmd strings) so they are not injection risks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:44:18 +08:00
ogt
ba86f98514 feat: integrate Elephant Alpha ecosystem with full ADR-012/013 compliance
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
- Add ElephantService, AutonomousEngine, Orchestrator, DecisionRouter (EA 4-file stack)
- Fix 10 bugs: URL typo, SQL schema mismatches (price_records JOIN), enum mapping,
  metadata_json, NemoTron PriceThreat dispatch, async/await mismatch, broken imports
- Wire ADR-012 Agent Action Ladder: EventRouter L2 → EA first + AIOrch fallback;
  all decisions dual-write DB + triaged_alert Telegram; momo: callback prefix
- Wire ADR-013 AutoHeal: resource_optimization trigger → AutoHealService
- Add W3 guards: connection cache 300s TTL, $5/hr cost hard limit
- Add W4 persistence: routing decisions + agent performance snapshots → ai_insights
- Add Migration 015: confidence + created_by columns on ai_insights
- Fix run_scheduler.py broken imports (DecisionTracker service didn't exist)
- Fix verify_elephant_integration.py: check_status() → check_connection()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 04:28:26 +08:00
ogt
1fd1622007 feat(telegram): 全面切換 HTML parse_mode + 三層式視覺分隔
All checks were successful
CD Pipeline / deploy (push) Successful in 1m12s
起因:Markdown 舊版 parse_mode 導致 \[Demo] / task\_name 反斜線外漏,
且三層結構(事件資訊 / AI 加工區 / 原始技術細節)分隔線不夠明顯。

切換 HTML parse_mode(只需 escape & < >,不會有反斜線副作用):
- telegram_templates.py 全模板重寫為 HTML
  * <b>粗體</b> / <code>module</code> / <pre>trace</pre>
  * H_DIV (━×20) 節間強分隔 / L_DIV (─×18) 節內弱分隔
  * 新增 triaged_alert() 實作 ADR-012 §④ 三層式結構
    [事件資訊] → ━━━ → [🤖 AI 分析] → ━━━ → [🔍 原始技術細節]

event_router.py:
- _hermes_observe_parsed() 回結構化 dict {summary, cause, actions}
  取代舊的字串版本
- _render_l1/l2_with_fallback 改用 tpl.triaged_alert() 統一格式
- _send() parse_mode 改 HTML

Call sites 同步改 HTML:
- routes/bot_api_routes.py price_decision_notify
- services/openclaw_strategist_service.py 兩個發送處
- services/telegram_bot_service.py 三個 edit_message_text
  (_handle_price_approve / _handle_price_reject / _handle_ops_callback)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:54:44 +08:00
ogt
528a6c0468 feat(telegram): 統一訊息格式模板(六類 + callback prefix)
All checks were successful
CD Pipeline / deploy (push) Successful in 1m12s
新增 services/telegram_templates.py:
- alert() 🚨 告警 / warning() ⚠️ 警告 / info() ℹ️ 資訊
- success()  成功 / report() 📊 報告 / price_decision() 💰 決策
- decision_result() 回執(edit_message 用)
- 全訊息標 [EwoooC] 前綴(跨專案共用 bot 識別來源,見 ADR-011)
- _escape_md() 處理 user input,避免 Markdown 破版
- _tail() 取 trace 末段,避開曠日 stack trace

接入點改用模板(P2/P3):
- routes/bot_api_routes.py price_decision_notify
- services/openclaw_strategist_service.py _send_price_decision_requests
- services/telegram_bot_service.py _handle_price_approve/reject
  callback_data 改用 momo: prefix(舊 pa:/pr: 向下相容)

尚未接入(待下次迭代):
- scheduler.py 各 task 錯誤通知
- _notify_telegram_group() 週報推播

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:28:23 +08:00
ogt
8d0b79cd00 feat(ops): restore Telegram chain + P2/P3 price decisions + ADR-011
All checks were successful
CD Pipeline / deploy (push) Successful in 1m19s
P2 (Inline Keyboard 降價決策):
- routes/bot_api_routes.py: POST /bot/api/price-decision/notify
- services/telegram_bot_service.py: pa:/pr: callback handlers

P3 (OpenClaw 自動觸發):
- services/openclaw_strategist_service.py: Gemini 週報末尾輸出
  PRICE_DECISIONS_JSON,解析後自動推送 inline keyboard 給 admin

Ops 修復(跨專案隔離與容器斷訊根因):
- ADR-011 全面規範多專案共存邊界、禁用 --remove-orphans
- .gitea/workflows/cd.yaml: sync 模式一次重啟三容器
  (原本僅 momo-pro-system,scheduler/telegram-bot 靜默落伍)
- run_telegram_bot.py: 從 scripts/tools/ 複製到根目錄
  (消滅 docker-compose mount 建空目錄的陷阱)
- CLAUDE.md: 補核心容器表、診斷黃金三句、緊急指令

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:25:04 +08:00
ogt
1b4f3a7bbe feat: EwoooC 初始化 — 完整專案推版至 Gitea
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00