diff --git a/poweron/appdoc/doc_system.html b/poweron/appdoc/doc_system.html new file mode 100644 index 0000000..fcdb33e --- /dev/null +++ b/poweron/appdoc/doc_system.html @@ -0,0 +1,501 @@ + + + + + + PowerOn System Documentation + + + +
+

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 the automatic conversion system to work correctly. +
+ +

1.6 Automatic Timestamp Conversion

+ +

The system automatically converts timestamp fields using the ModelMixin.to_dict() method:

+ +
+def to_dict(self) -> Dict[str, Any]: + """ + Convert a Pydantic model to a dictionary. + Handles both Pydantic v1 and v2. + Properly serializes datetime fields to ISO format strings. + + 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 + + # Convert datetime fields to ISO format strings + for key, value in data.items(): + if isinstance(value, datetime): + data[key] = value.isoformat() + elif isinstance(value, (int, float)) and self._is_timestamp_field(key): + # Handle timestamp fields based on field metadata + try: + data[key] = datetime.fromtimestamp(value).isoformat() + except (ValueError, TypeError): + # If conversion fails, keep the original value + pass + + return data + +def _is_timestamp_field(self, field_name: str) -> bool: + """ + Check if a field is a timestamp field based on field metadata. + Looks for 'UTC timestamp' in the field description. + """ + try: + # Get field info from Pydantic model + if hasattr(self, 'model_fields'): + # Pydantic v2 + field_info = self.model_fields.get(field_name) + if field_info and field_info.description: + return 'UTC timestamp' in field_info.description + elif hasattr(self, '__fields__'): + # Pydantic v1 + field_info = self.__fields__.get(field_name) + if field_info and field_info.field_info and field_info.field_info.description: + return 'UTC timestamp' in field_info.field_info.description + except Exception: + pass + + # Fallback: return False for safety + return False +
+ +

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

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ComponentStatusDetails
Backend ModelsCOMPLETED11 models, 15 timestamp fields standardized
Backend APIsCOMPLETEDAll endpoints return float timestamps
Frontend ModulesCOMPLETEDAll utilities expect float timestamps
Database MigrationNOT REQUIREDDatabase will be cleaned before testing
Testing & ValidationCOMPLETED24 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.

+
+ + +
+ +