fix: BUG-009/010/011 — DataMasking, cancel button, SQL casts
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

BUG-009 (P1): Add frontend DataMasking in saas-relay-client.ts
- Masks ID cards, phones, emails, money, company names before relay
- Unmasks tokens in AI response so user sees original data
- Mirrors Rust DataMasking middleware patterns

BUG-010 (P3): Send button transforms to Stop during streaming
- Shows square icon when isStreaming, calls cancelStream()
- Normal arrow icon when idle, calls handleSend()

BUG-011 (P2): Add ::timestamptz casts for old TEXT timestamp columns
- account/handlers.rs: dashboard stats query
- telemetry/service.rs: reported_at comparisons
- workers/aggregate_usage.rs: usage aggregation query
This commit is contained in:
iven
2026-04-09 23:45:19 +08:00
parent a304544233
commit ba586e5aa7
5 changed files with 88 additions and 22 deletions

View File

@@ -193,9 +193,9 @@ pub async fn dashboard_stats(
.and_utc();
let today_row: DashboardTodayRow = sqlx::query_as(
"SELECT
(SELECT COUNT(*) FROM relay_tasks WHERE created_at >= $1 AND created_at < $2) as tasks_today,
COALESCE((SELECT SUM(input_tokens) FROM usage_records WHERE created_at >= $1 AND created_at < $2), 0)::bigint as tokens_input,
COALESCE((SELECT SUM(output_tokens) FROM usage_records WHERE created_at >= $1 AND created_at < $2), 0)::bigint as tokens_output"
(SELECT COUNT(*) FROM relay_tasks WHERE created_at::timestamptz >= $1 AND created_at::timestamptz < $2) as tasks_today,
COALESCE((SELECT SUM(input_tokens) FROM usage_records WHERE created_at::timestamptz >= $1 AND created_at::timestamptz < $2), 0)::bigint as tokens_input,
COALESCE((SELECT SUM(output_tokens) FROM usage_records WHERE created_at::timestamptz >= $1 AND created_at::timestamptz < $2), 0)::bigint as tokens_output"
).bind(&today_start).bind(&tomorrow_start).fetch_one(&state.db).await?;
Ok(Json(serde_json::json!({