File size: 7,469 Bytes
50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 50925ca 5019340 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | import uuid
from datetime import datetime, timezone
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, Float, JSON
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import relationship
from app.database import Base
# Timezone-aware UTC timestamp factory — avoids naive/aware comparison TypeError
def utcnow():
return datetime.now(timezone.utc)
class User(Base):
__tablename__ = "users"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
firebase_uid = Column(String, unique=True, index=True, nullable=False)
email = Column(String, unique=True, index=True, nullable=False)
name = Column(String, nullable=True)
avatar_url = Column(String, nullable=True)
plan = Column(String, default="free") # 'free', 'starter', 'pro'
display_mode = Column(String, default="founder") # 'founder', 'engineer'
credits_remaining = Column(Integer, default=2)
credits_reset_at = Column(DateTime(timezone=True), default=utcnow)
stripe_customer_id = Column(String, nullable=True)
github_connected = Column(Boolean, default=False)
total_audits = Column(Integer, default=0)
total_designs = Column(Integer, default=0)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime(timezone=True), default=utcnow)
updated_at = Column(DateTime(timezone=True), default=utcnow, onupdate=utcnow)
projects = relationship("Project", back_populates="user", cascade="all, delete-orphan")
github_connection = relationship("GitHubConnection", back_populates="user", uselist=False, cascade="all, delete-orphan")
class Project(Base):
__tablename__ = "projects"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), index=True, nullable=False)
name = Column(String(100), nullable=False)
type = Column(String, nullable=False) # 'audit', 'system_design'
source = Column(String, nullable=False) # 'upload', 'github'
status = Column(String, index=True, default="queued") # 'queued', 'processing', 'complete', 'failed'
job_id = Column(String, index=True, nullable=True)
error_msg = Column(Text, nullable=True)
github_repo = Column(String, nullable=True)
github_branch = Column(String, nullable=True)
created_at = Column(DateTime(timezone=True), default=utcnow)
updated_at = Column(DateTime(timezone=True), default=utcnow, onupdate=utcnow)
user = relationship("User", back_populates="projects")
audit_report = relationship("AuditReport", back_populates="project", uselist=False, cascade="all, delete-orphan")
system_design = relationship("SystemDesign", back_populates="project", uselist=False, cascade="all, delete-orphan")
class AuditReport(Base):
__tablename__ = "audit_reports"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
project_id = Column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), index=True, unique=True, nullable=False)
overall_score = Column(Integer, nullable=False)
confidence = Column(JSONB, nullable=False) # JSON: level, score, label, based_on, limitations, to_increase_confidence
capacity_estimate = Column(JSONB, nullable=False) # JSON: safe_range, peak_range, description, reasoning, confidence
agents = Column(JSONB, nullable=False) # JSON: SRE, backend, infrastructure, cloud_architect reports
top_critical_issues = Column(JSONB, nullable=False) # Array of issues
quick_wins = Column(JSONB, nullable=False) # Array of quick wins
benchmark_percentile = Column(Float, nullable=True)
score_disclaimer = Column(Text, nullable=False)
files_analyzed = Column(Integer, default=0)
files_skipped = Column(Integer, default=0)
was_truncated = Column(Boolean, default=False)
created_at = Column(DateTime(timezone=True), default=utcnow)
project = relationship("Project", back_populates="audit_report")
class SystemDesign(Base):
__tablename__ = "system_designs"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
project_id = Column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), index=True, unique=True, nullable=False)
idea_prompt = Column(Text, nullable=False)
title = Column(String, nullable=False)
founder_summary = Column(Text, nullable=False)
engineer_summary = Column(Text, nullable=False)
architecture_type = Column(String, nullable=False) # 'Monolith', 'Microservices', 'Hybrid'
reasoning = Column(Text, nullable=False)
stack = Column(JSONB, nullable=False) # JSON: Frontend, Backend, Database, Infrastructure chips with reasons
database_design = Column(JSONB, nullable=False) # JSON: primary_db, cache, key_tables
api_design = Column(JSONB, nullable=False) # JSON: style, auth_strategy, core_endpoints
infrastructure = Column(JSONB, nullable=False) # JSON: cloud_provider, components, scaling_strategy
reliability = Column(JSONB, nullable=False) # JSON: uptime_target, strategies, backup_dr
cost_estimates = Column(JSONB, nullable=False) # JSON: 1k, 100k, 1m tier costs and drivers
diagram = Column(JSONB, nullable=False) # JSON: nodes, edges
created_at = Column(DateTime(timezone=True), default=utcnow)
project = relationship("Project", back_populates="system_design")
shared_link = relationship("SharedLink", back_populates="design", uselist=False, cascade="all, delete-orphan")
class SharedLink(Base):
__tablename__ = "shared_links"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
design_id = Column(UUID(as_uuid=True), ForeignKey("system_designs.id", ondelete="CASCADE"), unique=True, nullable=False)
slug = Column(String, unique=True, index=True, nullable=False)
view_count = Column(Integer, default=0)
created_at = Column(DateTime(timezone=True), default=utcnow)
design = relationship("SystemDesign", back_populates="shared_link")
class GitHubConnection(Base):
__tablename__ = "github_connections"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), unique=True, index=True, nullable=False)
github_username = Column(String, nullable=False)
access_token = Column(String, nullable=False) # Encrypted text
token_expires_at = Column(DateTime(timezone=True), nullable=True)
connected_at = Column(DateTime(timezone=True), default=utcnow)
last_used_at = Column(DateTime(timezone=True), default=utcnow, onupdate=utcnow)
user = relationship("User", back_populates="github_connection")
class BenchmarkData(Base):
__tablename__ = "benchmark_data"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
score_range = Column(String, nullable=False) # e.g., '80-89'
industry_tag = Column(String, nullable=False) # e.g., 'E-Commerce'
arch_type = Column(String, nullable=False) # e.g., 'Serverless'
created_at = Column(DateTime(timezone=True), default=utcnow)
class WebhookEvent(Base):
__tablename__ = "webhook_events"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
event_id = Column(String, unique=True, index=True, nullable=False)
event_type = Column(String, nullable=False)
processed_at = Column(DateTime(timezone=True), default=utcnow)
|