Skip to main content

Data Model

Kyqu uses PostgreSQL for all persistence. The schema is auto-migrated on every server start.

Entity Relationship

admin_users ──── admin_sessions
│ admin_backup_codes
│ admin_ip_allowlist
│ admin_impersonation_sessions

│ (via workspace_members)

workspaces ──── projects ──── project_auth_settings
│ project_api_keys
│ project_onboarding
│ project_jwt_keys
│ project_oauth_providers
│ project_oauth_states

├── project_users ──── project_sessions
│ │ project_auth_tokens
│ │ project_user_backup_codes
│ │ project_user_oauth_links
│ │ project_user_roles ──── project_roles
│ │ project_passkeys
│ │ project_webauthn_challenges

├── project_user_fields
├── project_webhooks ──── project_webhook_deliveries
├── project_email_templates
├── project_email_outbox
└── project_logs

Tables

admin_users

ColumnTypeDescription
idtext PKUUID
emailtext UNIQUEAdmin email
normalized_emailtext UNIQUELowercase trimmed email
nametextDisplay name
password_hashtextscrypt hash (scrypt:salt:hash)
is_superadminbooleanSuperadmin privileges
created_attimestamptzCreation timestamp
updated_attimestamptzLast update timestamp

admin_sessions

ColumnTypeDescription
idtext PKUUID
admin_user_idFK → admin_usersOwner
token_hashtext UNIQUESHA-256 of session token
created_attimestamptzCreation timestamp
expires_attimestamptzExpiry timestamp
revoked_attimestamptz?Revocation timestamp

projects

ColumnTypeDescription
idtext PKUUID
workspace_idFK → workspacesParent workspace
nametextProject name
slugtextURL-safe slug
product_typetextweb, app, extension, api, other
domaintextPrimary domain
statustextactive, suspended, archived
created_attimestamptzCreation timestamp
updated_attimestamptzLast update timestamp
UNIQUE(workspace_id, slug)Unique slug per workspace

project_auth_settings

ColumnTypeDefaultDescription
project_idFK → projects PKParent project
auth_enabledbooleantrueMaster auth toggle
email_password_enabledbooleantrueEmail/password auth
email_verification_requiredbooleanfalseRequire email verification
password_reset_enabledbooleantruePassword reset flow
magic_link_enabledbooleanfalseMagic link auth
two_factor_enabledbooleanfalseTOTP 2FA
allowed_originsjsonb[]CORS allowed origins
blocklisted_domainsjsonb[]Blocked email domains
whitelisted_domainsjsonb[]Allowed email domains
password_min_lengthinteger10Min password length
lockout_enabledbooleantrueAccount lockout
lockout_max_attemptsinteger5Failed attempts before lock
lockout_window_minutesinteger15Lockout window
login_urltext''Post-login redirect URL
email_verified_urltext''Post-verification redirect
password_reset_urltext''Password reset form URL

project_users

ColumnTypeDescription
idtext PKUUID
project_idFK → projectsParent project
emailtextUser email
normalized_emailtextLowercase trimmed email
nametextDisplay name
password_hashtextscrypt hash
statustextactive, suspended
email_verified_attimestamptz?Email verification timestamp
password_reset_requiredbooleanForce password reset
failed_login_countintegerConsecutive failed logins
locked_untiltimestamptz?Lockout expiry
totp_secrettext?TOTP secret (Base32)
totp_enabled_attimestamptz?TOTP enrollment timestamp
metadatajsonbCustom user fields data
UNIQUE(project_id, normalized_email)One account per project

project_sessions

ColumnTypeDescription
idtext PKUUID
project_idFK → projectsParent project
project_user_idFK → project_usersOwner
token_hashtext UNIQUESHA-256 of bearer token
ip_addresstext?Client IP at creation
user_agenttext?User agent at creation
created_attimestamptzCreation timestamp
expires_attimestamptzExpiry timestamp
revoked_attimestamptz?Revocation timestamp

Other Tables

  • workspaces — Top-level organizational unit
  • workspace_members — Links admins to workspaces
  • project_api_keys — Public/secret key pairs for project auth
  • project_auth_tokens — One-time tokens (verification, password reset, magic link)
  • project_roles / project_user_roles — Role-based access (extensible)
  • project_user_fields — Custom field definitions per project
  • project_user_backup_codes — TOTP backup codes (hashed)
  • project_webhooks — Webhook endpoints per project
  • project_webhook_deliveries — Webhook delivery log
  • project_email_templates — Custom email templates per project
  • project_email_outbox — Sent/stored email records
  • project_logs — Audit event log
  • project_onboarding — Per-project onboarding wizard state
  • api_rate_limits — PostgreSQL-backed rate-limit state
  • admin_backup_codes — Admin TOTP backup codes (hashed)
  • admin_ip_allowlist — IP-based admin access restrictions
  • admin_impersonation_sessions — Admin-to-user impersonation tracking
  • project_oauth_providers — OAuth2 provider configs (Google, GitHub)
  • project_oauth_states — OAuth2 state nonces for PKCE
  • project_user_oauth_links — OAuth identity links per project user
  • project_passkeys — WebAuthn/FIDO2 passkey credentials
  • project_webauthn_challenges — WebAuthn challenge nonces (5-min TTL)
  • project_jwt_keys — Per-project RSA-2048 signing keys (AES-256 encrypted)
  • schema_migrations — Migration version tracking

Migration Strategy

Migrations are idempotent and run on every server start using CREATE TABLE IF NOT EXISTS and ALTER TABLE ... ADD COLUMN IF NOT EXISTS — no manual migration scripts needed.