BUG-HUNT: [data-integrity] ProjectRepository.update() uses naive datetime.now() instead of UTC-aware timestamp #7723

Open
opened 2026-04-12 03:21:04 +00:00 by HAL9000 · 3 comments
Owner

Bug Report: Data Integrity — Naive (Timezone-Unaware) Timestamps in Repository Updates

Severity Assessment

  • Impact: Inconsistent timestamp data in the database; updated_at stored as local time in some repositories while others correctly use UTC, causing audit trail corruption across time zones
  • Likelihood: High — triggered on every update operation in affected repositories
  • Priority: Medium

Location

  • File: src/cleveragents/infrastructure/database/repositories.py
  • Function/Class: ProjectRepository.update, PlanRepository.update, ChangeRepository.mark_applied, ActorRepository.upsert, ActorRepository.clear_default, ActorRepository.set_default
  • Lines: ~245, ~341, ~607, ~775, ~823, ~834

Description

Several repository update methods use datetime.now() (naive, local time) for timestamp fields, while the codebase elsewhere consistently uses datetime.now(tz=UTC) or .isoformat() with UTC awareness. This creates a split-brain timestamp problem.

Evidence

# repositories.py line 245 - ProjectRepository.update
db_project.updated_at = datetime.now()  # type: ignore  <-- NAIVE local time

# repositories.py line 341 - PlanRepository.update  
db_plan.updated_at = datetime.now()  # type: ignore   <-- NAIVE local time

# repositories.py line 607 - ChangeRepository.mark_applied
{"applied": True, "applied_at": datetime.now()}       <-- NAIVE local time

# repositories.py line 775 - ActorRepository.upsert
existing.updated_at = datetime.now()                   <-- NAIVE local time

# repositories.py line 823 - ActorRepository.clear_default
{"is_default": False, "updated_at": datetime.now()}   <-- NAIVE local time

# repositories.py line 834 - ActorRepository.set_default
db_actor.updated_at = datetime.now()                   <-- NAIVE local time

Contrast with correct usage elsewhere in the same file:

# repositories.py line 1996 - ResourceTypeRepository.update (CORRECT)
row.updated_at = datetime.now(tz=UTC).isoformat()

# repositories.py line 3107 - NamespacedProjectRepository.update (CORRECT)
row.updated_at = datetime.now(tz=UTC).isoformat()

Expected Behavior

All updated_at / applied_at timestamps should use datetime.now(tz=UTC) for consistency across all repositories, regardless of server time zone.

Actual Behavior

ProjectRepository, PlanRepository, ChangeRepository, and ActorRepository use naive datetime.now() (local time), creating inconsistent timestamps compared to repositories that correctly use UTC.

Suggested Fix

Replace all datetime.now() with datetime.now(tz=UTC) in the affected repository update methods. The import for UTC is already present at the top of the file:

from datetime import UTC, datetime

Category

data-integrity

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD.


Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: bug-hunter

## Bug Report: Data Integrity — Naive (Timezone-Unaware) Timestamps in Repository Updates ### Severity Assessment - **Impact**: Inconsistent timestamp data in the database; `updated_at` stored as local time in some repositories while others correctly use UTC, causing audit trail corruption across time zones - **Likelihood**: High — triggered on every update operation in affected repositories - **Priority**: Medium ### Location - **File**: `src/cleveragents/infrastructure/database/repositories.py` - **Function/Class**: `ProjectRepository.update`, `PlanRepository.update`, `ChangeRepository.mark_applied`, `ActorRepository.upsert`, `ActorRepository.clear_default`, `ActorRepository.set_default` - **Lines**: ~245, ~341, ~607, ~775, ~823, ~834 ### Description Several repository update methods use `datetime.now()` (naive, local time) for timestamp fields, while the codebase elsewhere consistently uses `datetime.now(tz=UTC)` or `.isoformat()` with UTC awareness. This creates a split-brain timestamp problem. ### Evidence ```python # repositories.py line 245 - ProjectRepository.update db_project.updated_at = datetime.now() # type: ignore <-- NAIVE local time # repositories.py line 341 - PlanRepository.update db_plan.updated_at = datetime.now() # type: ignore <-- NAIVE local time # repositories.py line 607 - ChangeRepository.mark_applied {"applied": True, "applied_at": datetime.now()} <-- NAIVE local time # repositories.py line 775 - ActorRepository.upsert existing.updated_at = datetime.now() <-- NAIVE local time # repositories.py line 823 - ActorRepository.clear_default {"is_default": False, "updated_at": datetime.now()} <-- NAIVE local time # repositories.py line 834 - ActorRepository.set_default db_actor.updated_at = datetime.now() <-- NAIVE local time ``` Contrast with correct usage elsewhere in the same file: ```python # repositories.py line 1996 - ResourceTypeRepository.update (CORRECT) row.updated_at = datetime.now(tz=UTC).isoformat() # repositories.py line 3107 - NamespacedProjectRepository.update (CORRECT) row.updated_at = datetime.now(tz=UTC).isoformat() ``` ### Expected Behavior All `updated_at` / `applied_at` timestamps should use `datetime.now(tz=UTC)` for consistency across all repositories, regardless of server time zone. ### Actual Behavior `ProjectRepository`, `PlanRepository`, `ChangeRepository`, and `ActorRepository` use naive `datetime.now()` (local time), creating inconsistent timestamps compared to repositories that correctly use UTC. ### Suggested Fix Replace all `datetime.now()` with `datetime.now(tz=UTC)` in the affected repository update methods. The import for `UTC` is already present at the top of the file: ```python from datetime import UTC, datetime ``` ### Category data-integrity ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: bug-hunter
HAL9000 added this to the v3.2.0 milestone 2026-04-12 03:41:08 +00:00
Author
Owner

Verified — Data integrity bug: ProjectRepository.update() uses naive datetime instead of UTC-aware. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Data integrity bug: ProjectRepository.update() uses naive datetime instead of UTC-aware. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Data integrity bug: ProjectRepository.update() uses naive datetime instead of UTC-aware. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Data integrity bug: ProjectRepository.update() uses naive datetime instead of UTC-aware. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Data integrity bug: ProjectRepository.update() uses naive datetime instead of UTC-aware. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Data integrity bug: ProjectRepository.update() uses naive datetime instead of UTC-aware. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#7723
No description provided.