Documentation
¶
Index ¶
- Constants
- Variables
- func GetProviderDefaultScopes(name string) []string
- func GetProviderDisplayName(name string) string
- func IsValidOrgInvitationStatus(status string) bool
- func IsValidOrgMemberRole(role string) bool
- func IsValidOrgMemberStatus(status string) bool
- func IsValidProvider(name string) bool
- func ValidOrgInvitationStatuses() []string
- func ValidOrgMemberRoles() []string
- func ValidOrgMemberStatuses() []string
- type APIKey
- type APIKeyRole
- type Account
- type AccountLockout
- type App
- type AuditEvent
- type AuditableModel
- type AuthorizationCode
- type BackupCode
- type Delivery
- type Device
- type EmailOTP
- type Environment
- type EnvironmentPromotion
- type Event
- type FailedLoginAttempt
- type FormField
- type FormSchema
- type FormSubmission
- type IDModel
- type IdentityVerification
- type IdentityVerificationDocument
- type IdentityVerificationSession
- type ImpersonationAuditEvent
- type ImpersonationSession
- type Invitation
- type InvitationStatus
- type JSONMap
- type JWTKey
- type MFAAttempt
- type MFABypass
- type MFAChallenge
- type MFAFactor
- type MFAPolicy
- type MFARiskAssessment
- type MFASession
- type MFATrustedDevice
- type MagicLink
- type Member
- type MemberRole
- type MemberStatus
- type Notification
- type NotificationAnalytics
- type NotificationEvent
- type NotificationProvider
- type NotificationQueue
- type NotificationQueueStats
- type NotificationQueueStatus
- type NotificationTemplate
- type NotificationTemplateVersion
- type NotificationTest
- type NotificationTestStatus
- type NotificationTestType
- type OAuthClient
- type OAuthConsent
- type OAuthToken
- type OTPCode
- type Organization
- type OrganizationInvitation
- type OrganizationMember
- type OrganizationTeam
- type OrganizationTeamMember
- type Passkey
- type PasswordHistory
- type Permission
- type PhoneVerification
- type Policy
- type Role
- type RolePermission
- type SSOProvider
- type SecurityEvent
- type Session
- type SocialAccount
- type SocialProviderConfig
- type StringArray
- type Team
- type TeamMember
- type TrustedDevice
- type TwoFASecret
- type UsageEvent
- type User
- type UserBan
- type UserRole
- type UserVerificationStatus
- type Verification
- type Webhook
Constants ¶
const ( EnvironmentTypeDevelopment = "development" EnvironmentTypeProduction = "production" EnvironmentTypeStaging = "staging" EnvironmentTypePreview = "preview" EnvironmentTypeTest = "test" )
Environment types
const ( EnvironmentStatusActive = "active" EnvironmentStatusInactive = "inactive" )
Environment status
const ( PromotionStatusPending = "pending" PromotionStatusInProgress = "in_progress" PromotionStatusCompleted = "completed" PromotionStatusFailed = "failed" )
Promotion status
const ( OrgMemberRoleOwner = "owner" OrgMemberRoleAdmin = "admin" OrgMemberRoleMember = "member" )
Organization Member Roles
const ( OrgMemberStatusActive = "active" OrgMemberStatusSuspended = "suspended" OrgMemberStatusPending = "pending" )
Organization Member Statuses
const ( OrgInvitationStatusPending = "pending" OrgInvitationStatusAccepted = "accepted" OrgInvitationStatusExpired = "expired" OrgInvitationStatusCancelled = "cancelled" OrgInvitationStatusDeclined = "declined" )
Organization Invitation Statuses
Variables ¶
var ProviderDefaultScopes = map[string][]string{
"google": {"openid", "email", "profile"},
"github": {"user:email", "read:user"},
"microsoft": {"openid", "email", "profile", "User.Read"},
"apple": {"name", "email"},
"facebook": {"email", "public_profile"},
"discord": {"identify", "email"},
"twitter": {"users.read", "tweet.read"},
"linkedin": {"openid", "profile", "email"},
"spotify": {"user-read-email", "user-read-private"},
"twitch": {"user:read:email"},
"dropbox": {"account_info.read"},
"gitlab": {"read_user", "openid", "email"},
"line": {"profile", "openid", "email"},
"reddit": {"identity"},
"slack": {"users:read", "users:read.email"},
"bitbucket": {"account", "email"},
"notion": {},
}
ProviderDefaultScopes maps provider names to their default OAuth scopes
var ProviderDisplayNames = map[string]string{
"google": "Google",
"github": "GitHub",
"microsoft": "Microsoft",
"apple": "Apple",
"facebook": "Facebook",
"discord": "Discord",
"twitter": "Twitter / X",
"linkedin": "LinkedIn",
"spotify": "Spotify",
"twitch": "Twitch",
"dropbox": "Dropbox",
"gitlab": "GitLab",
"line": "LINE",
"reddit": "Reddit",
"slack": "Slack",
"bitbucket": "Bitbucket",
"notion": "Notion",
}
ProviderDisplayNames maps provider names to human-readable display names
var SupportedProviders = []string{
"google",
"github",
"microsoft",
"apple",
"facebook",
"discord",
"twitter",
"linkedin",
"spotify",
"twitch",
"dropbox",
"gitlab",
"line",
"reddit",
"slack",
"bitbucket",
"notion",
}
SupportedProviders returns the list of all supported OAuth provider names
Functions ¶
func GetProviderDefaultScopes ¶ added in v0.0.3
GetProviderDefaultScopes returns the default scopes for a provider
func GetProviderDisplayName ¶ added in v0.0.3
GetProviderDisplayName returns the display name for a provider
func IsValidOrgInvitationStatus ¶
IsValidOrgInvitationStatus checks if an invitation status is valid
func IsValidOrgMemberRole ¶
IsValidOrgMemberRole checks if a role is valid
func IsValidOrgMemberStatus ¶
IsValidOrgMemberStatus checks if a status is valid
func IsValidProvider ¶ added in v0.0.3
IsValidProvider checks if the given provider name is supported
func ValidOrgInvitationStatuses ¶
func ValidOrgInvitationStatuses() []string
ValidOrgInvitationStatuses returns the list of valid invitation statuses
func ValidOrgMemberRoles ¶
func ValidOrgMemberRoles() []string
ValidOrgMemberRoles returns the list of valid member roles
func ValidOrgMemberStatuses ¶
func ValidOrgMemberStatuses() []string
ValidOrgMemberStatuses returns the list of valid member statuses
Types ¶
type APIKey ¶
type APIKey struct {
AuditableModel
bun.BaseModel `bun:"table:api_keys"`
// 3-tier context (V2 architecture)
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"` // Platform tenant
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environmentID"` // Required: environment-scoped key
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationID,omitempty"` // Optional: org-scoped key
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)" json:"userID"` // User who created the key
// Key identification
Name string `bun:"name,notnull" json:"name"`
Description string `bun:"description" json:"description,omitempty"`
Prefix string `bun:"prefix,notnull,unique" json:"prefix"` // pk_test_xxx, sk_prod_xxx, rk_dev_xxx
KeyType string `bun:"key_type,notnull,default:'rk'" json:"keyType"` // pk/sk/rk
KeyHash string `bun:"key_hash,notnull" json:"-"` // Hashed key for verification
// Permissions and scopes
Scopes []string `bun:"scopes,type:jsonb" json:"scopes"` // ["read", "write", "admin"]
Permissions map[string]string `bun:"permissions,type:jsonb" json:"permissions"` // Custom permissions
RateLimit int `bun:"rate_limit,default:1000" json:"rate_limit"` // Requests per hour
AllowedIPs []string `bun:"allowed_ips,type:jsonb" json:"allowed_ips,omitempty"` // IP whitelist (CIDR notation supported)
// Status and expiration
Active bool `bun:"active,notnull,default:true" json:"active"`
ExpiresAt *time.Time `bun:"expires_at" json:"expires_at,omitempty"`
// Usage tracking
UsageCount int64 `bun:"usage_count,notnull,default:0" json:"usage_count"`
LastUsedAt *time.Time `bun:"last_used_at" json:"last_used_at,omitempty"`
LastUsedIP string `bun:"last_used_ip" json:"last_used_ip,omitempty"`
LastUsedUA string `bun:"last_used_ua" json:"last_used_ua,omitempty"`
// Metadata
Metadata map[string]string `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
// RBAC Integration (Hybrid Approach)
DelegateUserPermissions bool `bun:"delegate_user_permissions,notnull,default:false" json:"delegateUserPermissions"` // Inherit creator's permissions
ImpersonateUserID *xid.ID `bun:"impersonate_user_id,type:varchar(20)" json:"impersonateUserID,omitempty"` // Act as specific user
// RBAC Relationships
Roles []*Role `bun:"m2m:apikey_roles,join:APIKey=Role" json:"-"` // Many-to-many with roles
// Transient field - only populated during creation
Key string `bun:"-" json:"key,omitempty"`
}
APIKey represents an API key for programmatic access Updated for V2 architecture: App → Environment → Organization
func (*APIKey) BeforeAppendModel ¶
BeforeAppendModel implements bun.BeforeAppendModelHook
func (*APIKey) HasPermission ¶
HasPermission checks if the API key has a specific permission
func (*APIKey) IsIPAllowed ¶
IsIPAllowed checks if an IP address is in the allowed list Supports exact IP matching and CIDR notation
type APIKeyRole ¶
type APIKeyRole struct {
bun.BaseModel `bun:"table:apikey_roles,alias:akr"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
APIKeyID xid.ID `bun:"api_key_id,notnull,type:varchar(20)"`
RoleID xid.ID `bun:"role_id,notnull,type:varchar(20)"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)"` // Optional: org-scoped assignment
CreatedAt time.Time `bun:"created_at,notnull"`
CreatedBy *xid.ID `bun:"created_by,type:varchar(20)"`
DeletedAt *time.Time `bun:"deleted_at"`
// Relations
APIKey *APIKey `bun:"rel:belongs-to,join:api_key_id=id"`
Role *Role `bun:"rel:belongs-to,join:role_id=id"`
}
APIKeyRole represents the many-to-many relationship between API keys and roles This enables API keys to leverage the RBAC system for structured permissions
func (*APIKeyRole) BeforeAppendModel ¶
BeforeAppendModel implements bun.BeforeAppendModelHook
type Account ¶
type Account struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:accounts,alias:a"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"`
UserID xid.ID `json:"userID" bun:"user_id,notnull,type:varchar(20)"`
Provider string `json:"provider" bun:"provider,notnull"` // google, github, etc.
ProviderID string `json:"providerID" bun:"provider_id,notnull"`
AccessToken string `json:"accessToken" bun:"access_token"`
RefreshToken string `json:"refreshToken" bun:"refresh_token"`
ExpiresAt *time.Time `json:"expiresAt" bun:"expires_at"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
User *User `bun:"rel:belongs-to,join:user_id=id"`
}
Account represents OAuth accounts
type AccountLockout ¶
type AccountLockout struct {
bun.BaseModel `bun:"table:account_lockouts,alias:al"`
ID xid.ID `bun:"type:varchar(20),pk" json:"id"`
UserID xid.ID `bun:"type:varchar(20),notnull" json:"user_id"`
LockedUntil time.Time `bun:"type:timestamptz,notnull" json:"locked_until"`
Reason string `bun:"type:varchar(255)" json:"reason"`
CreatedAt time.Time `bun:"type:timestamptz,notnull,default:current_timestamp" json:"created_at"`
}
AccountLockout tracks locked user accounts due to failed login attempts
type App ¶
type App struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:apps,alias:a"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
Name string `json:"name" bun:"name,notnull"`
Slug string `json:"slug" bun:"slug,notnull,unique"`
Logo string `json:"logo" bun:"logo"`
Metadata map[string]interface{} `json:"metadata" bun:"metadata,type:jsonb"`
IsPlatform bool `json:"isPlatform" bun:"is_platform,default:false"` // Identifies the single platform app
// Relations
Members []Member `json:"members,omitempty" bun:"rel:has-many,join:id=app_id"`
Teams []Team `json:"teams,omitempty" bun:"rel:has-many,join:id=app_id"`
}
App represents the app table (formerly Organization - platform-level tenant)
type AuditEvent ¶
type AuditEvent struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:audit_events,alias:ae"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"`
OrganizationID *xid.ID `json:"organizationID,omitempty" bun:"organization_id,type:varchar(20)"` // User-created organization (optional)
EnvironmentID *xid.ID `json:"environmentID" bun:"environment_id,type:varchar(20)"` // Environment scoping
UserID *xid.ID `json:"userID" bun:"user_id,type:varchar(20)"`
Action string `json:"action" bun:"action,notnull"`
Resource string `json:"resource" bun:"resource,notnull"`
IPAddress string `json:"ipAddress" bun:"ip_address"`
UserAgent string `json:"userAgent" bun:"user_agent"`
Metadata string `json:"metadata" bun:"metadata"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id"`
}
AuditEvent represents the audit_events table
type AuditableModel ¶
type AuditableModel struct {
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
CreatedAt time.Time `json:"createdAt" bun:"created_at,nullzero,notnull,default:current_timestamp"`
CreatedBy xid.ID `json:"createdBy" bun:"created_by,nullzero"`
UpdatedAt time.Time `json:"updatedAt" bun:"updated_at,nullzero,notnull,default:current_timestamp"`
UpdatedBy xid.ID `json:"updatedBy" bun:"updated_by,nullzero"`
DeletedAt *time.Time `json:"deletedAt,omitempty" bun:"deleted_at,nullzero"`
Version int `json:"version" bun:"version,default:1"`
}
func (*AuditableModel) BeforeAppendModel ¶
type AuthorizationCode ¶
type AuthorizationCode struct {
AuditableModel
bun.BaseModel `bun:"table:authorization_codes"`
// Context fields
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"`
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environmentID"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationID,omitempty"` // Optional org context
SessionID *xid.ID `bun:"session_id,type:varchar(20)" json:"sessionID,omitempty"` // Link to user session
// OAuth2/OIDC fields
Code string `bun:"code,unique,notnull" json:"code"` // The authorization code
ClientID string `bun:"client_id,notnull" json:"clientID"` // OAuth client ID
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)" json:"userID"` // User who authorized
RedirectURI string `bun:"redirect_uri,notnull" json:"redirectURI"` // Redirect URI used in auth request
Scope string `bun:"scope,notnull" json:"scope"` // Requested scopes
State string `bun:"state" json:"state,omitempty"` // State parameter from auth request
Nonce string `bun:"nonce" json:"nonce,omitempty"` // Nonce for OIDC
CodeChallenge string `bun:"code_challenge" json:"codeChallenge,omitempty"` // PKCE code challenge
CodeChallengeMethod string `bun:"code_challenge_method" json:"codeChallengeMethod,omitempty"` // PKCE challenge method (S256, plain)
// Consent tracking
ConsentGranted bool `bun:"consent_granted,default:false" json:"consentGranted"`
ConsentScopes string `bun:"consent_scopes" json:"consentScopes,omitempty"` // Scopes user consented to
// Authentication context
AuthTime time.Time `bun:"auth_time,notnull" json:"authTime"` // When user authenticated (for max_age checks)
// Lifecycle
ExpiresAt time.Time `bun:"expires_at,notnull" json:"expiresAt"` // Code expiration (typically 10 minutes)
Used bool `bun:"used,notnull,default:false" json:"used"`
UsedAt *time.Time `bun:"used_at" json:"usedAt,omitempty"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id"`
Session *Session `bun:"rel:belongs-to,join:session_id=id"`
}
AuthorizationCode represents an OAuth2/OIDC authorization code
func (*AuthorizationCode) IsExpired ¶
func (ac *AuthorizationCode) IsExpired() bool
IsExpired checks if the authorization code has expired
func (*AuthorizationCode) IsValid ¶
func (ac *AuthorizationCode) IsValid() bool
IsValid checks if the authorization code is valid (not expired and not used)
type BackupCode ¶
type BackupCode struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:twofa_backup_codes,alias:tbc"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"`
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
CodeHash string `bun:"code_hash,notnull"`
UsedAt *time.Time `bun:"used_at"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
BackupCode stores recovery codes for 2FA
type Delivery ¶
type Delivery struct {
bun.BaseModel `bun:"table:webhook_deliveries,alias:wd"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
WebhookID xid.ID `bun:"webhook_id,notnull,type:varchar(20)" json:"webhook_id"`
EventID xid.ID `bun:"event_id,notnull,type:varchar(20)" json:"event_id"`
URL string `bun:"url,notnull" json:"url"`
HTTPMethod string `bun:"http_method,notnull,default:'POST'" json:"http_method"`
Headers []byte `bun:"headers,type:jsonb" json:"headers,omitempty"`
Body []byte `bun:"body" json:"body,omitempty"`
Status string `bun:"status,notnull" json:"status"`
StatusCode *int `bun:"status_code" json:"status_code,omitempty"`
ResponseHeaders []byte `bun:"response_headers,type:jsonb" json:"response_headers,omitempty"`
ResponseBody []byte `bun:"response_body" json:"response_body,omitempty"`
Error *string `bun:"error" json:"error,omitempty"`
AttemptNumber int `bun:"attempt_number,notnull,default:1" json:"attempt_number"`
NextRetryAt *time.Time `bun:"next_retry_at" json:"next_retry_at,omitempty"`
DeliveredAt *time.Time `bun:"delivered_at" json:"delivered_at,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
// Relations
Webhook *Webhook `bun:"rel:belongs-to,join:webhook_id=id" json:"webhook,omitempty"`
Event *Event `bun:"rel:belongs-to,join:event_id=id" json:"event,omitempty"`
}
Delivery represents a webhook delivery attempt
type Device ¶
type Device struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:devices,alias:d"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"`
UserID xid.ID `json:"userID" bun:"user_id,notnull,type:varchar(20)"`
Fingerprint string `json:"fingerprint" bun:"fingerprint,notnull,unique"`
UserAgent string `json:"userAgent" bun:"user_agent"`
IPAddress string `json:"ipAddress" bun:"ip_address"`
LastActive time.Time `json:"lastActive" bun:"last_active,notnull"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
User *User `bun:"rel:belongs-to,join:user_id=id"`
}
Device represents the devices table
type EmailOTP ¶
type EmailOTP struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:email_otps,alias:eotp"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"`
Email string `json:"email" bun:"email,notnull"`
OTP string `json:"otp" bun:"otp,notnull"`
ExpiresAt time.Time `json:"expiresAt" bun:"expires_at,notnull"`
Attempts int `json:"attempts" bun:"attempts,notnull,default:0"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
EmailOTP stores OTP codes for email-based authentication
type Environment ¶
type Environment struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:environments,alias:env"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"` // Foreign key to App
Name string `json:"name" bun:"name,notnull"`
Slug string `json:"slug" bun:"slug,notnull"` // dev, prod, staging
Type string `json:"type" bun:"type,notnull"` // development, production, staging, preview
Status string `json:"status" bun:"status,notnull,default:'active'"` // active, inactive
Config map[string]interface{} `json:"config" bun:"config,type:jsonb"` // Environment-specific configuration
IsDefault bool `json:"isDefault" bun:"is_default,notnull,default:false"` // Is this the default environment for the app
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
Environment represents an isolated data context within an App (dev, prod, staging, etc.)
func (*Environment) CanDelete ¶
func (e *Environment) CanDelete() bool
CanDelete checks if this environment can be deleted
func (*Environment) IsDevelopment ¶
func (e *Environment) IsDevelopment() bool
IsDevelopment checks if this is a development environment
func (*Environment) IsProduction ¶
func (e *Environment) IsProduction() bool
IsProduction checks if this is a production environment
type EnvironmentPromotion ¶
type EnvironmentPromotion struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:environment_promotions,alias:ep"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"`
SourceEnvID xid.ID `json:"sourceEnvId" bun:"source_env_id,notnull,type:varchar(20)"`
TargetEnvID xid.ID `json:"targetEnvId" bun:"target_env_id,notnull,type:varchar(20)"`
PromotedBy xid.ID `json:"promotedBy" bun:"promoted_by,notnull,type:varchar(20)"` // User who performed promotion
IncludeData bool `json:"includeData" bun:"include_data,notnull,default:false"` // Whether to copy data or just schema
Status string `json:"status" bun:"status,notnull"` // pending, in_progress, completed, failed
ErrorMessage string `json:"errorMessage" bun:"error_message"`
CompletedAt *time.Time `json:"completedAt" bun:"completed_at"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
SourceEnv *Environment `bun:"rel:belongs-to,join:source_env_id=id"`
TargetEnv *Environment `bun:"rel:belongs-to,join:target_env_id=id"`
}
EnvironmentPromotion represents a promotion from one environment to another
type Event ¶
type Event struct {
bun.BaseModel `bun:"table:webhook_events,alias:we"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"app_id"`
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environment_id"`
Type string `bun:"type,notnull" json:"type"`
Data map[string]interface{} `bun:"data,type:jsonb" json:"data"`
UserID *xid.ID `bun:"user_id,type:varchar(20)" json:"user_id,omitempty"`
SessionID *xid.ID `bun:"session_id,type:varchar(20)" json:"session_id,omitempty"`
IPAddress string `bun:"ip_address" json:"ip_address,omitempty"`
UserAgent string `bun:"user_agent" json:"user_agent,omitempty"`
OccurredAt time.Time `bun:"occurred_at,nullzero,notnull,default:current_timestamp" json:"occurred_at"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
}
Event represents a webhook event
type FailedLoginAttempt ¶
type FailedLoginAttempt struct {
bun.BaseModel `bun:"table:failed_login_attempts,alias:fla"`
ID xid.ID `bun:"type:varchar(20),pk" json:"id"`
Username string `bun:"type:varchar(255),notnull" json:"username"`
AppID xid.ID `bun:"type:varchar(20),notnull" json:"app_id"`
IP string `bun:"type:varchar(45)" json:"ip"`
UserAgent string `bun:"type:text" json:"user_agent"`
AttemptAt time.Time `bun:"type:timestamptz,notnull,default:current_timestamp" json:"attempt_at"`
}
FailedLoginAttempt records failed login attempts for account lockout functionality
type FormField ¶
type FormField struct {
ID string `json:"id"`
Type string `json:"type"` // text, email, password, select, checkbox, etc.
Label string `json:"label"`
Placeholder string `json:"placeholder"`
Required bool `json:"required"`
Validation map[string]interface{} `json:"validation"`
Options []string `json:"options,omitempty"` // For select fields
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
FormField represents a single form field configuration
type FormSchema ¶
type FormSchema struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:form_schemas,alias:fs"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"` // App-scoped form schemas
Type string `json:"type" bun:"type,notnull"` // signup, signin, profile, etc.
Name string `json:"name" bun:"name,notnull"`
Description string `json:"description" bun:"description"`
Schema map[string]interface{} `json:"schema" bun:"schema,type:jsonb,notnull"`
IsActive bool `json:"isActive" bun:"is_active,notnull,default:true"`
Version int `json:"version" bun:"version,notnull,default:1"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
FormSchema represents app-specific form configurations
type FormSubmission ¶
type FormSubmission struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:form_submissions,alias:fsub"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
FormSchemaID xid.ID `json:"formSchemaId" bun:"form_schema_id,notnull,type:varchar(20)"`
UserID *xid.ID `json:"userId" bun:"user_id,type:varchar(20)"` // Optional for anonymous submissions
SessionID *xid.ID `json:"sessionId" bun:"session_id,type:varchar(20)"`
Data map[string]interface{} `json:"data" bun:"data,type:jsonb,notnull"`
IPAddress string `json:"ipAddress" bun:"ip_address"`
UserAgent string `json:"userAgent" bun:"user_agent"`
Status string `json:"status" bun:"status,notnull,default:'submitted'"` // submitted, processed, failed
// Relations
FormSchema *FormSchema `bun:"rel:belongs-to,join:form_schema_id=id"`
User *User `bun:"rel:belongs-to,join:user_id=id"`
Session *Session `bun:"rel:belongs-to,join:session_id=id"`
}
FormSubmission represents a form submission
type IdentityVerification ¶
type IdentityVerification struct {
AuditableModel
bun.BaseModel `bun:"table:identity_verifications,alias:iv"`
ID string `bun:"id,pk,type:varchar(255)" json:"id"`
// V2 Multi-tenant context (App → Environment → Organization)
AppID string `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
EnvironmentID *string `bun:"environment_id,type:varchar(20)" json:"environmentId,omitempty"`
OrganizationID string `bun:"organization_id,notnull,type:varchar(20)" json:"organizationId"`
UserID string `bun:"user_id,notnull,type:varchar(20)" json:"userId"`
// Provider information
Provider string `bun:"provider,notnull,type:varchar(50)" json:"provider"` // onfido, jumio, stripe_identity
ProviderCheckID string `bun:"provider_check_id,type:varchar(255)" json:"providerCheckId"`
// Verification type and status
VerificationType string `bun:"verification_type,notnull,type:varchar(50)" json:"verificationType"` // document, liveness, age, aml
Status string `bun:"status,notnull,type:varchar(50)" json:"status"` // pending, in_progress, completed, failed, expired
// Document information (if applicable)
DocumentType string `bun:"document_type,type:varchar(50)" json:"documentType,omitempty"` // passport, drivers_license, national_id
DocumentNumber string `bun:"document_number,type:varchar(255)" json:"documentNumber,omitempty"` // Encrypted
DocumentCountry string `bun:"document_country,type:varchar(2)" json:"documentCountry,omitempty"` // ISO 3166-1 alpha-2
// Verification results
IsVerified bool `bun:"is_verified,default:false" json:"isVerified"`
RiskScore int `bun:"risk_score,type:int" json:"riskScore,omitempty"` // 0-100, higher is riskier
RiskLevel string `bun:"risk_level,type:varchar(20)" json:"riskLevel,omitempty"` // low, medium, high
ConfidenceScore int `bun:"confidence_score,type:int" json:"confidenceScore,omitempty"` // 0-100
// Personal information extracted
FirstName string `bun:"first_name,type:varchar(255)" json:"firstName,omitempty"`
LastName string `bun:"last_name,type:varchar(255)" json:"lastName,omitempty"`
DateOfBirth *time.Time `bun:"date_of_birth,type:date" json:"dateOfBirth,omitempty"`
Age int `bun:"age,type:int" json:"age,omitempty"`
Gender string `bun:"gender,type:varchar(20)" json:"gender,omitempty"`
Nationality string `bun:"nationality,type:varchar(2)" json:"nationality,omitempty"` // ISO 3166-1 alpha-2
// AML/Sanctions screening results
IsOnSanctionsList bool `bun:"is_on_sanctions_list,default:false" json:"isOnSanctionsList"`
IsPEP bool `bun:"is_pep,default:false" json:"isPep"` // Politically Exposed Person
SanctionsDetails string `bun:"sanctions_details,type:text" json:"sanctionsDetails,omitempty"`
// Liveness detection
LivenessScore int `bun:"liveness_score,type:int" json:"livenessScore,omitempty"` // 0-100
IsLive bool `bun:"is_live,default:false" json:"isLive"`
// Rejection/failure information
RejectionReasons []string `bun:"rejection_reasons,type:jsonb" json:"rejectionReasons,omitempty"`
FailureReason string `bun:"failure_reason,type:text" json:"failureReason,omitempty"`
// Metadata
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
ProviderData map[string]interface{} `bun:"provider_data,type:jsonb" json:"providerData,omitempty"` // Raw provider response
IPAddress string `bun:"ip_address,type:varchar(45)" json:"ipAddress,omitempty"`
UserAgent string `bun:"user_agent,type:text" json:"userAgent,omitempty"`
// Expiry and validity
ExpiresAt *time.Time `bun:"expires_at,type:timestamptz" json:"expiresAt,omitempty"`
VerifiedAt *time.Time `bun:"verified_at,type:timestamptz" json:"verifiedAt,omitempty"`
// Webhook tracking
WebhookDeliveryStatus string `bun:"webhook_delivery_status,type:varchar(50)" json:"webhookDeliveryStatus,omitempty"`
WebhookDeliveredAt *time.Time `bun:"webhook_delivered_at,type:timestamptz" json:"webhookDeliveredAt,omitempty"`
// Relations
User *User `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"`
}
IdentityVerification represents a KYC verification attempt
type IdentityVerificationDocument ¶
type IdentityVerificationDocument struct {
bun.BaseModel `bun:"table:identity_verification_documents,alias:ivd"`
ID string `bun:"id,pk,type:varchar(255)" json:"id"`
VerificationID string `bun:"verification_id,notnull,type:varchar(255)" json:"verificationId"`
// V2 Multi-tenant context (inherited from parent verification)
AppID string `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
EnvironmentID *string `bun:"environment_id,type:varchar(20)" json:"environmentId,omitempty"`
OrganizationID string `bun:"organization_id,notnull,type:varchar(20)" json:"organizationId"`
// Document details
DocumentSide string `bun:"document_side,type:varchar(20)" json:"documentSide"` // front, back, selfie
FileURL string `bun:"file_url,type:text" json:"fileUrl"` // Encrypted storage URL
FileHash string `bun:"file_hash,type:varchar(64)" json:"fileHash"` // SHA-256 for integrity
MimeType string `bun:"mime_type,type:varchar(100)" json:"mimeType"`
FileSize int64 `bun:"file_size,type:bigint" json:"fileSize"`
// Processing status
ProcessingStatus string `bun:"processing_status,type:varchar(50)" json:"processingStatus"` // pending, processing, processed, failed
// Extracted data
ExtractedData map[string]interface{} `bun:"extracted_data,type:jsonb" json:"extractedData,omitempty"`
// Retention policy
RetainUntil *time.Time `bun:"retain_until,type:timestamptz" json:"retainUntil,omitempty"`
DeletedAt *time.Time `bun:"deleted_at,type:timestamptz" json:"deletedAt,omitempty"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp" json:"updatedAt"`
// Relations
Verification *IdentityVerification `bun:"rel:belongs-to,join:verification_id=id" json:"verification,omitempty"`
}
IdentityVerificationDocument represents uploaded documents for verification
type IdentityVerificationSession ¶
type IdentityVerificationSession struct {
bun.BaseModel `bun:"table:identity_verification_sessions,alias:ivs"`
ID string `bun:"id,pk,type:varchar(255)" json:"id"`
// V2 Multi-tenant context (App → Environment → Organization)
AppID string `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
EnvironmentID *string `bun:"environment_id,type:varchar(20)" json:"environmentId,omitempty"`
OrganizationID string `bun:"organization_id,notnull,type:varchar(20)" json:"organizationId"`
UserID string `bun:"user_id,notnull,type:varchar(20)" json:"userId"`
// Session details
Provider string `bun:"provider,notnull,type:varchar(50)" json:"provider"`
SessionURL string `bun:"session_url,type:text" json:"sessionUrl"` // URL for user to complete verification
SessionToken string `bun:"session_token,type:varchar(255)" json:"sessionToken"` // Encrypted
// Configuration
RequiredChecks []string `bun:"required_checks,type:jsonb" json:"requiredChecks"` // [document, liveness, aml]
Config map[string]interface{} `bun:"config,type:jsonb" json:"config,omitempty"`
// Status tracking
Status string `bun:"status,notnull,type:varchar(50)" json:"status"` // created, started, completed, abandoned, expired
CompletedAt *time.Time `bun:"completed_at,type:timestamptz" json:"completedAt,omitempty"`
ExpiresAt time.Time `bun:"expires_at,notnull,type:timestamptz" json:"expiresAt"`
// Callback URLs
SuccessURL string `bun:"success_url,type:text" json:"successUrl,omitempty"`
CancelURL string `bun:"cancel_url,type:text" json:"cancelUrl,omitempty"`
// Tracking
IPAddress string `bun:"ip_address,type:varchar(45)" json:"ipAddress,omitempty"`
UserAgent string `bun:"user_agent,type:text" json:"userAgent,omitempty"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp" json:"updatedAt"`
// Relations
User *User `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"`
}
IdentityVerificationSession represents a verification session/flow
type ImpersonationAuditEvent ¶
type ImpersonationAuditEvent struct {
bun.BaseModel `bun:"table:impersonation_audit,alias:ia"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
ImpersonationID xid.ID `bun:"impersonation_id,notnull,type:varchar(20)" json:"impersonationID"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"` // Platform app (required)
EnvironmentID *xid.ID `bun:"environment_id,type:varchar(20)" json:"environmentID,omitempty"` // Environment (optional)
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationID,omitempty"` // User-created organization (optional)
EventType string `bun:"event_type,notnull,type:varchar(50)" json:"eventType"` // started, ended, action_performed, expired
Action string `bun:"action,type:varchar(100)" json:"action,omitempty"` // Specific action performed during impersonation
Resource string `bun:"resource,type:varchar(255)" json:"resource,omitempty"` // Resource accessed
IPAddress string `bun:"ip_address,type:varchar(45)" json:"ipAddress"`
UserAgent string `bun:"user_agent,type:text" json:"userAgent"`
Details map[string]string `bun:"details,type:jsonb" json:"details,omitempty"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"createdAt"`
// Relationships
ImpersonationSession *ImpersonationSession `bun:"rel:belongs-to,join:impersonation_id=id" json:"impersonationSession,omitempty"`
App *App `bun:"rel:belongs-to,join:app_id=id" json:"app,omitempty"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id" json:"environment,omitempty"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"`
}
ImpersonationAuditEvent represents a detailed audit log for impersonation events Updated for V2 architecture: App → Environment → Organization
type ImpersonationSession ¶
type ImpersonationSession struct {
AuditableModel
bun.BaseModel `bun:"table:impersonation_sessions,alias:is"`
// Core fields
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"` // Platform app (required)
EnvironmentID *xid.ID `bun:"environment_id,type:varchar(20)" json:"environmentID,omitempty"` // Environment (optional)
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationID,omitempty"` // User-created organization (optional)
ImpersonatorID xid.ID `bun:"impersonator_id,notnull,type:varchar(20)" json:"impersonatorID"` // Admin who is impersonating
TargetUserID xid.ID `bun:"target_user_id,notnull,type:varchar(20)" json:"targetUserID"` // User being impersonated
OriginalSession *xid.ID `bun:"original_session,type:varchar(20)" json:"originalSession,omitempty"` // Admin's original session
NewSessionID *xid.ID `bun:"new_session_id,type:varchar(20)" json:"newSessionID,omitempty"` // New session for impersonation
SessionToken string `bun:"session_token,type:text" json:"-"` // Session token for revocation (not exposed in JSON)
// Metadata
Reason string `bun:"reason,type:text" json:"reason"` // Required: ticket/reason for impersonation
IPAddress string `bun:"ip_address,type:varchar(45)" json:"ip_address"` // Admin's IP
UserAgent string `bun:"user_agent,type:text" json:"user_agent"` // Admin's user agent
Metadata map[string]string `bun:"metadata,type:jsonb" json:"metadata,omitempty"` // Additional context
TicketNumber string `bun:"ticket_number,type:varchar(100)" json:"ticket_number,omitempty"` // Support ticket reference
// Status and lifecycle
Active bool `bun:"active,notnull,default:true" json:"active"` // Currently active
ExpiresAt time.Time `bun:"expires_at,notnull" json:"expires_at"` // Auto-logout time
EndedAt *time.Time `bun:"ended_at" json:"ended_at,omitempty"` // When impersonation ended
EndReason string `bun:"end_reason,type:varchar(50)" json:"end_reason,omitempty"` // manual, timeout, error
// Relationships (for joins)
Impersonator *User `bun:"rel:belongs-to,join:impersonator_id=id" json:"impersonator,omitempty"`
TargetUser *User `bun:"rel:belongs-to,join:target_user_id=id" json:"targetUser,omitempty"`
App *App `bun:"rel:belongs-to,join:app_id=id" json:"app,omitempty"` // Platform app
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id" json:"environment,omitempty"` // Environment (optional)
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"` // User-created org (optional)
}
ImpersonationSession represents an admin impersonating a user Updated for V2 architecture: App → Environment → Organization
func (*ImpersonationSession) IsActive ¶
func (i *ImpersonationSession) IsActive() bool
IsActive checks if the impersonation session is currently active
func (*ImpersonationSession) IsExpired ¶
func (i *ImpersonationSession) IsExpired() bool
IsExpired checks if the impersonation session has expired
type Invitation ¶
type Invitation struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:invitations,alias:inv"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"`
Email string `json:"email" bun:"email,notnull"`
Role MemberRole `json:"role" bun:"role,notnull"`
InviterID xid.ID `json:"inviterID" bun:"inviter_id,notnull,type:varchar(20)"`
Token string `json:"token" bun:"token,notnull,unique"`
ExpiresAt time.Time `json:"expiresAt" bun:"expires_at,notnull"`
AcceptedAt *time.Time `json:"acceptedAt" bun:"accepted_at"`
Status InvitationStatus `json:"status" bun:"status,notnull"`
Metadata map[string]interface{} `json:"metadata" bun:"metadata,type:jsonb"`
// Relations
App *App `json:"app,omitempty" bun:"rel:belongs-to,join:app_id=id"`
}
Invitation represents the app invitation table
type InvitationStatus ¶
type InvitationStatus string
InvitationStatus represents the status of an invitation
const ( InvitationStatusPending InvitationStatus = "pending" InvitationStatusAccepted InvitationStatus = "accepted" InvitationStatusExpired InvitationStatus = "expired" InvitationStatusCancelled InvitationStatus = "cancelled" InvitationStatusDeclined InvitationStatus = "declined" )
func (InvitationStatus) IsValid ¶
func (s InvitationStatus) IsValid() bool
IsValid checks if the status is valid
func (InvitationStatus) String ¶
func (s InvitationStatus) String() string
String returns the string representation
type JSONMap ¶
type JSONMap map[string]interface{}
JSONMap is a helper type for storing JSON data
type JWTKey ¶
type JWTKey struct {
AuditableModel
bun.BaseModel `bun:"table:jwt_keys"`
// App context
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"`
IsPlatformKey bool `bun:"is_platform_key,notnull,default:false" json:"isPlatformKey"`
// Key identification
KeyID string `bun:"key_id,notnull" json:"keyID"` // Kid for JWKS (unique per app)
Algorithm string `bun:"algorithm,notnull" json:"algorithm"` // EdDSA, RS256, etc.
KeyType string `bun:"key_type,notnull" json:"keyType"` // OKP, RSA
Curve string `bun:"curve" json:"curve,omitempty"` // Ed25519, P-256, etc.
// Key material (encrypted)
PrivateKey []byte `bun:"private_key,notnull" json:"-"` // Encrypted private key
PublicKey []byte `bun:"public_key,notnull" json:"publicKey"` // Public key for JWKS
// Key status
Active bool `bun:"active,notnull,default:true" json:"active"`
ExpiresAt *time.Time `bun:"expires_at" json:"expiresAt,omitempty"`
// Usage tracking
UsageCount int64 `bun:"usage_count,notnull,default:0" json:"usageCount"`
LastUsedAt *time.Time `bun:"last_used_at" json:"lastUsedAt,omitempty"`
// Metadata
Name string `bun:"name" json:"name,omitempty"`
Description string `bun:"description" json:"description,omitempty"`
Metadata map[string]string `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
JWTKey represents a JWT signing key
type MFAAttempt ¶
type MFAAttempt struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_attempts,alias:mfa"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
FactorID *xid.ID `bun:"factor_id,type:varchar(20)"`
ChallengeID *xid.ID `bun:"challenge_id,type:varchar(20)"`
Type string `bun:"type,notnull"` // Factor type
Success bool `bun:"success,notnull"`
FailureReason string `bun:"failure_reason"`
IPAddress string `bun:"ip_address"`
UserAgent string `bun:"user_agent"`
Metadata JSONMap `bun:"metadata,type:jsonb"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFAAttempt tracks verification attempts for rate limiting and security
type MFABypass ¶
type MFABypass struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_bypasses,alias:mfb"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
GrantedBy xid.ID `bun:"granted_by,notnull,type:varchar(20)"` // Admin who granted bypass
Reason string `bun:"reason,notnull"`
ExpiresAt time.Time `bun:"expires_at,notnull"`
RevokedAt *time.Time `bun:"revoked_at"`
RevokedBy *xid.ID `bun:"revoked_by,type:varchar(20)"`
Metadata JSONMap `bun:"metadata,type:jsonb"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFABypass represents temporary MFA bypass granted by admins
type MFAChallenge ¶
type MFAChallenge struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_challenges,alias:mfc"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context
SessionID xid.ID `bun:"session_id,notnull,type:varchar(20)"` // Links to MFA session
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
FactorID xid.ID `bun:"factor_id,notnull,type:varchar(20)"`
Type string `bun:"type,notnull"` // Factor type
Status string `bun:"status,notnull"` // pending, verified, failed, expired
CodeHash string `bun:"code_hash"` // Hashed verification code
Metadata JSONMap `bun:"metadata,type:jsonb"`
Attempts int `bun:"attempts,notnull,default:0"`
MaxAttempts int `bun:"max_attempts,notnull,default:3"`
IPAddress string `bun:"ip_address"`
UserAgent string `bun:"user_agent"`
ExpiresAt time.Time `bun:"expires_at,notnull"`
VerifiedAt *time.Time `bun:"verified_at"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFAChallenge stores active MFA verification challenges
type MFAFactor ¶
type MFAFactor struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_factors,alias:mff"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context (required)
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)"` // User-created org (optional)
Type string `bun:"type,notnull"` // totp, sms, email, webauthn, backup, etc.
Status string `bun:"status,notnull"` // pending, active, disabled, revoked
Priority string `bun:"priority,notnull"` // primary, backup, optional
Name string `bun:"name"` // User-friendly name
Secret string `bun:"secret"` // Encrypted factor secret
Metadata JSONMap `bun:"metadata,type:jsonb"` // Factor-specific metadata
LastUsedAt *time.Time `bun:"last_used_at"`
VerifiedAt *time.Time `bun:"verified_at"`
ExpiresAt *time.Time `bun:"expires_at"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFAFactor stores enrolled authentication factors for users
type MFAPolicy ¶
type MFAPolicy struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_policies,alias:mfp"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)"` // User-created org (optional)
Enabled bool `bun:"enabled,notnull,default:true"`
RequiredFactorCount int `bun:"required_factor_count,notnull,default:1"`
AllowedFactorTypes StringArray `bun:"allowed_factor_types,type:text[]"`
RequiredFactorTypes StringArray `bun:"required_factor_types,type:text[]"`
GracePeriodDays int `bun:"grace_period_days,notnull,default:7"`
TrustedDeviceDays int `bun:"trusted_device_days,notnull,default:30"`
StepUpRequired bool `bun:"step_up_required,notnull,default:false"`
AdaptiveMFAEnabled bool `bun:"adaptive_mfa_enabled,notnull,default:false"`
MaxFailedAttempts int `bun:"max_failed_attempts,notnull,default:5"`
LockoutDurationMinutes int `bun:"lockout_duration_minutes,notnull,default:30"`
Metadata JSONMap `bun:"metadata,type:jsonb"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFAPolicy defines organization-level MFA requirements
type MFARiskAssessment ¶
type MFARiskAssessment struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_risk_assessments,alias:mra"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
SessionID *xid.ID `bun:"session_id,type:varchar(20)"`
RiskLevel string `bun:"risk_level,notnull"` // low, medium, high, critical
RiskScore float64 `bun:"risk_score,notnull"` // 0-100
Factors StringArray `bun:"factors,type:text[]"` // Risk factors identified
Recommended StringArray `bun:"recommended,type:text[]"` // Recommended factor types
IPAddress string `bun:"ip_address"`
UserAgent string `bun:"user_agent"`
Location string `bun:"location"` // Geographic location
Metadata JSONMap `bun:"metadata,type:jsonb"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFARiskAssessment stores risk assessment results
type MFASession ¶
type MFASession struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_sessions,alias:mfs"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
SessionToken string `bun:"session_token,unique,notnull"`
FactorsRequired int `bun:"factors_required,notnull"`
FactorsVerified int `bun:"factors_verified,notnull,default:0"`
VerifiedFactors StringArray `bun:"verified_factors,type:text[]"` // Array of factor IDs
RiskLevel string `bun:"risk_level"` // low, medium, high, critical
RiskScore float64 `bun:"risk_score"` // 0-100
Context string `bun:"context"` // login, transaction, step-up
IPAddress string `bun:"ip_address"`
UserAgent string `bun:"user_agent"`
Metadata JSONMap `bun:"metadata,type:jsonb"`
ExpiresAt time.Time `bun:"expires_at,notnull"`
CompletedAt *time.Time `bun:"completed_at"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFASession represents an MFA verification session
type MFATrustedDevice ¶
type MFATrustedDevice struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:mfa_trusted_devices,alias:mtd"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
DeviceID string `bun:"device_id,notnull"` // Fingerprint/identifier
Name string `bun:"name"` // User-friendly name
Metadata JSONMap `bun:"metadata,type:jsonb"` // Device info
IPAddress string `bun:"ip_address"`
UserAgent string `bun:"user_agent"`
LastUsedAt *time.Time `bun:"last_used_at"`
ExpiresAt time.Time `bun:"expires_at,notnull"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MFATrustedDevice stores trusted devices that can skip MFA
type MagicLink ¶
type MagicLink struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:magic_links,alias:ml"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
Email string `json:"email" bun:"email,notnull"`
Token string `json:"token" bun:"token,notnull"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"` // Platform app (required)
OrganizationID *xid.ID `json:"organizationID,omitempty" bun:"organization_id,type:varchar(20)"` // User-created org (optional)
EnvironmentID *xid.ID `json:"environmentID,omitempty" bun:"environment_id,type:varchar(20)"` // Optional environment context
ExpiresAt time.Time `json:"expiresAt" bun:"expires_at,notnull"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
MagicLink stores passwordless email tokens Updated for V2 architecture: App → Environment → Organization
type Member ¶
type Member struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:members,alias:m"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"` // App context
UserID xid.ID `json:"userID" bun:"user_id,notnull,type:varchar(20)"`
Role MemberRole `json:"role" bun:"role,nullzero"`
Status MemberStatus `json:"status" bun:"status,notnull,default:'active'"`
JoinedAt time.Time `json:"joinedAt" bun:"joined_at,nullzero,notnull,default:current_timestamp"` // when the member joined
// Relations
App *App `json:"app,omitempty" bun:"rel:belongs-to,join:app_id=id"`
User *User `json:"user,omitempty" bun:"rel:belongs-to,join:user_id=id"`
Teams []Team `json:"teams,omitempty" bun:"m2m:team_members,join:Member=Team"`
}
Member represents the app member table
type MemberRole ¶
type MemberRole string
MemberRole represents the role of a member in an app
const ( MemberRoleOwner MemberRole = "owner" MemberRoleAdmin MemberRole = "admin" MemberRoleMember MemberRole = "member" )
func (MemberRole) String ¶
func (r MemberRole) String() string
String returns the string representation
type MemberStatus ¶
type MemberStatus string
MemberStatus represents the status of a member
const ( MemberStatusActive MemberStatus = "active" MemberStatusSuspended MemberStatus = "suspended" MemberStatusPending MemberStatus = "pending" )
func (MemberStatus) IsValid ¶
func (s MemberStatus) IsValid() bool
IsValid checks if the status is valid
func (MemberStatus) String ¶
func (s MemberStatus) String() string
String returns the string representation
type Notification ¶
type Notification struct {
bun.BaseModel `bun:"table:notifications,alias:n"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
TemplateID *xid.ID `bun:"template_id,type:varchar(20)" json:"templateId,omitempty"`
Type string `bun:"type,notnull" json:"type"`
Recipient string `bun:"recipient,notnull" json:"recipient"`
Subject string `bun:"subject" json:"subject,omitempty"`
Body string `bun:"body,notnull" json:"body"`
Status string `bun:"status,notnull" json:"status"`
Error string `bun:"error" json:"error,omitempty"`
ProviderID string `bun:"provider_id" json:"providerId,omitempty"`
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
SentAt *time.Time `bun:"sent_at" json:"sentAt,omitempty"`
DeliveredAt *time.Time `bun:"delivered_at" json:"deliveredAt,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updatedAt"`
// Relations
Template *NotificationTemplate `bun:"rel:belongs-to,join:template_id=id" json:"template,omitempty"`
}
Notification represents a notification instance in the database
type NotificationAnalytics ¶
type NotificationAnalytics struct {
bun.BaseModel `bun:"table:notification_analytics,alias:na"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
NotificationID xid.ID `bun:"notification_id,notnull,type:varchar(20)" json:"notificationId"`
TemplateID *xid.ID `bun:"template_id,type:varchar(20)" json:"templateId,omitempty"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationId,omitempty"`
Event string `bun:"event,notnull" json:"event"` // sent, delivered, opened, clicked, converted, bounced, complained
EventData map[string]interface{} `bun:"event_data,type:jsonb" json:"eventData,omitempty"` // Additional event-specific data (e.g., link clicked, conversion value)
UserAgent string `bun:"user_agent" json:"userAgent,omitempty"`
IPAddress string `bun:"ip_address" json:"ipAddress,omitempty"`
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
// Relations
Notification *Notification `bun:"rel:belongs-to,join:notification_id=id" json:"notification,omitempty"`
Template *NotificationTemplate `bun:"rel:belongs-to,join:template_id=id" json:"template,omitempty"`
App *App `bun:"rel:belongs-to,join:app_id=id" json:"app,omitempty"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"`
}
NotificationAnalytics represents a single analytics event for a notification
type NotificationEvent ¶
type NotificationEvent string
NotificationEvent represents the type of analytics event
const ( NotificationEventSent NotificationEvent = "sent" // Notification sent NotificationEventDelivered NotificationEvent = "delivered" // Provider confirmed delivery NotificationEventOpened NotificationEvent = "opened" // Recipient opened (email tracking pixel) NotificationEventClicked NotificationEvent = "clicked" // Recipient clicked link (tracked URL) NotificationEventConverted NotificationEvent = "converted" // Recipient completed desired action NotificationEventBounced NotificationEvent = "bounced" // Delivery failed permanently NotificationEventComplained NotificationEvent = "complained" // Recipient marked as spam NotificationEventFailed NotificationEvent = "failed" // General failure )
type NotificationProvider ¶
type NotificationProvider struct {
bun.BaseModel `bun:"table:notification_providers,alias:np"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationId,omitempty"` // Nullable for app-level providers
ProviderType string `bun:"provider_type,notnull" json:"providerType"` // email, sms, push
ProviderName string `bun:"provider_name,notnull" json:"providerName"` // smtp, sendgrid, twilio, etc.
Config map[string]interface{} `bun:"config,type:jsonb,notnull" json:"config"` // Encrypted provider configuration
IsActive bool `bun:"is_active,notnull,default:true" json:"isActive"`
IsDefault bool `bun:"is_default,notnull,default:false" json:"isDefault"` // Default provider for this type
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updatedAt"`
DeletedAt *time.Time `bun:"deleted_at,soft_delete,nullzero" json:"-"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id" json:"app,omitempty"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"`
}
NotificationProvider represents a notification provider configuration in the database Providers can be configured at app-level or organization-level
type NotificationQueue ¶ added in v0.0.7
type NotificationQueue struct {
bun.BaseModel `bun:"table:notification_queue,alias:nq"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
// Notification details
Type string `bun:"type,notnull" json:"type"` // email, sms, push
Priority string `bun:"priority,notnull" json:"priority"` // critical, high, normal, low
Recipient string `bun:"recipient,notnull" json:"recipient"` // Email address or phone number
Subject string `bun:"subject" json:"subject,omitempty"` // Email subject
Body string `bun:"body" json:"body,omitempty"` // Direct body content
TemplateKey string `bun:"template_key" json:"templateKey,omitempty"` // Template key if using template
// Payload for retry (JSON serialized request)
Payload []byte `bun:"payload,type:bytea" json:"payload,omitempty"`
// Retry state
Attempts int `bun:"attempts,notnull,default:0" json:"attempts"`
MaxAttempts int `bun:"max_attempts,notnull,default:3" json:"maxAttempts"`
LastError string `bun:"last_error" json:"lastError,omitempty"`
Status NotificationQueueStatus `bun:"status,notnull,default:'pending'" json:"status"`
NextRetryAt *time.Time `bun:"next_retry_at" json:"nextRetryAt,omitempty"`
ProcessedAt *time.Time `bun:"processed_at" json:"processedAt,omitempty"`
// Audit fields
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updatedAt"`
}
NotificationQueue represents a notification queued for retry in the database
type NotificationQueueStats ¶ added in v0.0.7
type NotificationQueueStats struct {
PendingCount int64 `json:"pendingCount"`
ProcessingCount int64 `json:"processingCount"`
SucceededCount int64 `json:"succeededCount"`
FailedCount int64 `json:"failedCount"`
TotalCount int64 `json:"totalCount"`
}
NotificationQueueStats holds aggregate statistics for the notification queue
type NotificationQueueStatus ¶ added in v0.0.7
type NotificationQueueStatus string
NotificationQueueStatus represents the status of a queued notification
const ( NotificationQueueStatusPending NotificationQueueStatus = "pending" NotificationQueueStatusProcessing NotificationQueueStatus = "processing" NotificationQueueStatusSucceeded NotificationQueueStatus = "succeeded" NotificationQueueStatusFailed NotificationQueueStatus = "failed" )
type NotificationTemplate ¶
type NotificationTemplate struct {
bun.BaseModel `bun:"table:notification_templates,alias:nt"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationId,omitempty"` // Nullable for app-level templates
TemplateKey string `bun:"template_key,notnull" json:"templateKey"` // e.g., "auth.welcome", "auth.mfa_code"
Name string `bun:"name,notnull" json:"name"`
Type string `bun:"type,notnull" json:"type"`
Language string `bun:"language,notnull,default:'en'" json:"language"`
Subject string `bun:"subject" json:"subject,omitempty"`
Body string `bun:"body,notnull" json:"body"`
Variables []string `bun:"variables,array" json:"variables"`
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
Active bool `bun:"active,notnull,default:true" json:"active"`
IsDefault bool `bun:"is_default,notnull,default:false" json:"isDefault"` // Is this a default template
IsModified bool `bun:"is_modified,notnull,default:false" json:"isModified"` // Has it been modified from default
DefaultHash string `bun:"default_hash" json:"defaultHash"` // Hash of default content for comparison
// Versioning fields
Version int `bun:"version,notnull,default:1" json:"version"` // Current version number
ParentID *xid.ID `bun:"parent_id,type:varchar(20)" json:"parentId,omitempty"` // ID of template this was cloned from
// A/B Testing fields
ABTestGroup string `bun:"ab_test_group" json:"abTestGroup,omitempty"` // Group identifier for variants
ABTestEnabled bool `bun:"ab_test_enabled,notnull,default:false" json:"abTestEnabled"` // Is this variant active in A/B test
ABTestWeight int `bun:"ab_test_weight,notnull,default:100" json:"abTestWeight"` // Weight for variant selection (0-100)
// Analytics fields
SendCount int64 `bun:"send_count,notnull,default:0" json:"sendCount"` // Total sends
OpenCount int64 `bun:"open_count,notnull,default:0" json:"openCount"` // Total opens
ClickCount int64 `bun:"click_count,notnull,default:0" json:"clickCount"` // Total clicks
ConversionCount int64 `bun:"conversion_count,notnull,default:0" json:"conversionCount"` // Total conversions
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updatedAt"`
DeletedAt *time.Time `bun:"deleted_at,soft_delete,nullzero" json:"-"`
}
NotificationTemplate represents a notification template in the database
type NotificationTemplateVersion ¶
type NotificationTemplateVersion struct {
bun.BaseModel `bun:"table:notification_template_versions,alias:ntv"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
TemplateID xid.ID `bun:"template_id,notnull,type:varchar(20)" json:"templateId"`
Version int `bun:"version,notnull" json:"version"` // Version number
Subject string `bun:"subject" json:"subject,omitempty"`
Body string `bun:"body,notnull" json:"body"`
Variables []string `bun:"variables,array" json:"variables"`
Changes string `bun:"changes" json:"changes,omitempty"` // Description of what changed
ChangedBy *xid.ID `bun:"changed_by,type:varchar(20)" json:"changedBy,omitempty"` // User who made the change
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
RestoredAt *time.Time `bun:"restored_at" json:"restoredAt,omitempty"` // When this version was restored (if ever)
// Relations
Template *NotificationTemplate `bun:"rel:belongs-to,join:template_id=id" json:"template,omitempty"`
User *User `bun:"rel:belongs-to,join:changed_by=id" json:"user,omitempty"`
}
NotificationTemplateVersion represents a version snapshot of a notification template
type NotificationTest ¶
type NotificationTest struct {
bun.BaseModel `bun:"table:notification_tests,alias:ntest"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
TemplateID xid.ID `bun:"template_id,notnull,type:varchar(20)" json:"templateId"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationId,omitempty"`
TestType string `bun:"test_type,notnull" json:"testType"` // preview, send, bulk
Recipients []string `bun:"recipients,array" json:"recipients"` // Test recipient(s)
Variables map[string]interface{} `bun:"variables,type:jsonb" json:"variables,omitempty"` // Test variables
Results map[string]interface{} `bun:"results,type:jsonb" json:"results,omitempty"` // Test results (success/failure for each recipient)
Status string `bun:"status,notnull,default:'pending'" json:"status"` // pending, running, completed, failed, partial
Error string `bun:"error" json:"error,omitempty"` // Error message if failed
SuccessCount int `bun:"success_count,notnull,default:0" json:"successCount"`
FailureCount int `bun:"failure_count,notnull,default:0" json:"failureCount"`
CreatedBy *xid.ID `bun:"created_by,type:varchar(20)" json:"createdBy,omitempty"` // User who initiated the test
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
CompletedAt *time.Time `bun:"completed_at" json:"completedAt,omitempty"`
// Relations
Template *NotificationTemplate `bun:"rel:belongs-to,join:template_id=id" json:"template,omitempty"`
App *App `bun:"rel:belongs-to,join:app_id=id" json:"app,omitempty"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"`
User *User `bun:"rel:belongs-to,join:created_by=id" json:"user,omitempty"`
}
NotificationTest represents a test execution for notification templates
type NotificationTestStatus ¶
type NotificationTestStatus string
NotificationTestStatus represents the test execution status
const ( NotificationTestStatusPending NotificationTestStatus = "pending" // Test queued NotificationTestStatusRunning NotificationTestStatus = "running" // Test in progress NotificationTestStatusCompleted NotificationTestStatus = "completed" // Test completed successfully NotificationTestStatusFailed NotificationTestStatus = "failed" // Test failed NotificationTestStatusPartial NotificationTestStatus = "partial" // Some tests succeeded, some failed )
type NotificationTestType ¶
type NotificationTestType string
NotificationTestType represents the type of test being performed
const ( NotificationTestTypePreview NotificationTestType = "preview" // Template preview/render test NotificationTestTypeSend NotificationTestType = "send" // Single test send NotificationTestTypeBulk NotificationTestType = "bulk" // Bulk test with multiple recipients )
type OAuthClient ¶
type OAuthClient struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:oauth_clients,alias:oc"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"`
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environmentID"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationID,omitempty"` // null = app-level
Name string `bun:"name,notnull" json:"name"`
ClientID string `bun:"client_id,notnull,unique" json:"clientID"`
ClientSecret string `bun:"client_secret,notnull" json:"-"`
// OAuth2/OIDC Configuration
RedirectURI string `bun:"redirect_uri,notnull" json:"redirectURI"` // Legacy single URI, kept for backward compatibility
RedirectURIs []string `bun:"redirect_uris,array,type:text[]" json:"redirectURIs"`
PostLogoutRedirectURIs []string `bun:"post_logout_redirect_uris,array,type:text[]" json:"postLogoutRedirectURIs,omitempty"`
GrantTypes []string `bun:"grant_types,array,type:text[]" json:"grantTypes"` // Default: ["authorization_code", "refresh_token"] - set in application code
ResponseTypes []string `bun:"response_types,array,type:text[]" json:"responseTypes"` // Default: ["code"] - set in application code
AllowedScopes []string `bun:"allowed_scopes,array,type:text[]" json:"allowedScopes,omitempty"`
// Client Authentication & Security
TokenEndpointAuthMethod string `bun:"token_endpoint_auth_method,default:'client_secret_basic'" json:"tokenEndpointAuthMethod"` // client_secret_basic, client_secret_post, none
ApplicationType string `bun:"application_type,default:'web'" json:"applicationType"` // web, native, spa
RequirePKCE bool `bun:"require_pkce,default:false" json:"requirePKCE"`
RequireConsent bool `bun:"require_consent,default:true" json:"requireConsent"`
TrustedClient bool `bun:"trusted_client,default:false" json:"trustedClient"`
// Client Metadata (RFC 7591)
LogoURI string `bun:"logo_uri" json:"logoURI,omitempty"`
PolicyURI string `bun:"policy_uri" json:"policyURI,omitempty"`
TosURI string `bun:"tos_uri" json:"tosURI,omitempty"`
Contacts []string `bun:"contacts,array,type:text[]" json:"contacts,omitempty"`
// Flexible metadata storage
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id"`
}
OAuthClient stores registered OAuth/OIDC clients
type OAuthConsent ¶
type OAuthConsent struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:oauth_consents,alias:oc"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"`
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environmentID"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationID,omitempty"` // Optional org context
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)" json:"userID"`
ClientID string `bun:"client_id,notnull" json:"clientID"`
// Consent details
Scopes []string `bun:"scopes,array,type:text[],notnull" json:"scopes"` // Granted scopes
ExpiresAt *time.Time `bun:"expires_at" json:"expiresAt,omitempty"` // Optional consent expiration
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id"`
User *User `bun:"rel:belongs-to,join:user_id=id"`
}
OAuthConsent stores persistent user consent decisions for OAuth clients
func (*OAuthConsent) HasScope ¶
func (oc *OAuthConsent) HasScope(scope string) bool
HasScope checks if a specific scope was granted
func (*OAuthConsent) IsExpired ¶
func (oc *OAuthConsent) IsExpired() bool
IsExpired checks if the consent has expired
func (*OAuthConsent) IsValid ¶
func (oc *OAuthConsent) IsValid() bool
IsValid checks if the consent is still valid
type OAuthToken ¶
type OAuthToken struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:oauth_tokens,alias:ot"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"`
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environmentID"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)" json:"organizationID,omitempty"` // Optional org context
SessionID *xid.ID `bun:"session_id,type:varchar(20)" json:"sessionID,omitempty"` // Linked session for lifecycle management
// Token fields
AccessToken string `bun:"access_token,unique,notnull" json:"-"` // The access token
RefreshToken string `bun:"refresh_token,unique" json:"-"` // Optional refresh token
IDToken string `bun:"id_token" json:"-"` // OIDC ID token
TokenType string `bun:"token_type,notnull,default:'Bearer'" json:"tokenType"` // Token type (Bearer)
TokenClass string `bun:"token_class,default:'access_token'" json:"tokenClass"` // access_token, refresh_token, id_token
ClientID string `bun:"client_id,notnull" json:"clientID"` // OAuth client ID
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)" json:"userID"` // User who owns the token
Scope string `bun:"scope,notnull" json:"scope"` // Granted scopes
// JWT Claims
JTI string `bun:"jti,unique" json:"jti,omitempty"` // JWT ID for token revocation by ID
Issuer string `bun:"issuer" json:"issuer,omitempty"` // Token issuer
Audience []string `bun:"audience,array,type:text[]" json:"audience,omitempty"` // Token audience (aud claim)
NotBefore *time.Time `bun:"not_before" json:"notBefore,omitempty"` // Token validity start time (nbf claim)
// Authentication context
AuthTime *time.Time `bun:"auth_time" json:"authTime,omitempty"` // When user authenticated
ACR string `bun:"acr" json:"acr,omitempty"` // Authentication context class reference
AMR []string `bun:"amr,array,type:text[]" json:"amr,omitempty"` // Authentication methods references
// Lifecycle
ExpiresAt time.Time `bun:"expires_at,notnull" json:"expiresAt"` // Token expiration
RefreshExpiresAt *time.Time `bun:"refresh_expires_at" json:"refreshExpiresAt,omitempty"` // Refresh token expiration
Revoked bool `bun:"revoked,notnull,default:false" json:"revoked"` // Whether token is revoked
RevokedAt *time.Time `bun:"revoked_at" json:"revokedAt,omitempty"` // When token was revoked
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id"`
Session *Session `bun:"rel:belongs-to,join:session_id=id"`
}
OAuthToken represents an OAuth2/OIDC access token
func (*OAuthToken) IsExpired ¶
func (ot *OAuthToken) IsExpired() bool
IsExpired checks if the access token has expired
func (*OAuthToken) IsRefreshValid ¶
func (ot *OAuthToken) IsRefreshValid() bool
IsRefreshValid checks if the refresh token is valid
func (*OAuthToken) IsValid ¶
func (ot *OAuthToken) IsValid() bool
IsValid checks if the access token is valid (not expired and not revoked)
type OTPCode ¶
type OTPCode struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:twofa_otpcodes,alias:toc"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"`
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
CodeHash string `bun:"code_hash,notnull"`
ExpiresAt time.Time `bun:"expires_at,notnull"`
Attempts int `bun:"attempts,notnull,default:0"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
OTPCode stores one-time codes for OTP-based 2FA
type Organization ¶
type Organization struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:organizations,alias:uo"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"`
EnvironmentID xid.ID `json:"environmentID" bun:"environment_id,notnull,type:varchar(20)"` // Foreign key to Environment
Name string `json:"name" bun:"name,notnull"`
Slug string `json:"slug" bun:"slug,notnull"` // Unique within app+environment
Logo string `json:"logo" bun:"logo"`
Metadata map[string]interface{} `json:"metadata" bun:"metadata,type:jsonb"`
CreatedBy xid.ID `json:"createdBy" bun:"created_by,notnull,type:varchar(20)"`
// Relations
App *App `json:"app" bun:"rel:belongs-to,join:app_id=id"`
Environment *Environment `json:"environment" bun:"rel:belongs-to,join:environment_id=id"`
}
Organization represents user-created organizations (Clerk-style workspaces) within an environment
type OrganizationInvitation ¶
type OrganizationInvitation struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:organization_invitations,alias:uoi"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
OrganizationID xid.ID `json:"organizationID" bun:"organization_id,notnull,type:varchar(20)"`
Email string `json:"email" bun:"email,notnull"`
Role string `json:"role" bun:"role,notnull"`
InviterID xid.ID `json:"inviterID" bun:"inviter_id,notnull,type:varchar(20)"`
Token string `json:"token" bun:"token,notnull,unique"`
ExpiresAt time.Time `json:"expiresAt" bun:"expires_at,notnull"`
AcceptedAt *time.Time `json:"acceptedAt" bun:"accepted_at"`
Status string `json:"status" bun:"status,notnull"` // pending, accepted, expired, cancelled
// Relations
Organization *Organization `json:"organization" bun:"rel:belongs-to,join:organization_id=id"`
}
OrganizationInvitation represents invitations to user-created organizations
type OrganizationMember ¶
type OrganizationMember struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:organization_members,alias:uom"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
OrganizationID xid.ID `json:"organizationID" bun:"organization_id,notnull,type:varchar(20)"`
UserID xid.ID `json:"userID" bun:"user_id,notnull,type:varchar(20)"`
Role string `json:"role" bun:"role,notnull"` // owner, admin, member
Status string `json:"status" bun:"status,notnull,default:'active'"` // active, suspended, pending
JoinedAt time.Time `json:"joinedAt" bun:"joined_at,nullzero,notnull,default:current_timestamp"`
// Relations
Organization *Organization `json:"organization" bun:"rel:belongs-to,join:organization_id=id"`
User *User `json:"user" bun:"rel:belongs-to,join:user_id=id"`
}
OrganizationMember represents membership in user-created organizations
type OrganizationTeam ¶
type OrganizationTeam struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:organization_teams,alias:uot"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
OrganizationID xid.ID `json:"organizationID" bun:"organization_id,notnull,type:varchar(20)"`
Name string `json:"name" bun:"name,notnull"`
Description string `json:"description" bun:"description"`
Metadata map[string]interface{} `json:"metadata" bun:"metadata,type:jsonb"`
// Provisioning tracking
ProvisionedBy *string `json:"provisionedBy,omitempty" bun:"provisioned_by,type:varchar(50)"` // e.g., "scim"
ExternalID *string `json:"externalID,omitempty" bun:"external_id,type:varchar(255)"` // External system ID
// Relations
Organization *Organization `json:"organization" bun:"rel:belongs-to,join:organization_id=id"`
}
OrganizationTeam represents teams within user-created organizations
type OrganizationTeamMember ¶
type OrganizationTeamMember struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:organization_team_members,alias:uotm"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
TeamID xid.ID `json:"teamID" bun:"team_id,notnull,type:varchar(20)"`
MemberID xid.ID `json:"memberID" bun:"member_id,notnull,type:varchar(20)"` // References OrganizationMember
JoinedAt time.Time `json:"joinedAt" bun:"joined_at,nullzero,notnull,default:current_timestamp"`
// Provisioning tracking
ProvisionedBy *string `json:"provisionedBy,omitempty" bun:"provisioned_by,type:varchar(50)"` // e.g., "scim"
// Relations
Team *OrganizationTeam `json:"team" bun:"rel:belongs-to,join:team_id=id"`
Member *OrganizationMember `json:"member" bun:"rel:belongs-to,join:member_id=id"`
}
OrganizationTeamMember represents team membership within user-created organizations
type Passkey ¶
type Passkey struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:passkeys,alias:pk"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
UserID xid.ID `json:"userId" bun:"user_id,notnull,type:varchar(20)"`
CredentialID string `json:"credentialId" bun:"credential_id,notnull,unique"`
// WebAuthn cryptographic fields
PublicKey []byte `json:"-" bun:"public_key,notnull"` // COSE encoded public key
AAGUID []byte `json:"aaguid,omitempty" bun:"aaguid"` // Authenticator AAGUID
SignCount uint32 `json:"signCount" bun:"sign_count,default:0"` // Counter for replay attack detection
// Authenticator metadata
AuthenticatorType string `json:"authenticatorType,omitempty" bun:"authenticator_type"` // "platform" or "cross-platform"
// User-friendly naming for device management
Name string `json:"name,omitempty" bun:"name"`
// Resident key / discoverable credential support
IsResidentKey bool `json:"isResidentKey" bun:"is_resident_key,default:false"`
// Usage tracking
LastUsedAt *time.Time `json:"lastUsedAt,omitempty" bun:"last_used_at"`
// Multi-tenant scoping (App → Environment → Organization)
AppID xid.ID `json:"appId" bun:"app_id,notnull,type:varchar(20)"` // Platform app (required)
UserOrganizationID *xid.ID `json:"userOrganizationId,omitempty" bun:"user_organization_id,type:varchar(20)"` // User-created org (optional)
}
Passkey stores WebAuthn/FIDO2 credentials Updated for V2 architecture: App → Environment → Organization Now includes full WebAuthn fields for production-ready implementation
type PasswordHistory ¶
type PasswordHistory struct {
bun.BaseModel `bun:"table:password_histories,alias:ph"`
ID xid.ID `bun:"type:varchar(20),pk" json:"id"`
UserID xid.ID `bun:"type:varchar(20),notnull" json:"user_id"`
PasswordHash string `bun:"type:text,notnull" json:"password_hash"`
CreatedAt time.Time `bun:"type:timestamptz,notnull,default:current_timestamp" json:"created_at"`
}
PasswordHistory tracks user password history to prevent password reuse
type Permission ¶
type Permission struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:permissions,alias:perm"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID *xid.ID `json:"appID" bun:"app_id,type:varchar(20)"` // App-scoped permissions
OrganizationID *xid.ID `json:"organizationID" bun:"organization_id,type:varchar(20)"` // Org-scoped permissions (NULL = app-level)
Name string `json:"name" bun:"name,notnull"`
Description string `json:"description" bun:"description"`
IsCustom bool `json:"isCustom" bun:"is_custom,notnull,default:false"` // Distinguishes custom from pre-defined permissions
Category string `json:"category" bun:"category"` // Groups permissions: "users", "settings", "content", etc.
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id"`
Roles []Role `bun:"m2m:role_permissions,join:Permission=Role"`
}
Permission table
type PhoneVerification ¶
type PhoneVerification struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:phone_verifications,alias:pver"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
Phone string `json:"phone" bun:"phone,notnull"`
Code string `json:"code" bun:"code,notnull"`
AppID xid.ID `json:"appId" bun:"app_id,notnull,type:varchar(20)"` // Platform app (required)
UserOrganizationID *xid.ID `json:"userOrganizationId,omitempty" bun:"user_organization_id,type:varchar(20)"` // User-created org (optional)
ExpiresAt time.Time `json:"expiresAt" bun:"expires_at,notnull"`
Attempts int `json:"attempts" bun:"attempts,notnull,default:0"`
}
PhoneVerification stores SMS verification codes Updated for V2 architecture: App → Environment → Organization
type Policy ¶
type Policy struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:policies,alias:pol"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
Expression string `bun:"expression,notnull"`
}
Policy stores RBAC policy expressions
type Role ¶
type Role struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:roles,alias:r"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID *xid.ID `bun:"app_id,type:varchar(20)"` // App-scoped roles
EnvironmentID *xid.ID `bun:"environment_id,type:varchar(20)"` // Environment-scoped roles
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)"` // Org-scoped roles (NULL = app-level template)
Name string `bun:"name,notnull"` // Slug/identifier (e.g., "workspace_owner")
DisplayName string `bun:"display_name,notnull"` // Human-readable name (e.g., "Workspace Owner")
Description string `bun:"description"`
IsTemplate bool `bun:"is_template,notnull,default:false"` // Marks roles as templates for cloning
IsOwnerRole bool `bun:"is_owner_role,notnull,default:false"` // Marks the default owner role for new orgs
TemplateID *xid.ID `bun:"template_id,type:varchar(20)"` // Tracks which template this role was cloned from
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id"`
Template *Role `bun:"rel:belongs-to,join:template_id=id"`
Permissions []Permission `bun:"m2m:role_permissions,join:Role=Permission"`
}
Role table
type RolePermission ¶
type RolePermission struct {
bun.BaseModel `bun:"table:role_permissions,alias:rp"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
RoleID xid.ID `bun:"role_id,notnull,type:varchar(20)"`
PermissionID xid.ID `bun:"permission_id,notnull,type:varchar(20)"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp"`
// Relations
Role *Role `bun:"rel:belongs-to,join:role_id=id"`
Permission *Permission `bun:"rel:belongs-to,join:permission_id=id"`
}
RolePermission represents the many-to-many relationship between roles and permissions
type SSOProvider ¶
type SSOProvider struct {
bun.BaseModel `bun:"table:sso_providers"`
ID xid.ID `bun:",pk"`
CreatedAt time.Time
UpdatedAt time.Time
// Multi-tenant scoping: App → Environment → Organization
AppID xid.ID `bun:",notnull"` // Platform tenant (required)
EnvironmentID xid.ID `bun:",notnull"` // Environment within app (required)
OrganizationID *xid.ID `bun:",nullzero"` // End-user workspace (optional for app-level providers)
ProviderID string `bun:",notnull"` // e.g., "okta-saml" or "google-oidc"
Type string `bun:",notnull"` // "saml" or "oidc"
Domain string // org domain match for auto-discovery
// Attribute mapping from SSO assertions to user fields
// Maps user field names to SSO attribute names
// Example: {"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"}
AttributeMapping map[string]string `bun:"type:jsonb"`
// SAML configuration
SAMLEntryPoint string // IdP SSO URL
SAMLIssuer string // IdP Entity ID
SAMLCert string // IdP signing certificate (PEM format)
// OIDC configuration
OIDCClientID string // OAuth2 client ID
OIDCClientSecret string // OAuth2 client secret
OIDCIssuer string // OIDC issuer URL (e.g., https://idp.example.com)
OIDCRedirectURI string // Callback URL for this provider
}
SSOProvider stores SSO provider configuration with multi-tenant scoping
type SecurityEvent ¶
type SecurityEvent struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:security_events,alias:se"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"`
UserID *xid.ID `bun:"user_id,type:varchar(20)"`
Type string `bun:"type,notnull"`
IPAddress string `bun:"ip_address"`
UserAgent string `bun:"user_agent"`
Geo string `bun:"geo"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
SecurityEvent represents the security_events table
type Session ¶
type Session struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:sessions,alias:s"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
Token string `bun:"token,notnull,unique"`
// App-centric context
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"`
EnvironmentID *xid.ID `bun:"environment_id,type:varchar(20)"`
OrganizationID *xid.ID `bun:"organization_id,type:varchar(20)"`
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
ExpiresAt time.Time `bun:"expires_at,notnull"`
IPAddress string `bun:"ip_address"`
UserAgent string `bun:"user_agent"`
// Refresh token support (Option 3)
RefreshToken *string `bun:"refresh_token,unique"` // Long-lived refresh token
RefreshTokenExpiresAt *time.Time `bun:"refresh_token_expires_at"` // Refresh token expiry
LastRefreshedAt *time.Time `bun:"last_refreshed_at"` // When was access token last refreshed
// Relations
User *User `bun:"rel:belongs-to,join:user_id=id"`
}
Session represents the session table
type SocialAccount ¶
type SocialAccount struct {
bun.BaseModel `bun:"table:social_accounts"`
ID xid.ID `bun:",pk"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
// User relationship
UserID xid.ID `bun:",notnull"`
User *User `bun:"rel:belongs-to,join:user_id=id"`
AppID xid.ID `bun:"app_id,notnull"` // Platform app (required)
UserOrganizationID *xid.ID `bun:"user_organization_id,type:varchar(20)"` // User-created org (optional)
// Provider information
Provider string `bun:",notnull"` // google, github, microsoft, etc.
ProviderID string `bun:",notnull"` // Provider's unique user ID
Email string `bun:""` // Email from provider (may differ from user.Email)
Name string `bun:""` // Display name from provider
Avatar string `bun:""` // Profile picture URL
// OAuth tokens
AccessToken string `bun:",notnull"` // Current access token
RefreshToken string `bun:""` // Refresh token (if provided)
TokenType string `bun:",notnull,default:'Bearer'"` // Token type
ExpiresAt *time.Time `bun:""` // Access token expiration
RefreshExpiresAt *time.Time `bun:""` // Refresh token expiration
Scope string `bun:""` // Granted scopes (comma-separated)
// ID Token (for OIDC providers)
IDToken string `bun:"type:text"` // Full ID token JWT
// Provider-specific data (JSON)
RawUserInfo string `bun:"type:jsonb"` // Raw user profile from provider
// Account status
Revoked bool `bun:",notnull,default:false"` // Whether tokens were revoked
RevokedAt *time.Time `bun:""` // When account was disconnected
}
SocialAccount links a user to an OAuth provider account
func (*SocialAccount) IsRefreshTokenValid ¶
func (sa *SocialAccount) IsRefreshTokenValid() bool
IsRefreshTokenValid checks if refresh token is valid
func (*SocialAccount) IsTokenExpired ¶
func (sa *SocialAccount) IsTokenExpired() bool
IsTokenExpired checks if the access token has expired
func (*SocialAccount) NeedsRefresh ¶
func (sa *SocialAccount) NeedsRefresh() bool
NeedsRefresh checks if the access token needs refreshing
type SocialProviderConfig ¶ added in v0.0.3
type SocialProviderConfig struct {
bun.BaseModel `bun:"table:social_provider_configs,alias:spc"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updatedAt"`
// Multi-tenant scoping: App → Environment
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appId"` // Platform tenant (required)
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environmentId"` // Environment within app (required)
// Provider identification
ProviderName string `bun:"provider_name,notnull" json:"providerName"` // google, github, microsoft, apple, facebook, discord, twitter, linkedin, spotify, twitch, dropbox, gitlab, line, reddit, slack, bitbucket, notion
// OAuth credentials
ClientID string `bun:"client_id,notnull" json:"clientId"` // OAuth client ID
ClientSecret string `bun:"client_secret,notnull" json:"-"` // OAuth client secret (encrypted, never exposed in JSON)
RedirectURL string `bun:"redirect_url" json:"redirectUrl,omitempty"` // Custom redirect URL (optional, defaults to system URL)
// OAuth scopes
Scopes []string `bun:"scopes,type:jsonb" json:"scopes"` // OAuth scopes to request
// Status
IsEnabled bool `bun:"is_enabled,notnull,default:false" json:"isEnabled"` // Whether provider is active for this environment
// Advanced provider-specific configuration
// Examples: accessType for Google ("offline"), prompt settings, custom endpoints
AdvancedConfig map[string]interface{} `bun:"advanced_config,type:jsonb" json:"advancedConfig,omitempty"`
// Metadata for UI/tracking
DisplayName string `bun:"display_name" json:"displayName,omitempty"` // Custom display name (optional)
Description string `bun:"description" json:"description,omitempty"` // Admin notes/description
// Soft delete
DeletedAt *time.Time `bun:"deleted_at,soft_delete,nullzero" json:"-"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id" json:"app,omitempty"`
Environment *Environment `bun:"rel:belongs-to,join:environment_id=id" json:"environment,omitempty"`
}
SocialProviderConfig stores OAuth provider configuration per app/environment This enables dashboard-based configuration of social providers instead of code-only config
func (*SocialProviderConfig) GetDisplayName ¶ added in v0.0.3
func (c *SocialProviderConfig) GetDisplayName() string
GetDisplayName returns the display name or provider name if not set
func (*SocialProviderConfig) GetEffectiveScopes ¶ added in v0.0.3
func (c *SocialProviderConfig) GetEffectiveScopes() []string
GetEffectiveScopes returns the configured scopes or defaults if empty
func (*SocialProviderConfig) HasCustomRedirectURL ¶ added in v0.0.3
func (c *SocialProviderConfig) HasCustomRedirectURL() bool
HasCustomRedirectURL returns true if a custom redirect URL is configured
func (*SocialProviderConfig) MaskClientSecret ¶ added in v0.0.3
func (c *SocialProviderConfig) MaskClientSecret() string
MaskClientSecret returns a masked version of the client secret for display
type StringArray ¶
type StringArray []string
StringArray is a helper type for storing arrays of strings
func (*StringArray) Scan ¶
func (s *StringArray) Scan(value interface{}) error
Scan implements sql.Scanner for StringArray
type Team ¶
type Team struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:teams,alias:t"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
AppID xid.ID `json:"appID" bun:"app_id,notnull,type:varchar(20)"` // App context
Name string `json:"name" bun:"name,notnull"`
Description string `json:"description" bun:"description"`
Metadata map[string]interface{} `json:"metadata" bun:"metadata,type:jsonb"`
// Provisioning tracking
ProvisionedBy *string `json:"provisionedBy,omitempty" bun:"provisioned_by,type:varchar(50)"` // e.g., "scim"
ExternalID *string `json:"externalID,omitempty" bun:"external_id,type:varchar(255)"` // External system ID
// Relations
App *App `json:"app,omitempty" bun:"rel:belongs-to,join:app_id=id"`
Members []Member `json:"members,omitempty" bun:"m2m:team_members,join:Team=Member"`
}
Team represents the team table (belongs to App)
type TeamMember ¶
type TeamMember struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:team_members,alias:tm"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
TeamID xid.ID `bun:"team_id,notnull,type:varchar(20)"`
MemberID xid.ID `bun:"member_id,notnull,type:varchar(20)"`
// Provisioning tracking
ProvisionedBy *string `json:"provisionedBy,omitempty" bun:"provisioned_by,type:varchar(50)"` // e.g., "scim"
// Relations
Team *Team `bun:"rel:belongs-to,join:team_id=id"`
Member *Member `bun:"rel:belongs-to,join:member_id=id"`
}
TeamMember represents the team_members table
type TrustedDevice ¶
type TrustedDevice struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:trusted_devices,alias:td"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"`
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
DeviceID string `bun:"device_id,notnull"`
ExpiresAt time.Time `bun:"expires_at,notnull"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
TrustedDevice allows skipping 2FA for a period
type TwoFASecret ¶
type TwoFASecret struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:twofa_secrets,alias:tfs"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"`
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
Method string `bun:"method,notnull"` // totp or otp
Secret string `bun:"secret"`
Enabled bool `bun:"enabled,notnull,default:false"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
}
TwoFASecret stores per-user 2FA secret data
type UsageEvent ¶
type UsageEvent struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:usage_events,alias:ue"`
ID xid.ID `json:"id" bun:"id,pk,type:varchar(20)"`
UserID *xid.ID `json:"userId,omitempty" bun:"user_id,type:varchar(20)"`
OrganizationID *xid.ID `json:"organizationId,omitempty" bun:"organization_id,type:varchar(20)"`
SessionID *xid.ID `json:"sessionId,omitempty" bun:"session_id,type:varchar(20)"`
APIKeyID *xid.ID `json:"apiKeyId,omitempty" bun:"api_key_id,type:varchar(20)"`
// Request details
Method string `json:"method" bun:"method,notnull"`
Path string `json:"path" bun:"path,notnull"`
Endpoint string `json:"endpoint" bun:"endpoint"` // Normalized endpoint
StatusCode int `json:"statusCode" bun:"status_code"`
// Authentication context
AuthMethod string `json:"authMethod,omitempty" bun:"auth_method"` // session, apikey, jwt, anonymous
// Network information
IPAddress string `json:"ipAddress,omitempty" bun:"ip_address"`
UserAgent string `json:"userAgent,omitempty" bun:"user_agent,type:text"`
Country string `json:"country,omitempty" bun:"country"`
City string `json:"city,omitempty" bun:"city"`
// Performance metrics
ResponseTimeMs int64 `json:"responseTimeMs" bun:"response_time_ms"`
RequestSize int64 `json:"requestSize" bun:"request_size"`
ResponseSize int64 `json:"responseSize" bun:"response_size"`
// Feature tracking
Plugin string `json:"plugin,omitempty" bun:"plugin"`
Feature string `json:"feature,omitempty" bun:"feature"`
// Error tracking
Error string `json:"error,omitempty" bun:"error,type:text"`
ErrorCode string `json:"errorCode,omitempty" bun:"error_code"`
// Metadata
Metadata string `json:"metadata,omitempty" bun:"metadata,type:text"` // JSON string
}
UsageEvent represents the usage_events table for tracking API usage Note: Indexes should be created in migrations for the following columns: user_id, organization_id, session_id, api_key_id, method, endpoint, status_code, auth_method, country, plugin, feature
type User ¶
type User struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:users,alias:u"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID *xid.ID `bun:"app_id,type:varchar(20),notnull"` // App association (required in new architecture)
Email string `bun:"email,notnull"` // Unique per app, not globally
EmailVerified bool `bun:"email_verified,notnull,default:false"`
EmailVerifiedAt *time.Time `bun:"email_verified_at"`
Name string `bun:"name"`
Image string `bun:"image"`
PasswordHash string `bun:"password_hash"`
// Username support (Phase 6)
Username string `bun:"username,unique"`
DisplayUsername string `bun:"display_username"`
// Soft delete
DeletedAt *time.Time `bun:"deleted_at"`
}
User represents the user table In the new architecture: - Users are app-scoped (can exist in multiple apps with different IDs) - Same email can exist across different apps - Unique constraint is on (app_id, email) combination - User membership to apps is managed via the Member table in app service
type UserBan ¶
type UserBan struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:user_bans,alias:ub"`
// Primary key
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
// App context
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"appID"`
// Foreign keys
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)" json:"userID"`
BannedByID xid.ID `bun:"banned_by_id,notnull,type:varchar(20)" json:"bannedByID"`
UnbannedByID *xid.ID `bun:"unbanned_by_id,type:varchar(20)" json:"unbannedByID,omitempty"`
// Ban details
Reason string `bun:"reason,notnull" json:"reason"`
IsActive bool `bun:"is_active,notnull,default:true" json:"isActive"`
ExpiresAt *time.Time `bun:"expires_at" json:"expiresAt,omitempty"`
// Timestamps
UnbannedAt *time.Time `bun:"unbanned_at" json:"unbannedAt,omitempty"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
User *User `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
BannedBy *User `bun:"rel:belongs-to,join:banned_by_id=id" json:"bannedBy,omitempty"`
UnbannedBy *User `bun:"rel:belongs-to,join:unbanned_by_id=id" json:"unbannedBy,omitempty"`
}
UserBan represents a user ban record in the database
func (*UserBan) IsCurrentlyActive ¶
IsCurrentlyActive checks if the ban is currently active
type UserRole ¶
type UserRole struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:user_roles,alias:ur"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
RoleID xid.ID `bun:"role_id,notnull,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"` // App context for role assignment
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
User *User `bun:"rel:belongs-to,join:user_id=id"`
Role *Role `bun:"rel:belongs-to,join:role_id=id"`
}
UserRole maps users to roles within an app
type UserVerificationStatus ¶
type UserVerificationStatus struct {
bun.BaseModel `bun:"table:user_verification_status,alias:uvs"`
ID string `bun:"id,pk,type:varchar(255)" json:"id"`
// V2 Multi-tenant context (App → Environment → Organization)
AppID string `bun:"app_id,notnull,type:varchar(20)" json:"appId"`
EnvironmentID *string `bun:"environment_id,type:varchar(20)" json:"environmentId,omitempty"`
OrganizationID string `bun:"organization_id,notnull,type:varchar(20)" json:"organizationId"`
UserID string `bun:"user_id,notnull,type:varchar(20)" json:"userId"`
// Overall verification status
IsVerified bool `bun:"is_verified,default:false" json:"isVerified"`
VerificationLevel string `bun:"verification_level,type:varchar(50)" json:"verificationLevel"` // none, basic, enhanced, full
LastVerifiedAt *time.Time `bun:"last_verified_at,type:timestamptz" json:"lastVerifiedAt,omitempty"`
VerificationExpiry *time.Time `bun:"verification_expiry,type:timestamptz" json:"verificationExpiry,omitempty"`
RequiresReverification bool `bun:"requires_reverification,default:false" json:"requiresReverification"`
// Individual check statuses
DocumentVerified bool `bun:"document_verified,default:false" json:"documentVerified"`
LivenessVerified bool `bun:"liveness_verified,default:false" json:"livenessVerified"`
AgeVerified bool `bun:"age_verified,default:false" json:"ageVerified"`
AMLScreened bool `bun:"aml_screened,default:false" json:"amlScreened"`
AMLClear bool `bun:"aml_clear,default:false" json:"amlClear"`
// Most recent verification IDs
LastDocumentVerificationID string `bun:"last_document_verification_id,type:varchar(255)" json:"lastDocumentVerificationId,omitempty"`
LastLivenessVerificationID string `bun:"last_liveness_verification_id,type:varchar(255)" json:"lastLivenessVerificationId,omitempty"`
LastAMLVerificationID string `bun:"last_aml_verification_id,type:varchar(255)" json:"lastAMLVerificationId,omitempty"`
// Risk assessment
OverallRiskLevel string `bun:"overall_risk_level,type:varchar(20)" json:"overallRiskLevel"` // low, medium, high
RiskFactors []string `bun:"risk_factors,type:jsonb" json:"riskFactors,omitempty"`
// Compliance flags
IsBlocked bool `bun:"is_blocked,default:false" json:"isBlocked"`
BlockReason string `bun:"block_reason,type:text" json:"blockReason,omitempty"`
BlockedAt *time.Time `bun:"blocked_at,type:timestamptz" json:"blockedAt,omitempty"`
// Metadata
Metadata map[string]interface{} `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp" json:"updatedAt"`
// Relations
User *User `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
Organization *Organization `bun:"rel:belongs-to,join:organization_id=id" json:"organization,omitempty"`
}
UserVerificationStatus tracks the overall verification status of a user
type Verification ¶
type Verification struct {
AuditableModel `bun:",inline"`
bun.BaseModel `bun:"table:verifications,alias:v"`
ID xid.ID `bun:"id,pk,type:varchar(20)"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)"`
UserID xid.ID `bun:"user_id,notnull,type:varchar(20)"`
Token string `bun:"token,notnull,unique"`
Code string `bun:"code"` // 6-digit numeric code for mobile-friendly verification
Type string `bun:"type,notnull"` // email, phone, password_reset
ExpiresAt time.Time `bun:"expires_at,notnull"`
Used bool `bun:"used,notnull,default:false"`
UsedAt *time.Time `bun:"used_at"`
// Relations
App *App `bun:"rel:belongs-to,join:app_id=id"`
User *User `bun:"rel:belongs-to,join:user_id=id"`
}
Verification represents email/phone verification tokens
type Webhook ¶
type Webhook struct {
bun.BaseModel `bun:"table:webhooks,alias:w"`
ID xid.ID `bun:"id,pk,type:varchar(20)" json:"id"`
AppID xid.ID `bun:"app_id,notnull,type:varchar(20)" json:"app_id"`
EnvironmentID xid.ID `bun:"environment_id,notnull,type:varchar(20)" json:"environment_id"`
URL string `bun:"url,notnull" json:"url"`
Events []string `bun:"events,array" json:"events"`
Secret string `bun:"secret,notnull" json:"-"`
Enabled bool `bun:"enabled,notnull,default:true" json:"enabled"`
MaxRetries int `bun:"max_retries,notnull,default:3" json:"max_retries"`
RetryBackoff string `bun:"retry_backoff,notnull,default:'exponential'" json:"retry_backoff"`
Headers map[string]string `bun:"headers,type:jsonb" json:"headers,omitempty"`
Metadata map[string]string `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
LastDelivery *time.Time `bun:"last_delivery" json:"last_delivery,omitempty"`
FailureCount int `bun:"failure_count,notnull,default:0" json:"failure_count"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
DeletedAt *time.Time `bun:"deleted_at,soft_delete,nullzero" json:"-"`
}
Webhook represents a webhook subscription
Source Files
¶
- account.go
- account_lockout.go
- apikey.go
- apikey_role.go
- app.go
- audit.go
- authorization_code.go
- base.go
- device.go
- emailotp.go
- environment.go
- failed_login_attempt.go
- form.go
- identity_verification.go
- impersonation.go
- invitation.go
- jwt_key.go
- magiclink.go
- member.go
- mfa.go
- notification.go
- notification_analytics.go
- notification_provider.go
- notification_queue.go
- notification_template_version.go
- notificationtest.go
- oauth_client.go
- oauth_consent.go
- oauth_token.go
- organization.go
- organization_enums.go
- passkey.go
- password_history.go
- permission.go
- phone.go
- policy.go
- role.go
- role_permission.go
- security_event.go
- session.go
- social_account.go
- social_provider_config.go
- sso_provider.go
- team.go
- team_member.go
- twofa.go
- usage.go
- user.go
- user_ban.go
- user_role.go
- verification.go
- webhook.go