KrakenHashes Database Schema Reference¶
This document provides a comprehensive reference for the KrakenHashes database schema, extracted from migration files (v0.1.0-alpha).
Table of Contents¶
- Core Tables
- users
- teams
- user_teams
- Authentication & Security
- auth_tokens
- user_passkeys
- pending_passkey_registration
- pending_passkey_authentication
- mfa_methods
- mfa_backup_codes
- login_attempts
- security_events
- Agent Management
- agents
- agent_metrics
- agent_teams
- claim_vouchers
- claim_voucher_usage
- Email System
- email_config
- email_templates
- email_usage
- Hash Management
- hashlists
- hashes
- hashcat_hash_types
- LM/NTLM Support
- lm_hash_metadata
- linked_hashlists
- linked_hashes
- Job Management
- job_workflows
- job_executions
- job_tasks
- job_increment_layers
- preset_increment_layers
- job_execution_settings
- Resource Management
- wordlists
- rules
- binary_versions
- Client & Settings
- clients
- client_settings
- system_settings
- Performance & Scheduling
- Notifications & Audit
- Migration History
Core Tables¶
users¶
User accounts for the system, including the special system user with UUID 00000000-0000-0000-0000-000000000000.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique user identifier |
| username | VARCHAR(255) | UNIQUE NOT NULL | Username for login | |
| first_name | VARCHAR(255) | User's first name | ||
| last_name | VARCHAR(255) | User's last name | ||
| VARCHAR(255) | UNIQUE NOT NULL | User's email address | ||
| password_hash | VARCHAR(255) | NOT NULL | Bcrypt password hash | |
| role | VARCHAR(50) | NOT NULL, CHECK | 'user' | Role: user, admin, agent, system |
| status | VARCHAR(50) | NOT NULL | 'active' | Account status |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Account creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
Indexes: - idx_users_username (username) - idx_users_email (email) - idx_users_role (role)
Triggers: - update_users_updated_at: Updates updated_at on row modification
teams¶
Organizational teams for grouping users.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique team identifier |
| name | VARCHAR(100) | NOT NULL, UNIQUE | Team name | |
| description | TEXT | Team description | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Team creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
Indexes: - idx_teams_name (name)
Triggers: - update_teams_updated_at: Updates updated_at on row modification
user_teams¶
Junction table for user-team relationships.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| user_id | UUID | NOT NULL, FK → users(id) | User reference | |
| team_id | UUID | NOT NULL, FK → teams(id) | Team reference | |
| role | VARCHAR(50) | NOT NULL, CHECK | 'member' | Role in team: member, admin |
| joined_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Join timestamp |
Primary Key: (user_id, team_id)
Indexes: - idx_user_teams_user_id (user_id) - idx_user_teams_team_id (team_id)
Authentication & Security¶
auth_tokens¶
Stores refresh tokens for JWT authentication.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Token identifier |
| user_id | UUID | NOT NULL, FK → users(id) | User reference | |
| token | VARCHAR(255) | NOT NULL, UNIQUE | Refresh token value | |
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Token creation time |
Indexes: - idx_auth_tokens_token (token) - idx_auth_tokens_user_id (user_id)
user_passkeys¶
Stores registered WebAuthn/FIDO2 passkey credentials for users.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Passkey identifier |
| user_id | UUID | NOT NULL, FK → users(id) ON DELETE CASCADE | User reference | |
| credential_id | BYTEA | NOT NULL, UNIQUE | WebAuthn credential ID | |
| public_key | BYTEA | NOT NULL | Public key for verification | |
| aaguid | BYTEA | Authenticator attestation GUID | ||
| sign_count | BIGINT | NOT NULL | 0 | Sign counter for clone detection |
| transports | TEXT[] | '{}' | Supported transports (usb, nfc, ble, internal) | |
| name | VARCHAR(255) | NOT NULL | 'Passkey' | User-assigned passkey name |
| backup_eligible | BOOLEAN | NOT NULL | FALSE | Passkey can be synced/backed up |
| backup_state | BOOLEAN | NOT NULL | FALSE | Passkey is currently backed up |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Registration time |
| last_used_at | TIMESTAMP WITH TIME ZONE | Last authentication time |
Unique Constraint: (user_id, credential_id)
Indexes: - idx_user_passkeys_user_id (user_id) - idx_user_passkeys_credential_id (credential_id)
Security Features: - Clone Detection: Sign count must increase with each authentication; non-increasing counts indicate cloned authenticators - Backup Flags: Track whether passkey is synced across devices (Bitwarden, iCloud Keychain, etc.) - Phishing Resistant: Credentials are bound to the configured RP ID (domain)
pending_passkey_registration¶
Stores temporary challenges during passkey registration flow (5-minute expiry).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| user_id | UUID | PRIMARY KEY, FK → users(id) ON DELETE CASCADE | User registering passkey | |
| challenge | BYTEA | NOT NULL | WebAuthn challenge bytes | |
| session_data | BYTEA | NOT NULL | Serialized session state | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Challenge creation time |
Notes: - Only one pending registration per user at a time - Challenges expire after 5 minutes - Cleanup trigger removes expired entries
pending_passkey_authentication¶
Stores temporary challenges during passkey MFA authentication flow (5-minute expiry).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| session_token | TEXT | PRIMARY KEY | MFA session token | |
| user_id | UUID | NOT NULL, FK → users(id) ON DELETE CASCADE | User authenticating | |
| challenge | BYTEA | NOT NULL | WebAuthn challenge bytes | |
| session_data | BYTEA | NOT NULL | Serialized session state | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Challenge creation time |
Indexes: - idx_pending_passkey_auth_user_id (user_id)
Notes: - Linked to MFA session token from login flow - Challenges expire after 5 minutes - Cleanup trigger removes expired entries
Triggers: - trigger_cleanup_passkey_challenges: Cleans up expired registration and authentication challenges
Agent Management¶
agents¶
Registered compute agents for distributed processing.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Agent identifier | |
| name | VARCHAR(255) | NOT NULL | Agent name | |
| status | VARCHAR(50) | NOT NULL | 'inactive' | Agent status |
| last_heartbeat | TIMESTAMP WITH TIME ZONE | Last heartbeat received | ||
| version | VARCHAR(50) | NOT NULL | Agent version | |
| hardware | JSONB | NOT NULL | Hardware configuration | |
| os_info | JSONB | NOT NULL | '{}' | Operating system info |
| created_by_id | UUID | NOT NULL, FK → users(id) | Creator user | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
| api_key | VARCHAR(64) | UNIQUE | Agent API key | |
| api_key_created_at | TIMESTAMP WITH TIME ZONE | API key creation time | ||
| api_key_last_used | TIMESTAMP WITH TIME ZONE | API key last usage | ||
| last_error | TEXT | Last error message | ||
| metadata | JSONB | '{}' | Additional metadata | |
| owner_id | UUID | FK → users(id) | Agent owner (added in migration 30) | |
| extra_parameters | TEXT | Extra hashcat parameters (added in migration 30) | ||
| is_enabled | BOOLEAN | NOT NULL | true | Agent enabled status (added in migration 31) |
Indexes: - idx_agents_status (status) - idx_agents_created_by (created_by_id) - idx_agents_last_heartbeat (last_heartbeat) - idx_agents_api_key (api_key) - idx_agents_owner_id (owner_id)
Triggers: - update_agents_updated_at: Updates updated_at on row modification
agent_metrics¶
Time-series metrics data for agents.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| cpu_usage | FLOAT | NOT NULL | CPU usage percentage | |
| gpu_utilization | FLOAT | NOT NULL | GPU utilization percentage | |
| gpu_temp | FLOAT | NOT NULL | GPU temperature | |
| memory_usage | FLOAT | NOT NULL | Memory usage percentage | |
| gpu_metrics | JSONB | NOT NULL | '{}' | Additional GPU metrics |
| timestamp | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Metric timestamp |
Primary Key: (agent_id, timestamp)
Indexes: - idx_agent_metrics_timestamp (timestamp)
agent_teams¶
Junction table for agent-team associations.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| team_id | UUID | NOT NULL, FK → teams(id) | Team reference |
Primary Key: (agent_id, team_id)
claim_vouchers¶
Stores active agent registration vouchers.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| code | VARCHAR(50) | PRIMARY KEY | Voucher code | |
| created_by_id | UUID | NOT NULL, FK → users(id) | Creator user | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
| is_continuous | BOOLEAN | NOT NULL | false | Can be used multiple times |
| is_active | BOOLEAN | NOT NULL | true | Voucher active status |
| used_at | TIMESTAMP WITH TIME ZONE | Usage timestamp | ||
| used_by_agent_id | INTEGER | FK → agents(id) | Agent that used voucher |
Indexes: - idx_claim_vouchers_code (code) - idx_claim_vouchers_active (is_active) - idx_claim_vouchers_created_by (created_by_id)
Triggers: - update_claim_vouchers_updated_at: Updates updated_at on row modification
claim_voucher_usage¶
Tracks usage attempts of claim vouchers.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Usage record ID | |
| voucher_code | VARCHAR(50) | NOT NULL, FK → claim_vouchers(code) | Voucher reference | |
| attempted_by_id | UUID | NOT NULL, FK → users(id) | User who attempted | |
| attempted_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Attempt timestamp |
| success | BOOLEAN | NOT NULL | false | Success status |
| ip_address | VARCHAR(45) | Client IP address | ||
| user_agent | TEXT | Client user agent | ||
| error_message | TEXT | Error message if failed |
Indexes: - idx_claim_voucher_usage_voucher (voucher_code) - idx_claim_voucher_usage_attempted_by (attempted_by_id)
Email System¶
email_config¶
Email provider configuration.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Config ID | |
| provider_type | email_provider_type | NOT NULL | Provider: mailgun, sendgrid, smtp (added in migration 084) | |
| api_key | TEXT | NOT NULL | Provider API key | |
| additional_config | JSONB | Additional configuration | ||
| monthly_limit | INTEGER | Monthly email limit | ||
| reset_date | TIMESTAMP WITH TIME ZONE | Limit reset date | ||
| is_active | BOOLEAN | NOT NULL | false | Active status |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | NOW() | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | NOW() | Last update time |
Triggers: - update_email_config_updated_at: Updates updated_at on row modification
email_templates¶
Email template definitions.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Template ID | |
| template_type | email_template_type | NOT NULL | Type: security_event, job_completion, admin_error, mfa_code | |
| name | VARCHAR(255) | NOT NULL | Template name | |
| subject | VARCHAR(255) | NOT NULL | Email subject | |
| html_content | TEXT | NOT NULL | HTML template | |
| text_content | TEXT | NOT NULL | Plain text template | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | NOW() | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | NOW() | Last update time |
| last_modified_by | UUID | FK → users(id) | Last modifier |
Indexes: - idx_email_templates_type (template_type)
Triggers: - update_email_templates_updated_at: Updates updated_at on row modification
email_usage¶
Tracks email usage for rate limiting.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Usage record ID | |
| month_year | DATE | NOT NULL, UNIQUE | Month/year for tracking | |
| count | INTEGER | NOT NULL | 0 | Email count |
| last_reset | TIMESTAMP WITH TIME ZONE | NOT NULL | NOW() | Last reset time |
Indexes: - idx_email_usage_month_year (month_year)
Hash Management¶
clients¶
Stores information about clients for whom hashlists are processed.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Client identifier |
| name | VARCHAR(255) | NOT NULL, UNIQUE | Client name | |
| description | TEXT | Client description | ||
| contact_info | TEXT | Contact information | ||
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | Creation time |
| updated_at | TIMESTAMPTZ | NOT NULL | NOW() | Last update time |
| data_retention_months | INT | NULL | Data retention policy (NULL = system default, 0 = keep forever) |
Data Retention Notes: - data_retention_months overrides system default retention policy - NULL means use system default (client_settings.default_data_retention_months) - 0 means keep data forever (no automatic deletion) - Positive integers specify months to retain data after creation - When retention period expires, hashlists and associated data are securely deleted
Indexes: - idx_clients_name (name)
Triggers: - update_clients_updated_at: Updates updated_at on row modification
hash_types¶
Stores information about supported hash types, keyed by hashcat mode ID.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | INT | PRIMARY KEY | Hashcat mode number | |
| name | VARCHAR(255) | NOT NULL | Hash type name | |
| description | TEXT | Hash type description | ||
| example | TEXT | Example hash | ||
| needs_processing | BOOLEAN | NOT NULL | FALSE | Requires preprocessing |
| processing_logic | JSONB | Processing rules as JSON | ||
| is_enabled | BOOLEAN | NOT NULL | TRUE | Hash type enabled |
| slow | BOOLEAN | NOT NULL | FALSE | Slow hash algorithm |
| is_salted | BOOLEAN | NOT NULL | FALSE | Uses per-hash salts (added in migration 107) |
Indexes: - idx_hash_types_is_salted (is_salted) - For filtering salted hash types
hashlists¶
Stores metadata about uploaded hash lists.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | Hashlist identifier | |
| name | VARCHAR(255) | NOT NULL | Hashlist name | |
| user_id | UUID | NOT NULL, FK → users(id) | Owner user | |
| client_id | UUID | FK → clients(id) | Associated client | |
| hash_type_id | INT | NOT NULL, FK → hash_types(id) | Hash type | |
| file_path | VARCHAR(1024) | File storage path | ||
| total_hashes | INT | NOT NULL | 0 | Total hash count |
| cracked_hashes | INT | NOT NULL | 0 | Cracked hash count |
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | Creation time |
| updated_at | TIMESTAMPTZ | NOT NULL | NOW() | Last update time |
| status | TEXT | NOT NULL, CHECK | Status: uploading, processing, ready, error | |
| error_message | TEXT | Error details |
Retention & Deletion Behavior: - Deletion is CASCADE - removing a hashlist deletes: - All associations in hashlist_hashes - Related agent_hashlists entries - Related job_executions and their job_tasks - File at file_path is securely overwritten with random data before deletion - Orphaned hashes (not linked to any other hashlist) are automatically deleted - VACUUM ANALYZE runs after deletion to prevent WAL recovery
Indexes: - idx_hashlists_user_id (user_id) - idx_hashlists_client_id (client_id) - idx_hashlists_hash_type_id (hash_type_id) - idx_hashlists_status (status)
Triggers: - update_hashlists_updated_at: Updates updated_at on row modification
hashes¶
Stores individual hash entries.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Hash identifier |
| hash_value | TEXT | NOT NULL | Hash value | |
| original_hash | TEXT | Original hash if processed | ||
| username | TEXT | Associated username | ||
| hash_type_id | INT | NOT NULL, FK → hash_types(id) | Hash type | |
| is_cracked | BOOLEAN | NOT NULL | FALSE | Crack status |
| password | TEXT | Cracked password | ||
| last_updated | TIMESTAMPTZ | NOT NULL | NOW() | Last update time |
| cracked_by_task_id | UUID | FK → job_tasks(id) ON DELETE SET NULL | Task that cracked this hash (added in migration 098) |
Indexes: - idx_hashes_hash_value (hash_value) - idx_hashes_original_hash_unique (original_hash) UNIQUE - Fast deduplication during bulk import (added in migration 096) - idx_hashes_cracked_by_task_id (cracked_by_task_id) WHERE cracked_by_task_id IS NOT NULL - Crack attribution lookup (added in migration 098)
Triggers: - update_hashes_last_updated: Updates last_updated on row modification
hashlist_hashes¶
Junction table for the many-to-many relationship between hashlists and hashes.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| hashlist_id | BIGINT | NOT NULL, FK → hashlists(id) | Hashlist reference | |
| hash_id | UUID | NOT NULL, FK → hashes(id) | Hash reference |
Primary Key: (hashlist_id, hash_id)
Indexes: - idx_hashlist_hashes_hashlist_id (hashlist_id) - idx_hashlist_hashes_hash_id (hash_id)
hashcat_hash_types¶
Stores hashcat-specific hash type information (added in migration 16).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| mode | INT | PRIMARY KEY | Hashcat mode number | |
| name | VARCHAR(255) | NOT NULL | Hash type name | |
| category | VARCHAR(100) | Hash category | ||
| slow_hash | BOOLEAN | FALSE | Is slow hash | |
| password_length_min | INT | Minimum password length | ||
| password_length_max | INT | Maximum password length | ||
| supports_brain | BOOLEAN | FALSE | Supports brain feature | |
| example_hash_format | TEXT | Example hash format | ||
| benchmark_mask | VARCHAR(255) | Benchmark mask | ||
| benchmark_charset1 | VARCHAR(255) | Benchmark charset 1 | ||
| autodetect_regex | TEXT | Regex for autodetection | ||
| potfile_regex | TEXT | Regex for potfile parsing | ||
| test_hash | TEXT | Test hash value | ||
| test_password | VARCHAR(255) | Test password | ||
| valid_hash_regex | TEXT | Valid hash format regex |
LM/NTLM Support (v1.2.1+)¶
lm_hash_metadata¶
Tracks partial crack status for LM hashes (hash type 3000). This table is only populated for LM hashes and has zero impact on other hash types.
Purpose: LM hashes consist of two 7-character halves that can be cracked independently. This table tracks the crack status of each half and stores the password fragments.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| hash_id | UUID | PRIMARY KEY, FK → hashes(id) | Reference to parent hash record | |
| first_half_cracked | BOOLEAN | NOT NULL | FALSE | True if first 16 chars of LM hash cracked |
| second_half_cracked | BOOLEAN | NOT NULL | FALSE | True if last 16 chars of LM hash cracked |
| first_half_password | VARCHAR(7) | NULL | Password for first half (max 7 chars) | |
| second_half_password | VARCHAR(7) | NULL | Password for second half (max 7 chars) | |
| created_at | TIMESTAMP | NOT NULL | CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | NOT NULL | CURRENT_TIMESTAMP | Last update timestamp |
Indexes: - PRIMARY KEY (hash_id) - idx_lm_metadata_crack_status (first_half_cracked, second_half_cracked) - Fast partial crack queries - idx_lm_metadata_hash_id (hash_id) - Foreign key lookup
ON DELETE: CASCADE - When parent hash is deleted, metadata is automatically removed
Use Cases: - Track partial crack progress: "First half cracked, second half pending" - Analytics: Count of partially cracked LM hashes - Strategic intelligence: Keyspace reduction from 95^14 to 95^7 when one half known - LM-to-NTLM mask generation from partial crack patterns
Example Query - Find Partial Cracks:
SELECT h.username, h.domain,
lm.first_half_password, lm.second_half_password
FROM lm_hash_metadata lm
INNER JOIN hashes h ON lm.hash_id = h.id
WHERE (lm.first_half_cracked OR lm.second_half_cracked)
AND NOT (lm.first_half_cracked AND lm.second_half_cracked);
linked_hashlists¶
Manages relationships between entire hashlists (e.g., LM hashlist ↔ NTLM hashlist from same pwdump file).
Purpose: Track which hashlists are related to enable analytics calculations and proper hashlist counting.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique link identifier |
| hashlist_id_1 | BIGINT | NOT NULL, FK → hashlists(id) | First hashlist in relationship | |
| hashlist_id_2 | BIGINT | NOT NULL, FK → hashlists(id) | Second hashlist in relationship | |
| link_type | VARCHAR(50) | NOT NULL | Type of relationship (e.g., 'lm_ntlm') | |
| created_at | TIMESTAMP | NOT NULL | CURRENT_TIMESTAMP | Link creation timestamp |
Constraints: - UNIQUE (hashlist_id_1, hashlist_id_2) - Prevents duplicate links - CHECK (hashlist_id_1 != hashlist_id_2) - Prevents self-linking
Indexes: - PRIMARY KEY (id) - idx_linked_hashlists_id2 (hashlist_id_2) - Bidirectional lookup - idx_linked_hashlists_type (link_type) - Filter by link type
ON DELETE: CASCADE - When either hashlist is deleted, link is automatically removed
Link Types: - lm_ntlm: LM and NTLM hashlists from same pwdump file
Use Cases: - Analytics: Count linked pairs as ONE hashlist (prevent double-counting) - Determine when to create individual hash-to-hash links - Track which hashlists were created together
Example Query - Find Linked Hashlists:
SELECT hl1.name AS lm_hashlist, hl2.name AS ntlm_hashlist
FROM linked_hashlists lh
INNER JOIN hashlists hl1 ON lh.hashlist_id_1 = hl1.id
INNER JOIN hashlists hl2 ON lh.hashlist_id_2 = hl2.id
WHERE lh.link_type = 'lm_ntlm';
linked_hashes¶
Manages relationships between individual hash records (e.g., specific LM hash ↔ specific NTLM hash for same user).
Purpose: Enable correlation analysis showing which users have both LM and NTLM hashes cracked, partially cracked, or uncracked.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique link identifier |
| hash_id_1 | UUID | NOT NULL, FK → hashes(id) | First hash in relationship (typically LM) | |
| hash_id_2 | UUID | NOT NULL, FK → hashes(id) | Second hash in relationship (typically NTLM) | |
| link_type | VARCHAR(50) | NOT NULL | Type of relationship (e.g., 'lm_ntlm') | |
| created_at | TIMESTAMP | NOT NULL | CURRENT_TIMESTAMP | Link creation timestamp |
Constraints: - UNIQUE (hash_id_1, hash_id_2) - Prevents duplicate links - CHECK (hash_id_1 != hash_id_2) - Prevents self-linking
Indexes: - PRIMARY KEY (id) - idx_linked_hashes_id2 (hash_id_2) - Bidirectional lookup - idx_linked_hashes_type (link_type) - Filter by link type
ON DELETE: CASCADE - When either hash is deleted, link is automatically removed
Link Types: - lm_ntlm: LM and NTLM hashes for same username/domain
Linking Strategy: Links are created by matching username and domain columns in the hashes table. This approach handles: - Domain migrations (links persist across RID changes) - Account renames (links updated if username changes) - Multi-domain environments (links only within same domain)
Use Cases: - Analytics: "Linked Hash Correlation" statistics - Show: "Administrator's LM cracked but NTLM still unknown" - Domain-filtered correlation analysis - Identify high-value targets (both hashes cracked = full compromise)
Example Query - Correlation Statistics:
SELECT
COUNT(*) AS total_pairs,
COUNT(CASE WHEN lm.is_cracked AND ntlm.is_cracked THEN 1 END) AS both_cracked,
COUNT(CASE WHEN NOT lm.is_cracked AND ntlm.is_cracked THEN 1 END) AS only_ntlm,
COUNT(CASE WHEN lm.is_cracked AND NOT ntlm.is_cracked THEN 1 END) AS only_lm,
COUNT(CASE WHEN NOT lm.is_cracked AND NOT ntlm.is_cracked THEN 1 END) AS neither
FROM linked_hashes lh
INNER JOIN hashes lm ON lh.hash_id_1 = lm.id
INNER JOIN hashes ntlm ON lh.hash_id_2 = ntlm.id
WHERE lh.link_type = 'lm_ntlm';
Job Management¶
preset_jobs¶
Stores predefined job configurations.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | uuid_generate_v4() | Job identifier |
| name | TEXT | UNIQUE NOT NULL | Job name | |
| wordlist_ids | JSONB | NOT NULL | '[]' | Array of wordlist IDs |
| rule_ids | JSONB | NOT NULL | '[]' | Array of rule IDs |
| attack_mode | INTEGER | NOT NULL, CHECK | 0 | Attack mode: 0,1,3,6,7,9 |
| priority | INTEGER | NOT NULL | Job priority | |
| chunk_size_seconds | INTEGER | NOT NULL | Chunk duration | |
| status_updates_enabled | BOOLEAN | NOT NULL | true | Enable status updates |
| is_small_job | BOOLEAN | NOT NULL | false | Small job flag |
| allow_high_priority_override | BOOLEAN | NOT NULL | false | Allows this job to interrupt lower priority running jobs when no agents available |
| binary_version | VARCHAR(255) | NOT NULL | 'default' | Binary version pattern (e.g., "default", "7.x", "7.1.2") |
| mask | TEXT | NULL | Mask pattern | |
| created_at | TIMESTAMPTZ | NOW() | Creation time | |
| updated_at | TIMESTAMPTZ | NOW() | Last update time | |
| keyspace_limit | BIGINT | Keyspace limit (added in migration 32) | ||
| max_agents | INTEGER | Max agents allowed (added in migration 32) |
Triggers: - update_preset_jobs_updated_at: Updates updated_at on row modification
job_workflows¶
Stores workflow definitions for multi-step attacks.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | uuid_generate_v4() | Workflow identifier |
| name | TEXT | UNIQUE NOT NULL | Workflow name | |
| created_at | TIMESTAMPTZ | NOW() | Creation time | |
| updated_at | TIMESTAMPTZ | NOW() | Last update time |
Triggers: - update_job_workflows_updated_at: Updates updated_at on row modification
job_workflow_steps¶
Defines steps within a workflow.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | Step identifier | |
| job_workflow_id | UUID | NOT NULL, FK → job_workflows(id) | Workflow reference | |
| preset_job_id | UUID | NOT NULL, FK → preset_jobs(id) | Preset job reference | |
| step_order | INTEGER | NOT NULL | Execution order |
Unique Constraint: (job_workflow_id, step_order)
Indexes: - idx_job_workflow_steps_job_workflow_id (job_workflow_id) - idx_job_workflow_steps_preset_job_id (preset_job_id)
job_executions¶
Tracks actual job runs.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Execution identifier |
| preset_job_id | UUID | NOT NULL, FK → preset_jobs(id) | Preset job reference | |
| hashlist_id | BIGINT | NOT NULL, FK → hashlists(id) | Hashlist reference | |
| status | VARCHAR(50) | NOT NULL, CHECK | 'pending' | Status: pending, running, paused, processing, completed, failed, cancelled (added migration 085: processing status) |
| priority | INT | NOT NULL | 0 | Execution priority |
| total_keyspace | BIGINT | Total keyspace size | ||
| processed_keyspace | BIGINT | 0 | Processed keyspace | |
| attack_mode | INT | NOT NULL | Attack mode | |
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| started_at | TIMESTAMP WITH TIME ZONE | Start time | ||
| completed_at | TIMESTAMP WITH TIME ZONE | Completion time | ||
| error_message | TEXT | Error details | ||
| interrupted_by | UUID | FK → job_executions(id) | ID of the higher priority job that interrupted this one | |
| created_by | UUID | FK → users(id) | Creator user (added in migration 33) | |
| chunk_size | INTEGER | Chunk size override (added in migration 34) | ||
| chunk_overlap | INTEGER | 0 | Chunk overlap (added in migration 34) | |
| dispatched_keyspace | BIGINT | 0 | Dispatched keyspace (added in migration 40) | |
| progress | NUMERIC(6,3) | 0 | Progress percentage (added in migration 36, updated in migration 38) | |
| consecutive_failures | INTEGER | 0 | Consecutive failure count (added in migration 37) | |
| last_failure_at | TIMESTAMP WITH TIME ZONE | Last failure time (added in migration 37) | ||
| is_accurate_keyspace | BOOLEAN | false | True when keyspace is from hashcat progress[1] values (added in migration 63) | |
| avg_rule_multiplier | FLOAT | Actual/estimated keyspace ratio for improving future estimates (added in migration 63) | ||
| completion_email_sent | BOOLEAN | false | Whether completion email was sent (added in migration 085) | |
| completion_email_sent_at | TIMESTAMP WITH TIME ZONE | When completion email was sent (added in migration 085) | ||
| completion_email_error | TEXT | Error message if email sending failed (added in migration 085) | ||
| cracking_completed_at | TIMESTAMP WITH TIME ZONE | When all tasks finished hashcat processing - job enters processing state (added in migration 100) |
Indexes: - idx_job_executions_status (status) - idx_job_executions_priority (priority, created_at) - idx_job_executions_created_by (created_by) - idx_job_executions_consecutive_failures (consecutive_failures)
job_tasks¶
Individual chunks assigned to agents.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Task identifier |
| job_execution_id | UUID | NOT NULL, FK → job_executions(id) | Job execution reference | |
| agent_id | INTEGER | FK → agents(id) | Assigned agent (nullable in migration 35) | |
| status | VARCHAR(50) | NOT NULL, CHECK | 'pending' | Status: pending, assigned, reconnect_pending, running, processing, completed, failed, cancelled (added migration 085: processing status) |
| keyspace_start | BIGINT | NOT NULL | Keyspace start | |
| keyspace_end | BIGINT | NOT NULL | Keyspace end | |
| keyspace_processed | BIGINT | 0 | Processed amount | |
| benchmark_speed | BIGINT | Hashes per second | ||
| chunk_duration | INT | NOT NULL | Duration in seconds | |
| assigned_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Assignment time | |
| started_at | TIMESTAMP WITH TIME ZONE | Start time | ||
| completed_at | TIMESTAMP WITH TIME ZONE | Completion time | ||
| last_checkpoint | TIMESTAMP WITH TIME ZONE | Last checkpoint | ||
| error_message | TEXT | Error details | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time (added in migration 25) |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time (added in migration 26) |
| progress | NUMERIC(6,3) | 0 | Progress percentage (added in migration 36, updated in migration 38) | |
| consecutive_failures | INTEGER | 0 | Consecutive failure count (added in migration 37) | |
| last_failure_at | TIMESTAMP WITH TIME ZONE | Last failure time (added in migration 37) | ||
| chunk_number | INTEGER | Chunk number for rule splits (added in migration 44) | ||
| effective_keyspace | BIGINT | Effective keyspace size (added in migration 47) | ||
| is_actual_keyspace | BOOLEAN | false | True when task has actual keyspace from hashcat progress[1] (added in migration 63) | |
| chunk_actual_keyspace | BIGINT | Immutable chunk size from hashcat progress[1] for accurate keyspace tracking (added in migration 64) | ||
| crack_count | INTEGER | 0 | Number of hashes cracked by this task (existing field) | |
| expected_crack_count | INTEGER | 0 | Expected number of cracks from final progress message (added in migration 085) | |
| received_crack_count | INTEGER | 0 | Number of cracks received via crack_batch messages (added in migration 085) | |
| batches_complete_signaled | BOOLEAN | false | Whether agent has signaled all crack batches sent (added in migration 085) | |
| increment_layer_id | UUID | FK → job_increment_layers(id) | References increment layer for increment mode jobs (added in migration 089) | |
| cracking_completed_at | TIMESTAMP WITH TIME ZONE | When hashcat finished for this task - task enters processing state (added in migration 100) | ||
| retransmit_count | INTEGER | 0 | Number of crack retransmission attempts (added in migration 099) | |
| last_retransmit_at | TIMESTAMP WITH TIME ZONE | Timestamp of last retransmission request (added in migration 099) |
Indexes: - idx_job_tasks_agent_status (agent_id, status) - idx_job_tasks_execution (job_execution_id) - idx_job_tasks_consecutive_failures (consecutive_failures) - idx_job_tasks_chunk_number (job_execution_id, chunk_number) - idx_job_tasks_increment_layer (increment_layer_id) - added in migration 089 - idx_job_tasks_cracking_completed_at (cracking_completed_at) WHERE cracking_completed_at IS NOT NULL - Efficient completion state queries (added in migration 100)
Triggers: - update_job_tasks_updated_at: Updates updated_at on row modification
job_increment_layers¶
Sub-layers for increment mode jobs. Each layer represents one mask length in the increment sequence. Added in migration 088.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Layer identifier |
| job_execution_id | UUID | NOT NULL, FK → job_executions(id) ON DELETE CASCADE | Parent job execution | |
| layer_index | INT | NOT NULL | Order in sequence (1=first) | |
| mask | VARCHAR(255) | NOT NULL | Layer-specific mask (e.g., ?l?l) | |
| status | VARCHAR(50) | NOT NULL, CHECK | 'pending' | Status: pending, running, completed, failed, cancelled |
| base_keyspace | BIGINT | Estimated keyspace from --keyspace | ||
| effective_keyspace | BIGINT | Actual keyspace from benchmark | ||
| processed_keyspace | BIGINT | 0 | Completed keyspace | |
| dispatched_keyspace | BIGINT | 0 | Assigned keyspace | |
| is_accurate_keyspace | BOOLEAN | FALSE | TRUE after benchmark provides actual keyspace | |
| overall_progress_percent | NUMERIC(5,2) | 0.00 | Layer completion percentage | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
| started_at | TIMESTAMP WITH TIME ZONE | Layer start time | ||
| completed_at | TIMESTAMP WITH TIME ZONE | Layer completion time | ||
| error_message | TEXT | Error details if failed |
Unique Constraint: (job_execution_id, layer_index)
Indexes: - idx_job_increment_layers_execution (job_execution_id) - idx_job_increment_layers_status (status)
Triggers: - update_job_increment_layers_updated_at: Updates updated_at on row modification
Purpose: - Decomposes increment mode jobs into discrete layers for distributed processing - Each layer can be scheduled and tracked independently - Multiple agents can work on different layers simultaneously - Provides granular progress tracking per mask length
Use Cases: - Track progress for each mask length in an increment mode attack - Enable parallel processing of different mask lengths - Provide detailed status per layer in the UI
Example Query - Layer Progress:
SELECT layer_index, mask, status,
overall_progress_percent,
processed_keyspace, effective_keyspace
FROM job_increment_layers
WHERE job_execution_id = 'uuid-here'
ORDER BY layer_index;
See Increment Mode Architecture for implementation details.
preset_increment_layers¶
Pre-calculated increment layers for preset jobs. When a job is created from a preset with increment mode enabled, these layers are copied to job_increment_layers. Added in migration 090.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Layer identifier |
| preset_job_id | UUID | NOT NULL, FK → preset_jobs(id) ON DELETE CASCADE | Parent preset job | |
| layer_index | INT | NOT NULL | Order in sequence (1=first) | |
| mask | VARCHAR(512) | NOT NULL | Layer-specific mask (e.g., ?l?l) | |
| base_keyspace | BIGINT | Estimated keyspace from --keyspace | ||
| effective_keyspace | BIGINT | Calculated keyspace | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
Unique Constraint: (preset_job_id, layer_index)
Indexes: - idx_preset_increment_layers_preset_job_id (preset_job_id)
Triggers: - update_preset_increment_layers_updated_at: Updates updated_at on row modification
Purpose: - Pre-calculate layers at preset creation time rather than job creation time - Ensures consistent keyspace calculations across all jobs created from the same preset - Faster job creation (no need to re-run hashcat --keyspace for each layer) - Preset keyspace = sum of all layer effective_keyspaces
Data Flow: 1. Admin creates preset job with increment mode → preset_increment_layers populated 2. User creates job from preset → layers copied from preset_increment_layers to job_increment_layers 3. Job inherits preset's total keyspace
See Increment Mode Architecture for implementation details.
job_execution_settings¶
Settings for job executions (added in migration 21).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Settings ID | |
| name | VARCHAR(255) | NOT NULL, UNIQUE | Setting name | |
| value | TEXT | NOT NULL | Setting value | |
| description | TEXT | Setting description | ||
| data_type | VARCHAR(50) | NOT NULL | 'string' | Data type |
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| updated_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last update time |
Indexes: - idx_job_execution_settings_name (name)
Triggers: - update_job_execution_settings_updated_at: Updates updated_at on row modification
Resource Management¶
binary_versions¶
Stores information about different versions of hash cracking binaries. Supports both URL downloads and direct uploads.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Version ID | |
| binary_type | binary_type | NOT NULL | Type: hashcat, john | |
| compression_type | compression_type | NOT NULL | Compression: 7z, zip, tar.gz, tar.xz | |
| source_type | VARCHAR(50) | NOT NULL | 'url' | Source type: 'url' or 'upload' |
| source_url | TEXT | Download URL (NULL for uploads) | ||
| file_name | VARCHAR(255) | NOT NULL | File name | |
| md5_hash | VARCHAR(32) | NOT NULL | MD5 hash | |
| file_size | BIGINT | NOT NULL | File size in bytes | |
| version | VARCHAR(100) | Version string (e.g., "6.2.6", "7.1.2+338") | ||
| description | TEXT | Human-readable description | ||
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| created_by | UUID | NOT NULL, FK → users(id) | Creator user | |
| is_active | BOOLEAN | true | Active status | |
| is_default | BOOLEAN | false | Whether this is the default version | |
| last_verified_at | TIMESTAMP WITH TIME ZONE | Last verification time | ||
| verification_status | VARCHAR(50) | 'pending' | Status: pending, verified, failed, deleted |
Indexes: - idx_binary_versions_type_active (binary_type) WHERE is_active = true - idx_binary_versions_verification (verification_status)
binary_version_audit_log¶
Tracks all changes and actions performed on binary versions.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Audit log ID | |
| binary_version_id | INTEGER | NOT NULL, FK → binary_versions(id) | Binary version reference | |
| action | VARCHAR(50) | NOT NULL | Action performed | |
| performed_by | UUID | NOT NULL, FK → users(id) | User who performed action | |
| performed_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Action timestamp | |
| details | JSONB | Additional details |
Indexes: - idx_binary_version_audit_binary_id (binary_version_id) - idx_binary_version_audit_performed_at (performed_at)
wordlists¶
Stores information about wordlists used for password cracking.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Wordlist ID | |
| name | VARCHAR(255) | NOT NULL | Wordlist name | |
| description | TEXT | Description | ||
| wordlist_type | wordlist_type | NOT NULL | Type: general, specialized, targeted, custom | |
| format | wordlist_format | NOT NULL | 'plaintext' | Format: plaintext, compressed |
| file_name | VARCHAR(255) | NOT NULL | File name | |
| md5_hash | VARCHAR(32) | NOT NULL | MD5 hash | |
| file_size | BIGINT | NOT NULL | File size in bytes | |
| word_count | BIGINT | Number of words | ||
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| created_by | UUID | NOT NULL, FK → users(id) | Creator user | |
| updated_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last update time | |
| updated_by | UUID | FK → users(id) | Last updater | |
| last_verified_at | TIMESTAMP WITH TIME ZONE | Last verification time | ||
| verification_status | VARCHAR(50) | 'pending' | Status: pending, verified, failed |
Indexes: - idx_wordlists_name (name) - idx_wordlists_type (wordlist_type) - idx_wordlists_verification (verification_status) - idx_wordlists_md5 (md5_hash)
wordlist_audit_log¶
Tracks all changes and actions performed on wordlists.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Audit log ID | |
| wordlist_id | INTEGER | NOT NULL, FK → wordlists(id) | Wordlist reference | |
| action | VARCHAR(50) | NOT NULL | Action performed | |
| performed_by | UUID | NOT NULL, FK → users(id) | User who performed action | |
| performed_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Action timestamp | |
| details | JSONB | Additional details |
Indexes: - idx_wordlist_audit_wordlist_id (wordlist_id) - idx_wordlist_audit_performed_at (performed_at)
wordlist_tags¶
Stores tags associated with wordlists.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Tag ID | |
| wordlist_id | INTEGER | NOT NULL, FK → wordlists(id) | Wordlist reference | |
| tag | VARCHAR(50) | NOT NULL | Tag value | |
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| created_by | UUID | NOT NULL, FK → users(id) | Creator user |
Unique Index: idx_wordlist_tags_unique (wordlist_id, tag)
Indexes: - idx_wordlist_tags_tag (tag)
rules¶
Stores information about rules used for password cracking.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Rule ID | |
| name | VARCHAR(255) | NOT NULL | Rule name | |
| description | TEXT | Description | ||
| rule_type | rule_type | NOT NULL | Type: hashcat, john | |
| file_name | VARCHAR(255) | NOT NULL | File name | |
| md5_hash | VARCHAR(32) | NOT NULL | MD5 hash | |
| file_size | BIGINT | NOT NULL | File size in bytes | |
| rule_count | INTEGER | Number of rules | ||
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| created_by | UUID | NOT NULL, FK → users(id) | Creator user | |
| updated_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last update time | |
| updated_by | UUID | FK → users(id) | Last updater | |
| last_verified_at | TIMESTAMP WITH TIME ZONE | Last verification time | ||
| verification_status | VARCHAR(50) | 'pending' | Status: pending, verified, failed | |
| estimated_keyspace_multiplier | FLOAT | Keyspace multiplier estimate |
Indexes: - idx_rules_name (name) - idx_rules_type (rule_type) - idx_rules_verification (verification_status) - idx_rules_md5 (md5_hash)
rule_audit_log¶
Tracks all changes and actions performed on rules.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Audit log ID | |
| rule_id | INTEGER | NOT NULL, FK → rules(id) | Rule reference | |
| action | VARCHAR(50) | NOT NULL | Action performed | |
| performed_by | UUID | NOT NULL, FK → users(id) | User who performed action | |
| performed_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Action timestamp | |
| details | JSONB | Additional details |
Indexes: - idx_rule_audit_rule_id (rule_id) - idx_rule_audit_performed_at (performed_at)
rule_tags¶
Stores tags associated with rules.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Tag ID | |
| rule_id | INTEGER | NOT NULL, FK → rules(id) | Rule reference | |
| tag | VARCHAR(50) | NOT NULL | Tag value | |
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| created_by | UUID | NOT NULL, FK → users(id) | Creator user |
Unique Index: idx_rule_tags_unique (rule_id, tag)
Indexes: - idx_rule_tags_tag (tag)
rule_wordlist_compatibility¶
Stores compatibility information between rules and wordlists.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Compatibility ID | |
| rule_id | INTEGER | NOT NULL, FK → rules(id) | Rule reference | |
| wordlist_id | INTEGER | NOT NULL, FK → wordlists(id) | Wordlist reference | |
| compatibility_score | FLOAT | NOT NULL | 1.0 | Score from 0.0 to 1.0 |
| notes | TEXT | Compatibility notes | ||
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| created_by | UUID | NOT NULL, FK → users(id) | Creator user | |
| updated_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last update time | |
| updated_by | UUID | FK → users(id) | Last updater |
Unique Index: idx_rule_wordlist_unique (rule_id, wordlist_id)
Indexes: - idx_rule_wordlist_rule (rule_id) - idx_rule_wordlist_wordlist (wordlist_id)
Client & Settings¶
client_settings¶
Stores client-specific settings (added in migration 17). Also used for system-wide settings without a client_id.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Settings ID | |
| client_id | UUID | NOT NULL, FK → clients(id) | Client reference | |
| key | VARCHAR(255) | NOT NULL | Setting key | |
| value | TEXT | Setting value | ||
| data_type | VARCHAR(50) | NOT NULL | 'string' | Data type |
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| updated_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last update time |
Important System-Wide Settings: - default_data_retention_months - Default retention period for all hashlists (when client_id is NULL) - last_purge_run - Timestamp of last retention purge execution
Unique Constraint: (client_id, key)
Indexes: - idx_client_settings_client (client_id)
Triggers: - update_client_settings_updated_at: Updates updated_at on row modification
system_settings¶
Stores global system-wide settings.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| key | VARCHAR(255) | PRIMARY KEY | Setting key | |
| value | TEXT | Setting value | ||
| description | TEXT | Setting description | ||
| data_type | VARCHAR(50) | NOT NULL | 'string' | Data type: string, integer, boolean, float |
| updated_at | TIMESTAMPTZ | NOT NULL | NOW() | Last update time |
Default Settings: - max_job_priority: 1000 (integer) - agent_scheduling_enabled: false (boolean) - added in migration 42 - hashcat_speedtest_timeout: 300 (integer) - added in migration 39 - task_heartbeat_timeout: 300 (integer) - added in migration 46 - agent_overflow_allocation_mode: 'fifo' (string) - added in migration 82 - Values: 'fifo' (default) or 'round_robin' - Controls how overflow agents are distributed among same-priority jobs - FIFO: Oldest job gets all overflow agents - Round-robin: Distribute evenly across all jobs - hashlist_bulk_batch_size: 100000 (integer) - added in migration 097 - Number of hashes to process per batch during hashlist uploads - Higher values (500K-1M) may improve performance for large hashlists but use more memory - Lower values reduce memory usage but increase processing time
Triggers: - update_system_settings_updated_at: Updates updated_at on row modification
Performance & Scheduling¶
benchmark_requests¶
Tracks parallel benchmark execution requests (added in migration 83).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Request identifier |
| agent_id | INTEGER | NOT NULL, FK → agents(id) ON DELETE CASCADE | Agent reference | |
| job_execution_id | UUID | FK → job_executions(id) ON DELETE CASCADE | Job execution reference (for forced benchmarks) | |
| hash_type | INTEGER | NOT NULL | Hash type to benchmark | |
| attack_mode | INTEGER | NOT NULL | Attack mode to benchmark | |
| benchmark_type | VARCHAR(50) | NOT NULL | Type: 'forced' or 'agent_speed' | |
| status | VARCHAR(50) | NOT NULL | 'pending' | Status: pending, completed, failed |
| requested_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Request timestamp |
| completed_at | TIMESTAMP WITH TIME ZONE | Completion timestamp | ||
| result | JSONB | Benchmark result data | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
Purpose: - Enables polling-based coordination of async WebSocket benchmarks - Supports parallel benchmark execution for dramatic performance improvements - Tracks both forced benchmarks (for accurate keyspace) and agent speed benchmarks - Cleaned up after each scheduling cycle
Benchmark Types: - forced: Run full hashcat benchmark with actual job configuration to obtain accurate keyspace - agent_speed: Standard hashcat speed test to update agent performance metrics
Indexes: - idx_benchmark_requests_status (status) WHERE status = 'pending' - idx_benchmark_requests_agent (agent_id) - idx_benchmark_requests_job (job_execution_id)
Performance Impact: - Before (Sequential): 15 agents × 30s = 450 seconds - After (Parallel): 15 agents in ~12 seconds - Improvement: 96% reduction (37.5x faster)
agent_benchmarks¶
Stores benchmark results for agents.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Benchmark ID |
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| attack_mode | INT | NOT NULL | Attack mode | |
| hash_type | INT | NOT NULL | Hash type | |
| speed | BIGINT | NOT NULL | Hashes per second | |
| salt_count | INT | Salt count for salted hash types (added in migration 109) | ||
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| updated_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last update time |
Unique Constraint: (agent_id, attack_mode, hash_type, salt_count) - Uses IS NOT DISTINCT FROM for NULL-safe comparison
Indexes: - idx_agent_benchmarks_lookup (agent_id, attack_mode, hash_type, salt_count)
agent_performance_metrics¶
Historical performance tracking for agents.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Metric ID |
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| metric_type | VARCHAR(50) | NOT NULL, CHECK | Type: hash_rate, utilization, temperature, power_usage | |
| value | NUMERIC | NOT NULL | Metric value | |
| timestamp | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Metric timestamp | |
| aggregation_level | VARCHAR(20) | NOT NULL, CHECK | 'realtime' | Level: realtime, daily, weekly |
| period_start | TIMESTAMP WITH TIME ZONE | Aggregation period start | ||
| period_end | TIMESTAMP WITH TIME ZONE | Aggregation period end |
Indexes: - idx_agent_metrics_lookup (agent_id, metric_type, timestamp) - idx_agent_metrics_aggregation (aggregation_level, timestamp)
performance_metrics¶
Detailed performance metrics (added in migration 41).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Metric ID |
| job_task_id | UUID | FK → job_tasks(id) | Job task reference | |
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| device_id | INTEGER | Device ID | ||
| device_name | VARCHAR(255) | Device name | ||
| timestamp | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Metric timestamp |
| hash_rate | BIGINT | Current hash rate | ||
| utilization | FLOAT | GPU utilization % | ||
| temperature | FLOAT | Temperature in Celsius | ||
| power_usage | FLOAT | Power usage in watts | ||
| memory_used | BIGINT | Memory used in bytes | ||
| memory_total | BIGINT | Total memory in bytes | ||
| fan_speed | FLOAT | Fan speed % | ||
| core_clock | INTEGER | Core clock in MHz | ||
| memory_clock | INTEGER | Memory clock in MHz | ||
| pcie_rx | BIGINT | PCIe RX throughput | ||
| pcie_tx | BIGINT | PCIe TX throughput |
Indexes: - idx_performance_metrics_timestamp (timestamp) - idx_performance_metrics_agent (agent_id, timestamp) - idx_performance_metrics_job_task (job_task_id) - idx_performance_metrics_device (agent_id, device_id, timestamp)
job_performance_metrics¶
Job-level performance tracking.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Metric ID |
| job_execution_id | UUID | NOT NULL, FK → job_executions(id) | Job execution reference | |
| metric_type | VARCHAR(50) | NOT NULL, CHECK | Type: hash_rate, progress_percentage, cracks_found | |
| value | NUMERIC | NOT NULL | Metric value | |
| timestamp | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Metric timestamp | |
| aggregation_level | VARCHAR(20) | NOT NULL, CHECK | 'realtime' | Level: realtime, daily, weekly |
| period_start | TIMESTAMP WITH TIME ZONE | Aggregation period start | ||
| period_end | TIMESTAMP WITH TIME ZONE | Aggregation period end |
Indexes: - idx_job_metrics_lookup (job_execution_id, metric_type, timestamp)
agent_hashlists¶
Tracks hashlist distribution to agents.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Record ID |
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| hashlist_id | BIGINT | NOT NULL, FK → hashlists(id) | Hashlist reference | |
| file_path | TEXT | NOT NULL | Local file path | |
| downloaded_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Download time | |
| last_used_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last usage time | |
| file_hash | VARCHAR(32) | MD5 hash for verification |
Unique Constraint: (agent_id, hashlist_id)
Indexes: - idx_agent_hashlists_cleanup (last_used_at)
agent_devices¶
Tracks individual physical compute devices with runtime selection support (updated in migration 81).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Device record ID | |
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| device_id | INTEGER | NOT NULL | Physical device index (0-based) | |
| device_name | VARCHAR(255) | NOT NULL | Device name | |
| device_type | VARCHAR(50) | NOT NULL | Type: GPU or CPU | |
| enabled | BOOLEAN | NOT NULL | TRUE | Device enabled status |
| runtime_options | JSONB | NOT NULL | '[]'::jsonb | Available runtimes with capabilities |
| selected_runtime | VARCHAR(50) | Active runtime (CUDA/HIP/OpenCL) | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
Unique Constraint: (agent_id, device_id)
Indexes: - idx_agent_devices_agent_id (agent_id) - idx_agent_devices_enabled (agent_id, enabled)
Triggers: - update_agent_devices_updated_at: Updates updated_at on row modification
Runtime Options Structure (JSONB):
[
{
"backend": "HIP",
"device_id": 1,
"processors": 16,
"clock": 2208,
"memory_total": 8176,
"memory_free": 8064,
"pci_address": "03:00.0"
}
]
Migration History: - Migration 29: Initial table creation - Migration 81: Added runtime_options and selected_runtime columns for GPU runtime selection
agent_schedules¶
Stores daily scheduling information for agents (added in migration 42).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | SERIAL | PRIMARY KEY | Schedule ID | |
| agent_id | INTEGER | NOT NULL, FK → agents(id) | Agent reference | |
| day_of_week | INTEGER | NOT NULL, CHECK | Day: 0=Sunday...6=Saturday | |
| start_time | TIME | NOT NULL | Start time in UTC | |
| end_time | TIME | NOT NULL | End time in UTC | |
| timezone | VARCHAR(50) | NOT NULL | 'UTC' | Original timezone |
| is_active | BOOLEAN | NOT NULL | true | Schedule active status |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
| updated_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Last update time |
Unique Constraint: (agent_id, day_of_week)
Check Constraint: end_time != start_time (allows overnight schedules)
Indexes: - idx_agent_schedules_agent_id (agent_id) - idx_agent_schedules_day_active (day_of_week, is_active)
Triggers: - update_agent_schedules_updated_at: Updates updated_at on row modification
Authentication & Security (Extended)¶
The users table has been extended with additional security columns added through migrations:
Additional users columns¶
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| mfa_enabled | BOOLEAN | FALSE | MFA enabled status | |
| mfa_type | text[] | CHECK | ARRAY['email'] | MFA types enabled: email, authenticator, backup, passkey |
| mfa_secret | TEXT | MFA secret | ||
| backup_codes | TEXT[] | Hashed backup codes | ||
| last_password_change | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last password change | |
| failed_login_attempts | INT | 0 | Failed login count | |
| last_failed_attempt | TIMESTAMP WITH TIME ZONE | Last failed attempt | ||
| account_locked | BOOLEAN | FALSE | Account lock status | |
| account_locked_until | TIMESTAMP WITH TIME ZONE | Lock expiration | ||
| account_enabled | BOOLEAN | TRUE | Account enabled status | |
| last_login | TIMESTAMP WITH TIME ZONE | Last successful login | ||
| disabled_reason | TEXT | Reason for disabling | ||
| disabled_at | TIMESTAMP WITH TIME ZONE | Disable timestamp | ||
| disabled_by | UUID | FK → users(id) | Who disabled account | |
| preferred_mfa_method | VARCHAR(20) | Preferred MFA method | ||
| deleted_at | TIMESTAMP WITH TIME ZONE | Soft delete timestamp (migration 106) |
Indexes (users table): - idx_users_deleted_at (deleted_at) WHERE deleted_at IS NULL - Efficient filtering of active users
tokens¶
JWT token storage with sliding window session support (added in migration 7, updated in migration 101).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Token ID |
| user_id | UUID | NOT NULL, FK → users(id) | User reference | |
| token | TEXT | NOT NULL, UNIQUE | Token value | |
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Creation time | |
| last_used_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last usage time | |
| expires_at | TIMESTAMP WITH TIME ZONE | NOT NULL | Expiration time | |
| revoked | BOOLEAN | FALSE | Revocation status | |
| revoked_at | TIMESTAMP WITH TIME ZONE | Revocation time | ||
| revoked_reason | TEXT | Revocation reason | ||
| superseded_at | TIMESTAMP WITH TIME ZONE | When token was replaced by a new token (migration 101) | ||
| superseded_by | UUID | FK → tokens(id) | Reference to the replacement token (migration 101) |
Sliding Window Session Behavior: - Tokens are refreshed on user activity after ⅓ of the session time has passed - When refreshed, the old token is marked as superseded (not immediately invalidated) - Superseded tokens remain valid for a 5-minute grace period to handle concurrent requests - Token validity check: superseded_at IS NULL OR superseded_at > NOW() - INTERVAL '5 minutes'
Relationships: - Referenced by active_sessions(token_id) with CASCADE delete (migration 65) - Deleting a token automatically removes all associated sessions - Self-referential via superseded_by to track token refresh chain
Indexes: - idx_tokens_token (token) - idx_tokens_user_id (user_id) - idx_tokens_revoked (revoked) - idx_tokens_superseded_at (superseded_at) - For efficient grace period queries (migration 101)
auth_settings¶
Stores global authentication and security settings.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Settings ID |
| min_password_length | INT | 15 | Minimum password length | |
| require_uppercase | BOOLEAN | TRUE | Require uppercase letters | |
| require_lowercase | BOOLEAN | TRUE | Require lowercase letters | |
| require_numbers | BOOLEAN | TRUE | Require numbers | |
| require_special_chars | BOOLEAN | TRUE | Require special characters | |
| max_failed_attempts | INT | 5 | Max failed login attempts | |
| lockout_duration_minutes | INT | 60 | Account lockout duration | |
| require_mfa | BOOLEAN | FALSE | Require MFA for all users | |
| jwt_expiry_minutes | INT | 60 | JWT token expiry | |
| display_timezone | VARCHAR(50) | 'UTC' | Display timezone | |
| notification_aggregation_minutes | INT | 60 | Notification aggregation period | |
| allowed_mfa_methods | JSONB | '["email", "authenticator"]' | Allowed MFA methods | |
| email_code_validity_minutes | INT | 5 | Email code validity | |
| backup_codes_count | INT | 8 | Number of backup codes | |
| mfa_code_cooldown_minutes | INT | 1 | MFA code cooldown | |
| mfa_code_expiry_minutes | INT | 5 | MFA code expiry | |
| mfa_max_attempts | INT | 3 | Max MFA attempts | |
| webauthn_rp_id | VARCHAR(255) | WebAuthn Relying Party ID (domain) | ||
| webauthn_rp_origins | TEXT[] | '{}' | Allowed WebAuthn origins | |
| webauthn_rp_display_name | VARCHAR(255) | 'KrakenHashes' | Display name for passkey prompts |
WebAuthn Configuration Notes: - webauthn_rp_id must be a domain name (not IP address per WebAuthn spec) - webauthn_rp_origins should include all URLs users access the system from - Changing webauthn_rp_id after passkeys are registered will invalidate all existing passkeys
login_attempts¶
Tracks login attempts for security monitoring.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Attempt ID |
| user_id | UUID | FK → users(id) | User reference (nullable) | |
| username | VARCHAR(255) | Attempted username | ||
| ip_address | INET | NOT NULL | Client IP address | |
| user_agent | TEXT | Client user agent | ||
| success | BOOLEAN | NOT NULL | Success status | |
| failure_reason | TEXT | Failure reason | ||
| attempted_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Attempt time | |
| notified | BOOLEAN | FALSE | Notification sent |
Indexes: - idx_login_attempts_user_id (user_id) - idx_login_attempts_attempted_at (attempted_at) - idx_login_attempts_notified (notified)
active_sessions¶
Tracks active user sessions linked to JWT tokens (updated in migration 65).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Session ID |
| user_id | UUID | FK → users(id) | User reference | |
| ip_address | INET | NOT NULL | Session IP address | |
| user_agent | TEXT | Client user agent | ||
| created_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Session start | |
| last_active_at | TIMESTAMP WITH TIME ZONE | CURRENT_TIMESTAMP | Last activity | |
| token_id | UUID | FK → tokens(id) ON DELETE CASCADE | Linked JWT token (migration 65) |
Security Features: - Session-Token Binding: Each session is linked to its authentication token via foreign key - CASCADE Delete: Deleting the token automatically removes the session - True Logout: Terminating a session deletes the token, immediately invalidating authentication - No Orphaned Sessions: Sessions cannot exist without valid tokens after migration 65
Indexes: - idx_active_sessions_user_id (user_id) - idx_active_sessions_last_active (last_active_at) - idx_active_sessions_token_id (token_id)
pending_mfa_setup¶
Tracks pending MFA setup processes (added in migration 8).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| user_id | UUID | PRIMARY KEY, FK → users(id) | User reference | |
| method | VARCHAR(20) | NOT NULL, CHECK | Method: email, authenticator | |
| secret | TEXT | MFA secret | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
Indexes: - idx_pending_mfa_created_at (created_at)
email_mfa_codes¶
Stores temporary MFA codes sent via email (added in migration 8).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| user_id | UUID | PRIMARY KEY, FK → users(id) | User reference | |
| code | VARCHAR(6) | NOT NULL | MFA code | |
| attempts | INT | NOT NULL | 0 | Attempt count |
| expires_at | TIMESTAMP WITH TIME ZONE | NOT NULL | Expiration time | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
Indexes: - idx_email_mfa_expires_at (expires_at)
mfa_methods¶
Stores user MFA method configurations (added in migration 8).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Method ID |
| user_id | UUID | NOT NULL, FK → users(id) | User reference | |
| method | VARCHAR(20) | NOT NULL, CHECK | Method: email, authenticator | |
| is_primary | BOOLEAN | FALSE | Primary method flag | |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
| last_used_at | TIMESTAMP WITH TIME ZONE | Last usage time | ||
| metadata | JSONB | Method-specific data |
Unique Constraint: (user_id, method)
Indexes: - idx_mfa_methods_user (user_id) - idx_mfa_methods_primary (user_id, is_primary)
mfa_backup_codes¶
Stores MFA backup codes (added in migration 8).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Code ID |
| user_id | UUID | NOT NULL, FK → users(id) | User reference | |
| code_hash | VARCHAR(255) | NOT NULL | Hashed backup code | |
| used_at | TIMESTAMP WITH TIME ZONE | Usage timestamp | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Creation time |
Indexes: - idx_mfa_backup_codes_user (user_id) - idx_mfa_backup_codes_unused (user_id, used_at) WHERE used_at IS NULL
mfa_sessions¶
Tracks MFA verification sessions during login (added in migration 11).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Session ID |
| user_id | UUID | NOT NULL, FK → users(id) | User reference | |
| session_token | TEXT | NOT NULL | Session token | |
| expires_at | TIMESTAMP WITH TIME ZONE | NOT NULL | Expiration time | |
| attempts | INT | NOT NULL | 0 | Failed attempts |
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | NOW() | Creation time |
Indexes: - idx_mfa_sessions_user_id (user_id) - idx_mfa_sessions_session_token (session_token) - idx_mfa_sessions_expires_at (expires_at)
Triggers: - enforce_mfa_max_attempts_trigger: Enforces max attempts limit - cleanup_expired_mfa_sessions_trigger: Cleans up expired sessions
security_events¶
Logs security-related events (added in migration 8).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Event ID |
| user_id | UUID | FK → users(id) | User reference | |
| event_type | VARCHAR(50) | NOT NULL | Event type | |
| ip_address | INET | Client IP address | ||
| user_agent | TEXT | Client user agent | ||
| details | JSONB | Event details | ||
| created_at | TIMESTAMP WITH TIME ZONE | NOT NULL | CURRENT_TIMESTAMP | Event time |
Indexes: - idx_security_events_user (user_id) - idx_security_events_type (event_type) - idx_security_events_created (created_at)
Potfile Initialization Sequence¶
The potfile system initializes in stages during server startup:
1. On Server Startup¶
- Creates
/data/krakenhashes/wordlists/custom/potfile.txtif missing - Creates potfile wordlist entry in database with
is_potfile = true - Attempts to create "Potfile Run" preset job
2. Binary Dependency¶
- Preset jobs use a
binary_versionpattern (e.g., "default", "7.x") - The pattern must resolve to at least one active binary
- If no binaries exist, preset job creation is deferred
- A background monitor runs every 5 seconds checking for binary availability
- Monitor stops once preset job is successfully created
3. Completion¶
- Once a binary is uploaded and verified, the preset job is created
- System settings are updated with both
potfile_wordlist_idandpotfile_preset_job_id - The potfile system is fully operational
Related Tables¶
- wordlists: Contains potfile entry with
is_potfile = true - preset_jobs: Contains "Potfile Run" job (once binary available)
- potfile_staging: Temporary storage for passwords before batch processing
- system_settings: Stores
potfile_wordlist_idandpotfile_preset_job_id
Notifications & Audit¶
notifications¶
Stores all notification history for user display and audit trail. Tracks delivery status across multiple channels (in-app, email, webhook).
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique notification identifier |
| user_id | UUID | NOT NULL, FK | User receiving the notification | |
| notification_type | notification_type | NOT NULL | Type of notification (enum) | |
| title | VARCHAR(255) | NOT NULL | Notification title | |
| message | TEXT | NOT NULL | Full notification message | |
| data | JSONB | '{}' | Additional structured data | |
| in_app_read | BOOLEAN | NOT NULL | FALSE | Whether read in app |
| in_app_read_at | TIMESTAMPTZ | When marked as read | ||
| email_sent | BOOLEAN | NOT NULL | FALSE | Whether email was sent |
| email_sent_at | TIMESTAMPTZ | When email was sent | ||
| email_error | TEXT | Email delivery error if any | ||
| webhook_sent | BOOLEAN | NOT NULL | FALSE | Whether webhook was sent |
| webhook_sent_at | TIMESTAMPTZ | When webhook was sent | ||
| webhook_error | TEXT | Webhook delivery error if any | ||
| source_type | VARCHAR(50) | Source entity type (job, agent, etc.) | ||
| source_id | VARCHAR(255) | Source entity identifier | ||
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | Creation timestamp |
Indexes: - idx_notifications_user_id (user_id) - idx_notifications_user_unread (user_id, in_app_read) WHERE in_app_read = FALSE - idx_notifications_created_at (created_at DESC) - idx_notifications_type (notification_type) - idx_notifications_source (source_type, source_id) WHERE source_type IS NOT NULL
Foreign Keys: - user_id → users(id) ON DELETE CASCADE
user_notification_preferences¶
Per-user, per-notification-type channel preferences. Each user can enable/disable each delivery channel for each notification type independently.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique preference identifier |
| user_id | UUID | NOT NULL, FK | User owning the preference | |
| notification_type | notification_type | NOT NULL | Type of notification | |
| in_app_enabled | BOOLEAN | NOT NULL | TRUE | Enable in-app notifications |
| email_enabled | BOOLEAN | NOT NULL | FALSE | Enable email notifications |
| webhook_enabled | BOOLEAN | NOT NULL | FALSE | Enable webhook notifications |
| settings | JSONB | '{}' | Type-specific settings (e.g., task report mode) | |
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | Creation timestamp |
| updated_at | TIMESTAMPTZ | NOT NULL | NOW() | Last update timestamp |
Indexes: - idx_user_notification_prefs_user (user_id)
Constraints: - user_notification_prefs_unique: UNIQUE (user_id, notification_type)
Triggers: - update_user_notification_preferences_updated_at: Updates updated_at on modification
user_webhooks¶
User-configured webhook endpoints for receiving notifications. Supports filtering by notification type, custom headers, retry configuration, and delivery statistics.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique webhook identifier |
| user_id | UUID | NOT NULL, FK | User owning the webhook | |
| name | VARCHAR(100) | NOT NULL | User-friendly webhook name | |
| url | TEXT | NOT NULL | Webhook endpoint URL | |
| secret | VARCHAR(255) | HMAC-SHA256 signing secret | ||
| is_active | BOOLEAN | NOT NULL | TRUE | Whether webhook is enabled |
| notification_types | notification_type[] | Filter to specific types (NULL = all) | ||
| custom_headers | JSONB | '{}' | Additional HTTP headers | |
| retry_count | INT | NOT NULL | 3 | Max retry attempts (0-10) |
| timeout_seconds | INT | NOT NULL | 30 | Request timeout (1-60) |
| last_triggered_at | TIMESTAMPTZ | Last trigger timestamp | ||
| last_success_at | TIMESTAMPTZ | Last successful delivery | ||
| last_error | TEXT | Most recent error message | ||
| total_sent | INT | NOT NULL | 0 | Successful delivery count |
| total_failed | INT | NOT NULL | 0 | Failed delivery count |
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | Creation timestamp |
| updated_at | TIMESTAMPTZ | NOT NULL | NOW() | Last update timestamp |
Indexes: - idx_user_webhooks_user_active (user_id) WHERE is_active = TRUE
Constraints: - user_webhooks_unique_name: UNIQUE (user_id, name)
Triggers: - update_user_webhooks_updated_at: Updates updated_at on modification
agent_offline_buffer¶
Tracks agents pending offline notifications with a configurable buffer period. Prevents notification spam during brief network interruptions.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique buffer entry identifier |
| agent_id | INT | NOT NULL, FK | Agent that disconnected | |
| disconnected_at | TIMESTAMPTZ | NOT NULL | NOW() | When agent disconnected |
| notification_due_at | TIMESTAMPTZ | NOT NULL | When notification should be sent | |
| notification_sent | BOOLEAN | NOT NULL | FALSE | Whether notification was sent |
| notification_sent_at | TIMESTAMPTZ | When notification was sent | ||
| reconnected | BOOLEAN | NOT NULL | FALSE | Whether agent reconnected |
| reconnected_at | TIMESTAMPTZ | When agent reconnected | ||
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | Creation timestamp |
Indexes: - idx_agent_offline_buffer_pending (notification_due_at) WHERE notification_sent = FALSE AND reconnected = FALSE - idx_agent_offline_buffer_agent (agent_id)
Foreign Keys: - agent_id → agents(id) ON DELETE CASCADE
audit_log¶
Admin-visible audit log for security and critical events across all users. Stores user context separately to preserve visibility when users are deleted.
| Column | Type | Constraints | Default | Description |
|---|---|---|---|---|
| id | UUID | PRIMARY KEY | gen_random_uuid() | Unique audit entry identifier |
| event_type | notification_type | NOT NULL | Type of event (enum) | |
| severity | VARCHAR(20) | NOT NULL | 'info' | Severity: info, warning, critical |
| user_id | UUID | FK | User the event happened to | |
| username | VARCHAR(255) | Cached username (preserved on delete) | ||
| user_email | VARCHAR(255) | Cached email (preserved on delete) | ||
| title | VARCHAR(255) | NOT NULL | Event title | |
| message | TEXT | NOT NULL | Event description | |
| data | JSONB | '{}' | Additional structured data | |
| source_type | VARCHAR(50) | Source entity type | ||
| source_id | VARCHAR(255) | Source entity identifier | ||
| ip_address | INET | Request source IP | ||
| user_agent | TEXT | Request user agent | ||
| created_at | TIMESTAMPTZ | NOT NULL | NOW() | Event timestamp |
Indexes: - idx_audit_log_created_at (created_at DESC) - idx_audit_log_event_type (event_type) - idx_audit_log_user_id (user_id) WHERE user_id IS NOT NULL - idx_audit_log_severity (severity) - idx_audit_log_type_date (event_type, created_at DESC)
Foreign Keys: - user_id → users(id) ON DELETE SET NULL
System Settings for Notifications¶
The following system settings control notification behavior:
| Key | Type | Default | Description |
|---|---|---|---|
| global_webhook_url | string | NULL | System-wide webhook URL |
| global_webhook_secret | string | NULL | Signing secret for system webhook |
| global_webhook_enabled | boolean | false | Enable system-wide webhook |
| global_webhook_custom_headers | string | '{}' | Custom headers as JSON |
| agent_offline_buffer_minutes | integer | 10 | Minutes before offline notification |
Migration History¶
The database schema has evolved through 115 migrations:
- 000001: Initial schema - users, teams, user_teams
- 000002: Add auth_tokens table
- 000003: Create agents system
- 000004: Create voucher system
- 000005: Add email system
- 000006: Add email templates (enhancement)
- 000007: Auth security infrastructure
- 000008: Add MFA tables
- 000009: Update auth settings
- 000010: Add preferred MFA method
- 000011: Add MFA session
- 000012: Add binary versions
- 000013: Add wordlists
- 000014: Add rules
- 000015: Add hashlist tables
- 000016: Add hashcat hash types
- 000017: Add client settings
- 000018: Add job workflows
- 000019: Add system settings
- 000020: Add job execution (fixed)
- 000021: Add job execution settings
- 000022: Enhance job tasks and system settings
- 000023: Add max_agents column
- 000024: Add interrupted status
- 000025: Add job_tasks created_at
- 000026: Add job_tasks updated_at
- 000027: Fix hashes trigger
- 000028: Fix cracked counts
- 000029: Add agent devices
- 000030: Add agent owner and extra parameters
- 000031: Add agent is_enabled
- 000032: Add preset job keyspace and max_agents
- 000033: Add job created_by
- 000034: Add enhanced chunking support
- 000035: Make agent_id nullable in job_tasks
- 000036: Add progress tracking
- 000037: Add consecutive failures tracking
- 000038: Update progress precision
- 000039: Add speedtest timeout setting
- 000040: Add dispatched_keyspace to job_executions
- 000041: Add device tracking to performance_metrics
- 000042: Add agent scheduling
- 000043: Set owner_id for existing agents
- 000044: Add chunk_number to job_tasks
- 000045: Fix total_keyspace for rule split jobs
- 000046: Add task heartbeat timeout setting
- 000047: Add effective_keyspace to job_tasks
- 000048: Add potfile support
- 000049: Make job executions self-contained
- 000050: Add reconnect_pending status
- 000051: Add monitoring settings
- 000052: Remove is_small_job column
- 000053: Add binary default system
- 000054: Add auth token last activity tracking
- 000055: Add job notification tracking
- 000056: Add reconnect grace period setting
- 000057: Add agent download settings
- 000058: Add agent sync status
- 000059: Add average speed to tasks
- 000060: Add missing hash types
- 000061: Add hashlist potfile exclusion
- 000062: Add client potfile exclusion
- 000063: Add accurate keyspace tracking
- 000064: Add chunk_actual_keyspace tracking
- 000065: Link sessions to tokens with CASCADE delete for session security
- 000066-000081: [Various enhancements and bug fixes]
- 000082: Add agent_overflow_allocation_mode system setting
- Controls overflow agent distribution (FIFO vs round-robin)
- Applies to same-priority jobs exceeding max_agents limits
- Default value: 'fifo' (oldest job gets all overflow agents)
- Alternative: 'round_robin' (distribute evenly across jobs)
- 000083: Add benchmark_requests table for parallel benchmark execution
- Enables polling-based coordination of async WebSocket benchmarks
- Tracks both forced benchmarks (accurate keyspace) and agent speed benchmarks
- Supports 96% performance improvement (15 agents: 450s → 12s)
- Status tracking: pending, completed, failed
- Automatic cleanup after each scheduling cycle 84-87. 000084-000087: [Various enhancements]
- 000088: Add job_increment_layers table for increment mode support
- Stores sub-layers for increment mode jobs
- Each layer represents one mask length in the increment sequence
- Enables parallel processing of different mask lengths
- Tracks per-layer progress and status
- 000089: Add increment_layer_id to job_tasks
- Links tasks to their parent increment layer
- NULL for non-increment mode jobs
- Enables layer-specific task tracking
- 000090: Add preset_increment_layers table
- Pre-calculated increment layers for preset jobs
- Layers are copied to job_increment_layers when job is created from preset
- Ensures consistent keyspace calculations across jobs from same preset
- 000091: [Reserved]
- 000092: Add WebAuthn/Passkey support
- Creates
user_passkeystable for storing passkey credentials - Creates
pending_passkey_registrationtable for registration challenges - Creates
pending_passkey_authenticationtable for MFA authentication challenges - Adds WebAuthn settings to
auth_settings(rp_id, rp_origins, rp_display_name) - Adds cleanup trigger for expired challenges
- 000093: Add passkey to MFA type constraints
- Updates
users.mfa_typeCHECK constraint to allow 'passkey' - Updates
users.preferred_mfa_methodCHECK constraint to allow 'passkey' - 000094: Add passkey backup flags
- Adds
backup_eligiblecolumn touser_passkeys - Adds
backup_statecolumn touser_passkeys - Required for WebAuthn credential validation with synced passkeys
- 000095: [Reserved/Internal]
- 000096: Add original_hash unique index
- Creates
idx_hashes_original_hash_uniqueunique index onhashes.original_hash - Enables fast deduplication during bulk import using
ON CONFLICT DO NOTHING - Uses
CONCURRENTLYto avoid locking during creation - 000097: Add hashlist bulk batch size setting
- Adds
hashlist_bulk_batch_sizesystem setting (default: 100000) - Controls batch size during hashlist upload processing
- Higher values improve performance for large hashlists at cost of memory
- 000098: Add cracked_by_task_id to hashes
- Adds
hashes.cracked_by_task_idcolumn referencingjob_tasks(id) - Enables granular tracking of which task cracked each hash
- Used for retransmit deduplication in the outfile acknowledgment protocol
- ON DELETE SET NULL to preserve hashes when tasks are deleted
- 000099: Add task retransmit tracking
- Adds
job_tasks.retransmit_countto track retransmission attempts - Adds
job_tasks.last_retransmit_atfor timing information - Supports the outfile acknowledgment protocol for crack recovery
- 000100: Add cracking_completed_at timestamps
- Adds
job_tasks.cracking_completed_at- when hashcat finished (enters processing state) - Adds
job_executions.cracking_completed_at- when all tasks finished hashcat - Distinguishes between hashcat completion and full processing completion
- Enables tracking of hashcat work time vs data transmission time
- 000101: Add token sliding window session support
- Adds
tokens.superseded_atcolumn for tracking when a token was replaced - Adds
tokens.superseded_bycolumn referencing the replacement token - Creates
idx_tokens_superseded_atindex for efficient grace period queries - Enables sliding window sessions that extend on user activity
- Old tokens remain valid for 5-minute grace period after refresh
- 000102: Add preset job effective keyspace
- Adds
preset_jobs.effective_keyspacefor actual keyspace from --total-candidates - Adds
preset_jobs.is_accurate_keyspaceboolean to track keyspace accuracy - Adds
preset_jobs.use_rule_splittingboolean for pre-computed splitting decisions - Enables accurate keyspace calculation accounting for rule multipliers
- 000103: Add preset job multiplication factor
- Adds
preset_jobs.multiplication_factorcolumn (default: 1) - Stores rule multiplier (effective_keyspace / keyspace) for rule splitting
- Enables job creation to be a pure copy when is_accurate_keyspace = true
- 000104: Add association attack support
- Adds
hashlists.original_file_pathfor association attack file reference - Adds
hashlists.has_mixed_work_factorswarning flag for different work factors - Creates
association_wordliststable linked to hashlists - Adds
job_executions.association_wordlist_idreference - Enables hashcat -a 9 association attack mode
- 000105: Add SSO support (LDAP, SAML, OAuth/OIDC)
- Adds SSO toggles to
auth_settings(local_auth_enabled, ldap/saml/oauth_auth_enabled, auto_create/enable_users) - Adds per-user auth overrides to
users(local_auth_override, sso_auth_override, auth_override_notes) - Creates
sso_providersbase table for all SSO providers - Creates
ldap_configstable with server URL, bind DN, search filters, TLS settings - Creates
saml_configstable with SP/IdP entity IDs, certificates, signing options - Creates
oauth_configstable with client ID/secret, discovery URL, scopes - Creates
user_identitiestable linking external identities to local accounts - Creates
pending_oauth_authenticationandpending_saml_authenticationfor redirect flow state - Extends
login_attemptswith provider_id and provider_type columns - 000106: Add user soft delete support
- Adds
users.deleted_atcolumn for soft delete timestamps - Creates partial index
idx_users_deleted_atWHERE deleted_at IS NULL - Enables soft delete of user accounts while preserving historical data
- User listings filter out soft-deleted users automatically
- 000107: Add salted hash type classification
- Adds
hash_types.is_saltedBOOLEAN column (default: false) - Auto-classifies 40+ known salted hash types via pattern matching
- Includes: md5crypt, bcrypt, scrypt, NetNTLM, Kerberos, WPA, Argon2, PBKDF2
- Creates index on
is_saltedfor faster lookups - Enables salt-aware chunk calculations and benchmark caching
- 000108: Fix NULL completed_at values
- Backfills
completed_atfor terminal-status jobs with NULL values - Sets
completed_at = COALESCE(updated_at, created_at)for affected jobs - Fixes job list ordering on dashboard and /jobs page
- Ensures proper sorting by completion time
- 000109: Add benchmark salt count
- Adds
agent_benchmarks.salt_countINT column for salt-aware caching - Drops old unique constraint:
(agent_id, attack_mode, hash_type) - Creates new unique constraint:
(agent_id, attack_mode, hash_type, salt_count) - Uses
IS NOT DISTINCT FROMfor NULL-safe salt count comparison - Enables per-salt-count benchmark caching for accurate speed estimation
- 000110: Convert binary versions to patterns
- Converts binary version management to pattern-based system
- Enables flexible version matching for hashcat binaries
- 000111: Drop total_keyspace column
- Removes deprecated
total_keyspacecolumn from job_executions - Replaced by
base_keyspaceandeffective_keyspacefor accurate tracking - 000112: Enhanced notification system
- Creates
notification_typeenum with 11 notification types - Creates
notificationstable for notification history and delivery tracking - Creates
user_notification_preferencesfor per-user, per-type channel settings - Creates
user_webhooksfor user-configurable webhook endpoints - Creates
agent_offline_bufferfor buffered offline detection - Adds system settings for global webhook and agent offline buffer
- 000113: Notification email templates enum
- Extends
email_template_typeenum with 10 notification template types - Adds: security_password_changed, security_mfa_disabled, security_suspicious_login
- Adds: job_started, job_failed, first_crack, task_completed
- Adds: agent_offline, agent_error, webhook_failure
- 000114: Notification email template data
- Inserts 10 default HTML/text email templates for notification types
- Templates include KrakenHashes branding and template variable support
- Color-coded templates (success: green, error: red, warning: yellow)
- 000115: Admin audit log
- Creates
audit_logtable for admin-visible security events - Stores user context (username, email) separately for deleted user visibility
- Tracks severity levels (info, warning, critical)
- Includes request context (IP address, user agent)
- Indexed for efficient admin queries by date, type, severity
Enums and Custom Types¶
email_provider_type¶
- mailgun
- sendgrid
- mailchimp
- gmail
email_template_type¶
- security_event
- job_completion
- admin_error
- mfa_code
- security_password_changed (added in migration 113)
- security_mfa_disabled (added in migration 113)
- security_suspicious_login (added in migration 113)
- job_started (added in migration 113)
- job_failed (added in migration 113)
- first_crack (added in migration 113)
- task_completed (added in migration 113)
- agent_offline (added in migration 113)
- agent_error (added in migration 113)
- webhook_failure (added in migration 113)
notification_type (added in migration 112)¶
- job_started
- job_completed
- job_failed
- first_crack
- task_completed_with_cracks
- agent_offline
- agent_error
- security_suspicious_login
- security_mfa_disabled
- security_password_changed
- webhook_failure
binary_type¶
- hashcat
- john
compression_type¶
- 7z
- zip
- tar.gz
- tar.xz
wordlist_type¶
- general
- specialized
- targeted
- custom
wordlist_format¶
- plaintext
- compressed
rule_type¶
- hashcat
- john
Key Relationships¶
- User System: users ↔ teams (many-to-many via user_teams)
- Agent System: agents → users (created_by), agents ↔ teams (many-to-many via agent_teams)
- Hash Management: hashlists → users, hashlists → clients, hashlists ↔ hashes (many-to-many via hashlist_hashes)
- Job System: preset_jobs → binary_versions, job_executions → preset_jobs + hashlists, job_tasks → job_executions + agents
- Resource Management: wordlists/rules → users (created_by), rules ↔ wordlists (compatibility)
- Authentication: Various MFA and security tables → users
- Session Security: tokens (parent) → active_sessions (child) with CASCADE delete - ensures session termination revokes authentication
- Notification System: notifications → users (CASCADE), user_notification_preferences → users (CASCADE), user_webhooks → users (CASCADE)
- Audit System: audit_log → users (SET NULL) - preserves logs when users are deleted
- Agent Monitoring: agent_offline_buffer → agents (CASCADE) - tracks disconnect buffer periods
Data Lifecycle & Security¶
Data Retention System¶
The database implements a comprehensive data retention system with automatic purging:
- Retention Policy Hierarchy
- System default:
client_settings.default_data_retention_months(when client_id is NULL) - Client-specific:
clients.data_retention_monthsoverrides system default -
Special values: NULL = use system default, 0 = keep forever
-
Automatic Purge Process
- Runs daily at midnight and on backend startup
- Processes hashlists older than retention period based on
created_at - Executes within database transactions for atomicity
-
Logs all deletions for audit compliance
-
Secure Deletion Process
- Database: Transactional deletion with CASCADE to dependent tables
- Filesystem: Files overwritten with random data before removal
- PostgreSQL: VACUUM ANALYZE on affected tables to prevent WAL recovery
-
Orphan Cleanup: Automatic removal of hashes not linked to any hashlist
-
Affected Tables During Purge
hashlists- Primary deletion targethashlist_hashes- Junction table entries removedhashes- Orphaned entries deletedagent_hashlists- CASCADE deletionjob_executions- CASCADE deletionjob_tasks- CASCADE deletion via job_executions
Security Features¶
- Deletion Security
- Files are securely overwritten with random data to prevent recovery
- VACUUM ANALYZE prevents recovery from PostgreSQL dead tuples
-
Audit trail maintained for compliance verification
-
CASCADE Deletion Paths
-
Agent-Side Cleanup
- Agents automatically clean files older than 3 days
- Prevents storage accumulation on compute nodes
- Preserves base resources (binaries, wordlists, rules)
Important Notes¶
- UUID Usage: Most primary keys use UUID except for legacy/performance-critical tables (agents, hashlists use SERIAL/BIGSERIAL)
- Soft Deletes: Implemented for users table via
deleted_atcolumn (migration 106). Other tables use CASCADE deletes for referential integrity. - Audit Trails: Separate audit tables for binary_versions, wordlists, and rules
- Time Zones: All timestamps stored as TIMESTAMP WITH TIME ZONE
- JSON Storage: Heavy use of JSONB for flexible metadata storage
- System User: Special user with UUID 00000000-0000-0000-0000-000000000000 for system operations
- Data Retention: Automatic purging with secure deletion and WAL protection