--- id: RMGR-ADR-002 type: architecture-decision-record title: "Canonical UTC timestamps; local time only at I/O boundaries" status: accepted decided: "2026-08-21" deciders: ["Bernd Worsch"] related: - RMGR-WP-0008 - RMGR-WP-0005 - docs/observation-command-contracts_v0.1.md --- # ADR-002: Canonical UTC timestamps; local time only at I/O boundaries ## Status **Accepted** (2026-08-21). ## Context Repo Manager emits timestamps into repository records, indexes, mutation meters, events, evidence, and compatibility contracts. Host-local clocks and implicit calendar conversion make identical events serialize differently, create daylight-saving ambiguity, and make deterministic reconciliation harder. Users and external systems still need local calendars, wall-clock times, and locale-specific formatting. Those are presentation and ingestion concerns, not stored identity. ## Decision 1. Every value representing an **instant** is created, stored, compared, and exchanged in UTC. 2. New textual timestamps use RFC 3339/ISO 8601 with the canonical `Z` suffix. Readers may accept legacy explicit offsets and normalize them to UTC before comparison or re-emission. Naive datetimes are rejected at boundaries. 3. Database timestamp columns use timezone-aware types and UTC values. Epoch values, where a foreign contract requires them, denote UTC instants. 4. Conversion to or from a local timezone, locale, calendar, or wall-clock representation occurs only in UI and I/O adapters. The converted value never replaces the canonical instant. 5. Inputs that omit a timezone are invalid unless the specific I/O contract also supplies an explicit timezone. DST gaps and folds must be resolved at that boundary before producing UTC. 6. A genuine **date-only domain value**—for example a contractual due date—is not a timestamp and keeps its declared calendar semantics. A date derived from the current instant for repository metadata uses the UTC calendar date. 7. Tests, fixtures, logs, filenames, events, and idempotency material follow the same rule; test convenience is not an exception. ## Enforcement - Repo Manager timestamp creation goes through `repo_manager.time`. - Ruff `DTZ` and `UP` rules remain explicitly selected so naive datetime use and non-canonical UTC APIs fail lint even if Ruff defaults change. - Contract tests require UTC-aware values and canonical `Z` serialization. ## Consequences Stored and exchanged instants are byte-stable across hosts. Ordering and reconciliation no longer depend on operator locale or daylight-saving rules. Presentation clients must retain the canonical value and treat local rendering as a reversible view. Legacy offset-bearing timestamps remain readable but are normalized when rewritten.