PowerOn System Documentation

1. Timestamp & Datetime Architecture

Status: COMPLETED Last Updated: 2025-01-21 Scope: Entire codebase (Gateway + Frontend Agents)

1.1 Overview

PowerOn implements a unified timestamp architecture that ensures consistency across all modules, APIs, and frontend components. The system uses float UTC timestamps as the single source of truth for all temporal data, eliminating timezone confusion and format inconsistencies.

1.2 Core Design Principles

Single Source of Truth: UTC Timestamps

Consistent Data Flow Architecture

Database ←→ Models ←→ API Endpoints ←→ Frontend ↓ ↓ ↓ ↓ Float Float Float Float UTC UTC UTC UTC

Frontend-Backend Contract

1.3 Technical Implementation Standards

Backend (Python) Standards

# ✅ CORRECT - Use UTC timestamp functions from modules.shared.timezoneUtils import get_utc_timestamp, create_expiration_timestamp # For current time current_time = get_utc_timestamp() # Returns float # For expiration times expires_at = create_expiration_timestamp(3600) # 1 hour from now # For model fields class UserConnection(BaseModel): connectedAt: float = Field(default_factory=get_utc_timestamp) expiresAt: Optional[float] = None

Frontend (JavaScript) Standards

// ✅ CORRECT - Expect float UTC timestamps import { isExpiredUtc, formatUtcForDisplay } from '../shared/timezoneUtils.js'; // Check expiration (expects float) if (isExpiredUtc(connection.expiresAt)) { // Handle expired token } // Display in local timezone (expects float) const localTime = formatUtcForDisplay(connection.connectedAt);

API Response Standards

// ✅ CORRECT - All timestamp fields as float { "id": "conn_123", "connectedAt": 1705852800.0, "expiresAt": 1705856400.0, "lastChecked": 1705852800.0 } // ❌ WRONG - Mixed types or ISO strings { "id": "conn_123", "connectedAt": "2024-01-21T12:00:00Z", // ISO string "expiresAt": 1705856400.0, // Float "lastChecked": "2024-01-21T12:00:00Z" // ISO string }

1.4 Database Schema Standards

Timestamp Field Types

-- ✅ CORRECT - All timestamp fields as FLOAT/DOUBLE CREATE TABLE connections ( id VARCHAR(255) PRIMARY KEY, connectedAt DOUBLE NOT NULL, -- UTC timestamp in seconds expiresAt DOUBLE, -- UTC timestamp in seconds lastChecked DOUBLE NOT NULL -- UTC timestamp in seconds ); -- ❌ WRONG - Mixed types CREATE TABLE connections ( id VARCHAR(255) PRIMARY KEY, connectedAt DATETIME, -- Datetime type expiresAt DOUBLE, -- Float type lastChecked VARCHAR(255) -- String type );

System Fields (Keep as-is)

-- ✅ CORRECT - System fields remain as strings CREATE TABLE connections ( id VARCHAR(255) PRIMARY KEY, connectedAt DOUBLE NOT NULL, -- User data: float UTC _createdAt VARCHAR(255), -- System data: ISO string _modifiedAt VARCHAR(255) -- System data: ISO string );

1.5 Model Field Standards

All timestamp fields in Pydantic models must follow these standards:

class UserConnection(BaseModel, ModelMixin): """Data model for a user's connection to an external service""" id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the connection") userId: str = Field(description="ID of the user this connection belongs to") authority: AuthAuthority = Field(description="Authentication authority") externalId: str = Field(description="User ID in the external system") externalUsername: str = Field(description="Username in the external system") externalEmail: Optional[EmailStr] = Field(None, description="Email in the external system") status: ConnectionStatus = Field(default=ConnectionStatus.ACTIVE, description="Connection status") connectedAt: float = Field(default_factory=get_utc_timestamp, description="When the connection was established (UTC timestamp in seconds)") lastChecked: float = Field(default_factory=get_utc_timestamp, description="When the connection was last verified (UTC timestamp in seconds)") expiresAt: Optional[float] = Field(None, description="When the connection expires (UTC timestamp in seconds)")
⚠️ Critical Rule: All timestamp fields MUST include "UTC timestamp in seconds" in their description for consistency and documentation purposes.

1.6 Direct Float Storage

The system now stores all timestamp fields directly as float values in the database:

def to_dict(self) -> Dict[str, Any]: """ Convert a Pydantic model to a dictionary. Handles both Pydantic v1 and v2. All timestamp fields remain as float values. Returns: Dict[str, Any]: Dictionary representation of the model """ # Get the raw dictionary if hasattr(self, 'model_dump'): data: Dict[str, Any] = self.model_dump() # Pydantic v2 else: data: Dict[str, Any] = self.dict() # Pydantic v1 # All fields (including timestamps) remain in their original format # No conversions needed - timestamps are already float return data

Key Benefits:

1.7 Utility Functions

Backend Utilities (Python)

from modules.shared.timezoneUtils import get_utc_timestamp, create_expiration_timestamp # Get current UTC timestamp current_time = get_utc_timestamp() # Returns float # Create expiration timestamp (seconds from now) expires_in_1_hour = create_expiration_timestamp(3600) expires_in_1_day = create_expiration_timestamp(86400) # Get UTC datetime object utc_now = get_utc_now() # Returns datetime object in UTC

Frontend Utilities (JavaScript)

import { isExpiredUtc, formatUtcForDisplay, getExpiresInSeconds, normalizeTimestamp } from '../shared/timezoneUtils.js'; // Check if timestamp is expired if (isExpiredUtc(connection.expiresAt)) { console.log('Connection expired'); } // Format for display (converts to local timezone) const displayTime = formatUtcForDisplay(connection.connectedAt); // Get seconds until expiration const secondsLeft = getExpiresInSeconds(connection.expiresAt); // Normalize any timestamp format to float (backward compatibility) const normalized = normalizeTimestamp(connection.lastChecked);

1.8 Migration Rules

When converting existing timestamp data to the new format:

def migrate_timestamp_field(value): """Migrate any timestamp format to float UTC timestamp""" if isinstance(value, float): return value # Already float, assume UTC elif isinstance(value, str): if value.endswith('Z') or 'T' in value: # ISO string format dt = datetime.fromisoformat(value.replace('Z', '+00:00')) return dt.timestamp() else: # Try parsing as float return float(value) elif isinstance(value, datetime): # Convert to UTC timestamp return value.timestamp() else: raise ValueError(f"Cannot migrate timestamp: {value}")

1.9 Implementation Status

Component Status Details
Backend Models COMPLETED 11 models, 15 timestamp fields standardized as float
Backend APIs COMPLETED All endpoints return float timestamps
Frontend Modules COMPLETED All utilities expect float timestamps
Database Storage COMPLETED All timestamps stored as float (no string conversion)
Testing & Validation COMPLETED 24 tests passing, all functionality verified

2. System Overview

This section will contain the overall system architecture documentation.

3. Development Guidelines

This section will contain coding standards and best practices.

4. API Standards

This section will contain API design and response format standards.

5. Testing Standards

This section will contain testing methodologies and standards.