mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-27 11:14:59 +00:00
## Problem Audit log timestamps displayed 8 hours later than actual time when JVM default timezone != UTC. Root cause: `audit_log.created_at` was `TIMESTAMP without time zone`, and `rs.getTimestamp()` interprets bare values using JVM timezone. ## Solution ### Backend - **V42 migration**: Upgrade `audit_log.created_at` from `TIMESTAMP` to `TIMESTAMPTZ`, anchor historical data as UTC via `USING created_at AT TIME ZONE 'UTC'` (same pattern as V18/V19/V23/V25/V36) - **Read path**: `AdminAuditLogAppService.readInstant()` uses `rs.getObject(col, OffsetDateTime.class).toInstant()`, result independent of JVM timezone - **Write path (filter params)**: `startTime`/`endTime` binding changed from `Timestamp.from()` to `OffsetDateTime.ofInstant(instant, ZoneOffset.UTC)` via `toUtcOffsetDateTime()` helper, symmetric with read path ### Migration Safety - `SET LOCAL lock_timeout = '30s'` (transaction-scoped, won't leak to pool) - `DO $$ ... IF data_type = 'timestamp without time zone' THEN ... ELSE ... END $$` idempotent guard with dual-branch `RAISE NOTICE` - Safe retry: re-running won't double-apply `AT TIME ZONE 'UTC'` ### Test Coverage (10 tests, 477 total suite) - `rowMapper_readsCreatedAtAsInstant` — UTC offset regression - `rowMapper_normalisesNonUtcOffsetToInstant` — Non-UTC offset (+08:00) - `rowMapper_returnsNullTimestampWhenColumnIsNull` — Null path - `rowMapper_isIndependentOfJvmDefaultTimezone` — JVM TZ=Asia/Shanghai drift prevention with `verify(rs, never()).getTimestamp()` - `@ParameterizedTest buildWhereClause_bindsTimeRangeAsOffsetDateTime` — 3 cases (both/startOnly/endOnly) for filter param binding - `@BeforeEach setUp()` — Mock isolation to prevent cross-test stub accumulation ## Quality Gates - [x] `make test-backend-app` passes (477 tests, 0 failures) - [x] No Controller changes, `make generate-api` not needed - [x] No frontend changes, typecheck/lint/e2e not needed ## Deployment V42 must run before new code (guaranteed by Spring Boot startup sequence → Flyway executes before app accepts traffic). Rolling deployment: - New pod + migrated column: correct - Old pod + migrated column: old code reads TIMESTAMPTZ correctly (pgjdbc returns absolute instant) ## Related Docs - `docs/15-backend-time-governance-plan.md` §3.1: V42 progress registered - `docs/16-backend-time-inventory.md` §3.1: V42 listed - Same migration pattern: V18/V19/V23/V25/V36 |
||
|---|---|---|
| .. | ||
| prds | ||
| skillhub | ||
| superpowers | ||
| 00-product-direction.md | ||
| 01-system-architecture.md | ||
| 02-domain-model.md | ||
| 03-authentication-design.md | ||
| 04-search-architecture.md | ||
| 05-business-flows.md | ||
| 06-api-design.md | ||
| 07-skill-protocol.md | ||
| 08-frontend-architecture.md | ||
| 09-deployment.md | ||
| 10-delivery-roadmap.md | ||
| 11-auth-extensibility-and-private-sso.md | ||
| 12-private-sso-integration-playbook.md | ||
| 13-parallel-workflow.md | ||
| 14-skill-lifecycle.md | ||
| 15-backend-time-governance-plan.md | ||
| 16-backend-time-inventory.md | ||
| 17-backend-annotation-findings.md | ||
| 18-frontend-annotation-findings.md | ||
| 19-smtp-password-reset-email-setup.md | ||
| 2026-03-20-skill-label-system-design.md | ||
| 2026-04-08-issue-automation-design.md | ||
| dev-workflow.md | ||
| e2e.md | ||
| openclaw-integration-en.md | ||
| openclaw-integration.md | ||
| oss-01-core-contract-freeze.md | ||
| oss-02-core-semantic-rules.md | ||
| pr-batch-test-runtime.md | ||
| security-scanning.md | ||