botserver/src/core/shared/models/core.rs.head
Rodrigo Rodriguez e143968179 feat: Add JWT secret rotation and health verification
SEC-02: Implement credential rotation security improvements

- Add JWT secret rotation to rotate-secret command
- Generate 64-character HS512-compatible secrets
- Automatic .env backup with timestamp
- Atomic file updates via temp+rename pattern
- Add health verification for rotated credentials
- Route rotate-secret, rotate-secrets, vault commands in CLI
- Add verification attempts for database and JWT endpoints

Security improvements:
- JWT_SECRET now rotatable (previously impossible)
- Automatic rollback via backup files
- Health checks catch configuration errors
- Clear warnings about token invalidation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 19:42:41 +00:00

161 lines
4.5 KiB
Text

use chrono::{DateTime, Utc};
use diesel::prelude::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::core::shared::models::schema::{
bot_configuration, bot_memories, bots, clicks, message_history, organizations,
system_automations, user_login_tokens, user_preferences, user_sessions, users,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TriggerKind {
Scheduled = 0,
TableUpdate = 1,
TableInsert = 2,
TableDelete = 3,
Webhook = 4,
EmailReceived = 5,
FolderChange = 6,
}
impl TriggerKind {
pub fn from_i32(value: i32) -> Option<Self> {
match value {
0 => Some(Self::Scheduled),
1 => Some(Self::TableUpdate),
2 => Some(Self::TableInsert),
3 => Some(Self::TableDelete),
4 => Some(Self::Webhook),
5 => Some(Self::EmailReceived),
6 => Some(Self::FolderChange),
_ => None,
}
}
}
#[derive(Debug, Queryable, Serialize, Deserialize, Identifiable)]
#[diesel(table_name = system_automations)]
pub struct Automation {
pub id: Uuid,
pub bot_id: Uuid,
pub kind: i32,
pub target: Option<String>,
pub schedule: Option<String>,
pub param: String,
pub is_active: bool,
pub last_triggered: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Selectable)]
#[diesel(table_name = user_sessions)]
pub struct UserSession {
pub id: Uuid,
pub user_id: Uuid,
pub bot_id: Uuid,
pub title: String,
pub context_data: serde_json::Value,
pub current_tool: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)]
#[diesel(table_name = bot_memories)]
pub struct BotMemory {
pub id: Uuid,
pub bot_id: Uuid,
pub key: String,
pub value: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = users)]
pub struct User {
pub id: Uuid,
pub username: String,
pub email: String,
pub password_hash: String,
pub is_active: bool,
pub is_admin: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = bots)]
pub struct Bot {
pub id: Uuid,
pub name: String,
pub description: Option<String>,
pub llm_provider: String,
pub llm_config: serde_json::Value,
pub context_provider: String,
pub context_config: serde_json::Value,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub is_active: Option<bool>,
pub tenant_id: Option<Uuid>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = organizations)]
#[diesel(primary_key(org_id))]
pub struct Organization {
pub org_id: Uuid,
pub name: String,
pub slug: String,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = message_history)]
pub struct MessageHistory {
pub id: Uuid,
pub session_id: Uuid,
pub user_id: Uuid,
pub role: i32,
pub content_encrypted: String,
pub message_type: i32,
pub message_index: i64,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = bot_configuration)]
pub struct BotConfiguration {
pub id: Uuid,
pub bot_id: Uuid,
pub config_key: String,
pub config_value: String,
pub is_encrypted: bool,
pub config_type: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = user_login_tokens)]
pub struct UserLoginToken {
pub id: Uuid,
pub user_id: Uuid,
pub token_hash: String,
pub expires_at: DateTime<Utc>,
pub created_at: DateTime<Utc>,
pub last_used: DateTime<Utc>,
pub user_agent: Option<String>,
pub ip_address: Option<String>,
pub is_active: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = user_preferences)]
pub struct UserPreference {
pub id: Uuid,
pub user_id: Uuid,
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[diesel(table_name = crate::core::shared::models::schema::organization_invitations)]
pub struct OrganizationInvitation {