-
Notifications
You must be signed in to change notification settings - Fork 0
Database Schema Reference
TMI uses two primary data stores: PostgreSQL for persistent data and Redis for real-time collaboration and caching.
The TMI database schema supports a collaborative threat modeling platform with the following key features:
- Multi-Database Support: PostgreSQL, Oracle ADB, MySQL, SQL Server, SQLite
- OAuth-based Authentication: Multi-provider OAuth support
- Role-Based Access Control (RBAC): Granular permissions for threat models (owner, writer, reader)
- Hierarchical Data Model: Threat models contain threats, diagrams, documents, notes, and repositories
- Real-time Collaboration: WebSocket-based diagram collaboration with session management
- Flexible Metadata System: Key-value metadata for all entity types
- Audit Trail: Complete timestamps and user tracking
TMI uses GORM AutoMigrate for schema management. The schema is defined in Go structs in api/models/models.go, which serves as the single source of truth for all supported databases.
# Schema is automatically created/updated on server startup
make start-dev
# The server runs GORM AutoMigrate which creates all required tablesThe schema includes the following tables (defined in api/models/models.go):
| Table | Purpose |
|---|---|
users |
User accounts with OAuth provider information |
refresh_tokens |
JWT refresh token management |
client_credentials |
OAuth 2.0 client credentials for machine-to-machine auth |
groups |
Identity provider groups |
group_members |
User memberships in groups |
| Table | Purpose |
|---|---|
threat_models |
Central threat modeling projects |
threat_model_access |
Role-based access control (owner, writer, reader) |
threats |
Individual security threats with severity levels |
diagrams |
Visual diagram storage with JSON cells |
assets |
Assets within threat models |
| Table | Purpose |
|---|---|
documents |
Document references |
notes |
Notes attached to threat models |
repositories |
Source code repository references |
metadata |
Flexible key-value metadata for all entity types |
| Table | Purpose |
|---|---|
collaboration_sessions |
WebSocket collaboration session management |
session_participants |
Active participant tracking |
| Table | Purpose |
|---|---|
webhook_subscriptions |
Webhook subscription configurations |
webhook_deliveries |
Webhook delivery attempts |
webhook_quotas |
Per-user webhook quotas |
webhook_url_deny_list |
Blocked URL patterns for webhooks |
addons |
Addon configurations |
addon_invocation_quotas |
Per-user addon invocation quotas |
| Table | Purpose |
|---|---|
administrators |
Administrator users and groups |
user_api_quotas |
Per-user API rate limits |
user_preferences |
User preferences stored as JSON |
TMI implements several important database design patterns:
All tables use UUIDs (varchar(36)) for primary keys, generated automatically via GORM's BeforeCreate hook using uuid.New().String().
Users and groups are scoped by OAuth provider to support multi-provider authentication:
- Provider field stores: "tmi", "google", "github", "microsoft", "azure"
- Users are provider-scoped:
alice@googleandalice@githubare different users - Groups support provider-specific or wildcard ("*") for cross-provider groups
Authorization tables (threat_model_access, administrators) support both user and group subjects using XOR constraints:
- Either
user_internal_uuidORgroup_internal_uuidis populated, never both -
subject_typefield discriminates between 'user' and 'group'
Child resources inherit authorization from their parent threat model:
- Diagrams, threats, assets, documents, notes, repositories all inherit from
threat_models - No direct access control on child resources - access is determined by threat model access
The threat_model_framework field supports five methodologies:
- CIA - Confidentiality, Integrity, Availability
- STRIDE - Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege (default)
- LINDDUN - Linkability, Identifiability, Non-repudiation, Detectability, Disclosure of information, Unawareness, Non-compliance
- DIE - Distributed, Immutable, Ephemeral
- PLOT4ai - AI-focused threat modeling
The assets.type field supports:
- data, hardware, software, infrastructure, service, personnel
All tables use UUID (varchar(36)) as primary keys, generated automatically on record creation.
All tables include:
-
created_at- Record creation time (auto-generated) -
modified_at- Last modification time (auto-updated)
-
threat_model_accessreferencesthreat_modelsandusers - All sub-resources (threats, diagrams, documents, notes, repositories) reference
threat_models -
threatsoptionally referencediagramsandassets -
collaboration_sessionsreferencethreat_modelsanddiagrams
Authorization is stored in threat_model_access:
- Owner - Full read/write/delete permissions, can manage access
- Writer - Read and write permissions
- Reader - Read-only permissions
Access can be granted to individual users or groups.
Redis provides real-time collaboration features and comprehensive caching with structured key patterns.
All Redis keys follow a hierarchical naming pattern:
{namespace}:{type}:{identifier}:{sub-identifier}
| Key Pattern | Data Type | TTL | Description |
|---|---|---|---|
session:{user_id}:{session_id} |
Hash | 24 hours | User session data |
auth:token:{token_id} |
String | Token expiry | JWT token cache |
auth:refresh:{refresh_token_id} |
Hash | 30 days | Refresh token data |
auth:state:{state} |
Hash | 10 minutes | OAuth state data for PKCE flow |
blacklist:token:{jti} |
String | Token expiry | Revoked JWT tokens |
| Key Pattern | Data Type | TTL | Description |
|---|---|---|---|
rate_limit:global:{ip}:{endpoint} |
String | 1 minute | Global rate limiting per IP/endpoint |
rate_limit:user:{user_id}:{action} |
String | 1 minute | User-specific rate limiting |
rate_limit:api:{api_key}:{endpoint} |
String | 1 hour | API key rate limiting |
| Key Pattern | Data Type | TTL | Description |
|---|---|---|---|
cache:user:{user_id} |
JSON | 15 minutes | User profile cache |
cache:threat_model:{model_id} |
JSON | 10 minutes | Threat model cache |
cache:diagram:{diagram_id} |
JSON | 2 minutes | Diagram data cache |
cache:threat:{threat_id} |
JSON | 5 minutes | Individual threat cache |
cache:document:{document_id} |
JSON | 5 minutes | Document reference cache |
cache:repository:{repository_id} |
JSON | 5 minutes | Repository cache |
cache:note:{note_id} |
JSON | 5 minutes | Note cache |
cache:asset:{asset_id} |
JSON | 5 minutes | Asset cache |
cache:metadata:{entity_type}:{entity_id} |
JSON | 7 minutes | Entity metadata cache |
cache:cells:{diagram_id} |
JSON | 2 minutes | Diagram cells cache |
cache:auth:{threat_model_id} |
JSON | 15 minutes | Authorization data cache |
cache:list:{entity_type}:{parent_id}:{offset}:{limit} |
JSON | 5 minutes | Paginated list cache |
| Key Pattern | Data Type | TTL | Description |
|---|---|---|---|
temp:export:{job_id} |
Hash | 1 hour | Export job status |
temp:import:{job_id} |
Hash | 1 hour | Import job status |
lock:{resource}:{id} |
String | 30 seconds | Distributed locks |
| Cache Type | TTL | Justification |
|---|---|---|
| Threat Models | 10 minutes | Core entities, moderate update frequency |
| Diagrams | 2 minutes | High collaboration, real-time updates |
| Sub-resources | 5 minutes | Threats, documents, repositories - balanced consistency |
| Authorization | 15 minutes | Security-critical, infrequent changes |
| Metadata | 7 minutes | Flexible data, moderate update frequency |
| Lists | 5 minutes | Paginated results, balance between performance and freshness |
TMI implements proactive cache invalidation through the CacheService:
- Entity Updates: Individual entity caches are invalidated on modification
- Metadata Changes: Entity-specific metadata caches are cleared
- Authorization Updates: Auth data cache is invalidated on role changes
- Cascade Invalidation: Parent entity updates trigger related cache clearing
# Connect to Redis
redis-cli
# View all keys by pattern
redis-cli --scan --pattern "cache:threat_model:*"
# Check TTL of a key
redis-cli TTL "cache:threat_model:uuid-here"
# Monitor real-time activity
redis-cli MONITORThe definitive schema is defined in:
-
api/models/models.go- 25 GORM model definitions for all tables (single source of truth) -
api/validation/validators.go- Business rules (replaces PostgreSQL CHECK constraints) -
api/seed/seed.go- Required initial data (everyone group, webhook deny list)
To view the complete schema with all field types and constraints, refer to the source code.
TMI originally used golang-migrate with PostgreSQL-specific SQL migration files. When multi-database support was added (PostgreSQL, Oracle, MySQL, SQL Server, SQLite), the architecture was changed to use GORM AutoMigrate.
Legacy SQL migration files exist in docs/reference/legacy-migrations/ for historical reference. These are preserved for:
- Reference: Understanding the original PostgreSQL-specific schema design
- Documentation: Viewing what triggers, partial indexes, and CHECK constraints were used
- Troubleshooting: Comparing GORM-generated schema with the original design
PostgreSQL-Specific Features (No Longer Used):
- Partial indexes (e.g.,
WHERE deleted_at IS NULL) - GIN indexes for JSONB columns
- Covering indexes (INCLUDE clause)
- PostgreSQL triggers for
modified_attimestamps - CHECK constraints for enum validation
- Native UUID type (GORM uses
varchar(36)for Oracle compatibility)
Note: These legacy migration files are not executed by the current codebase. They are for reference only.
# View schema in PostgreSQL
psql -U tmi_dev -d tmi_dev -c "\dt"
# View table structure
psql -U tmi_dev -d tmi_dev -c "\d+ threat_models"
# Export schema
pg_dump -U tmi_dev -d tmi_dev --schema-only > schema.sqlThe TMI WebSocket API uses JSON messages for real-time collaboration. See WebSocket-API-Reference for complete documentation.
All WebSocket messages include:
-
message_type- Message type identifier -
timestamp- ISO 8601 timestamp
// Diagram operation message
{
"message_type": "diagram_operation",
"user_internal_uuid": "UUID",
"operation_id": "UUID",
"sequence_number": 1,
"operation": {
"type": "patch",
"cells": [
{
"id": "cell-id",
"operation": "add|update|remove",
"data": {}
}
]
},
"timestamp": "2025-01-24T12:00:00Z"
}
// Presenter mode messages
{
"message_type": "current_presenter",
"current_presenter": "UUID",
"timestamp": "2025-01-24T12:00:00Z"
}
// Session management
{
"event": "join|leave|session_ended",
"user_internal_uuid": "UUID",
"message": "optional reason",
"timestamp": "2025-01-24T12:00:00Z"
}- Database-Operations - Operational procedures
- Database-Setup - Initial database deployment
- Performance-and-Scaling - Optimize schema for scale
- WebSocket-API-Reference - WebSocket message format details
- Configuration-Reference - Server and application configuration
- Using TMI for Threat Modeling
- Accessing TMI
- Creating Your First Threat Model
- Understanding the User Interface
- Working with Data Flow Diagrams
- Managing Threats
- Collaborative Threat Modeling
- Using Notes and Documentation
- Metadata and Extensions
- Planning Your Deployment
- Deploying TMI Server
- OCI Container Deployment
- Terraform Deployment
- Certificate Automation
- Deploying TMI Web Application
- Setting Up Authentication
- Database Setup
- Component Integration
- Post-Deployment
- Monitoring and Health
- Cloud Logging
- Database Operations
- Security Operations
- Performance and Scaling
- Maintenance Tasks