Skip to content

fix(audit): resolve 8-hour timezone offset in audit log timestamps#472

Open
dongmucat wants to merge 1 commit into
mainfrom
fix/audit-log-timestamp-utc
Open

fix(audit): resolve 8-hour timezone offset in audit log timestamps#472
dongmucat wants to merge 1 commit into
mainfrom
fix/audit-log-timestamp-utc

Conversation

@dongmucat
Copy link
Copy Markdown
Collaborator

概述

修复管理员"系统操作记录"页面时间列显示比实际时间晚 8 小时的 bug。根因是 audit_log.created_atTIMESTAMP(无时区),读出路径 rs.getTimestamp() 使用 JVM 默认时区解释裸值,当 JVM TZ != UTC 时产生偏移。

变更内容

后端实现

  • V42 migrationaudit_log.created_atTIMESTAMP 升级为 TIMESTAMPTZ,历史数据通过 USING created_at AT TIME ZONE 'UTC' 锚定为 UTC(与 V18/V19/V23/V25 同模式)
  • 读路径补丁AdminAuditLogAppService.javars.getTimestamp("created_at") 替换为 rs.getObject(col, OffsetDateTime.class).toInstant(),对 TIMESTAMP 和 TIMESTAMPTZ 列均正确,不依赖 JVM 时区

前端实现

  • 无前端变更(前端 parseServerDateTime 对带 Z 的字符串处理已正确)

测试覆盖

  • 后端单测:AdminAuditLogAppServiceTest.rowMapper_readsCreatedAtAsUtcInstant — 通过 ArgumentCaptor 抓取 RowMapper,mock ResultSet 验证 OffsetDateTime 读取路径,并断言不再调用 getTimestamp()

质量门禁

  • make test-backend-app 通过(471 tests, 0 failures)
  • 无 Controller 变更,make generate-api 不需要
  • 无前端变更,typecheck/lint/e2e 不需要

安全考虑

本次变更不涉及安全敏感内容。仅修复时间展示精度问题。

相关文档

  • docs/15-backend-time-governance-plan.md 3.1 节:系统事件时间统一为 TIMESTAMPTZ
  • 同模式先例:V18/V19/V23/V25/V36

测试说明

本地验证步骤

  1. make dev-all 启动本地环境(Flyway 自动执行 V42)
  2. 触发一条审计操作(如管理员审批/拒绝 promotion)
  3. 访问 admin/audit-log 页面,确认时间列与本地墙钟一致(不再差 8 小时)
  4. 可选:docker exec <postgres> psql -U skillhub -c "SELECT pg_typeof(created_at) FROM audit_log LIMIT 1;" 确认列类型为 timestamp with time zone

回归测试范围

  • 管理员审计日志页面时间显示
  • 审计日志时间范围筛选功能

部署注意

  • V42 migration 执行 ALTER COLUMN ... TYPE TIMESTAMPTZ 会取 ACCESS EXCLUSIVE 锁并重写整表,建议在低峰期执行

audit_log.created_at was TIMESTAMP (without timezone). The JDBC read path
used rs.getTimestamp() which interprets values using the JVM default
timezone, causing an 8-hour offset when JVM TZ != UTC.

Fix: upgrade column to TIMESTAMPTZ (V42 migration) and switch the read
path to OffsetDateTime which is timezone-independent for both column types.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant