joseph njoroge kariuki
Deploy Senti AI to Hugging Face Spaces
021e065
Raw
History Blame Contribute Delete
3.17 kB
from sqlalchemy import (
Column, String, Boolean, DateTime, Integer,
Text, Index, TypeDecorator
)
from sqlalchemy.sql import func
from .base import Base
import uuid
import sys
import os
# Ensure core is in path for encryption
sys.path.append(os.path.join(os.path.dirname(__file__), "../../../.."))
from core.security.encryption import encryptor
class EncryptedString(TypeDecorator):
impl = String
cache_ok = True
def process_bind_param(self, value, dialect):
if value is None: return None
return encryptor.encrypt(str(value))
def process_result_value(self, value, dialect):
if value is None: return None
return encryptor.decrypt(value)
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
user_hash = Column(String(64), unique=True, nullable=False, index=True)
# PII (Encrypted)
phone_number = Column(EncryptedString(500), nullable=True, index=True)
kra_pin = Column(EncryptedString(500), nullable=True)
national_id = Column(EncryptedString(500), nullable=True)
tenant_id = Column(String(64), nullable=True, index=True)
# Profile
display_name = Column(String(100))
user_type = Column(String(20), default="personal")
# personal | business | institutional
language_preference = Column(String(10), default="en")
# en | sw | mixed
country_code = Column(String(5), default="KE")
currency = Column(String(5), default="KES")
# Subscription
tier = Column(String(20), default="free")
# free | personal_pro | business | institutional
tier_expires_at = Column(DateTime, nullable=True)
# Auth
pin_hash = Column(String(128), nullable=False)
is_active = Column(Boolean, default=True)
# Consent (ODPC compliance)
consent_data_storage = Column(Boolean, default=False)
consent_training_data = Column(Boolean, default=False)
consent_marketing = Column(Boolean, default=False)
consent_given_at = Column(DateTime, nullable=True)
# Timestamps
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, onupdate=func.now())
last_active_at = Column(DateTime, server_default=func.now())
__table_args__ = (
Index("ix_users_hash", "user_hash"),
Index("ix_users_tier", "tier"),
Index("ix_users_created", "created_at"),
)
class ApiKey(Base):
__tablename__ = "api_keys"
id = Column(Integer, primary_key=True)
key_hash = Column(String(128), unique=True, nullable=False, index=True)
user_hash = Column(String(64), nullable=False, index=True)
name = Column(String(100))
# e.g. "Hermes Production", "My App"
scopes = Column(Text, default="[]")
# JSON: ["process", "files", "hermes"]
tenant_id = Column(String(64), nullable=True, index=True)
# For institutional: links key to tenant
is_active = Column(Boolean, default=True)
last_used_at = Column(DateTime, nullable=True)
expires_at = Column(DateTime, nullable=True)
requests_today = Column(Integer, default=0)
created_at = Column(DateTime, server_default=func.now())
__table_args__ = (
Index("ix_apikeys_user", "user_hash"),
Index("ix_apikeys_tenant", "tenant_id"),
)