audit

package
v0.0.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 4, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CodeAuditEventNotFound     = "AUDIT_EVENT_NOT_FOUND"
	CodeAuditEventCreateFailed = "AUDIT_EVENT_CREATE_FAILED"
	CodeInvalidFilter          = "AUDIT_INVALID_FILTER"
	CodeInvalidTimeRange       = "AUDIT_INVALID_TIME_RANGE"
	CodeInvalidPagination      = "AUDIT_INVALID_PAGINATION"
	CodeQueryFailed            = "AUDIT_QUERY_FAILED"
)

Error codes for audit operations

Variables

This section is empty.

Functions

func AuditEventCreateFailed

func AuditEventCreateFailed(err error) *errs.AuthsomeError

AuditEventCreateFailed returns an error when creating an audit event fails

func AuditEventNotFound

func AuditEventNotFound(id string) *errs.AuthsomeError

AuditEventNotFound returns an error when an audit event is not found

func InvalidFilter

func InvalidFilter(field, reason string) *errs.AuthsomeError

InvalidFilter returns an error when filter parameters are invalid

func InvalidPagination

func InvalidPagination(reason string) *errs.AuthsomeError

InvalidPagination returns an error when pagination parameters are invalid

func InvalidTimeRange

func InvalidTimeRange(reason string) *errs.AuthsomeError

InvalidTimeRange returns an error when the time range is invalid

func QueryFailed

func QueryFailed(operation string, err error) *errs.AuthsomeError

QueryFailed returns an error when a query operation fails

Types

type ActionStatistic added in v0.0.9

type ActionStatistic struct {
	Action        string    `json:"action"`
	Count         int64     `json:"count"`
	FirstOccurred time.Time `json:"firstOccurred"`
	LastOccurred  time.Time `json:"lastOccurred"`
}

ActionStatistic represents aggregated statistics for an action

type ActionUserStatistic added in v0.0.9

type ActionUserStatistic struct {
	Action string  `json:"action"`
	UserID *xid.ID `json:"userId"`
	Count  int64   `json:"count"`
}

ActionUserStatistic represents statistics for action-user combinations

type ActivitySummary added in v0.0.9

type ActivitySummary struct {
	// Total counts
	TotalEvents int64 `json:"totalEvents"`
	UniqueUsers int64 `json:"uniqueUsers"`
	UniqueIPs   int64 `json:"uniqueIps"`

	// Top N breakdowns
	TopActions   []*ActionStatistic   `json:"topActions"`
	TopResources []*ResourceStatistic `json:"topResources"`
	TopUsers     []*UserStatistic     `json:"topUsers"`
	TopIPs       []*IPStatistic       `json:"topIps"`

	// Temporal breakdown
	HourlyBreakdown []*HourStatistic `json:"hourlyBreakdown"`
	DailyBreakdown  []*DayStatistic  `json:"dailyBreakdown"`

	// Filter used for this summary
	Filter *StatisticsFilter `json:"filter,omitempty"`
}

ActivitySummary provides a comprehensive dashboard summary

type AnalyticsService added in v0.0.7

type AnalyticsService struct {
	// contains filtered or unexported fields
}

AnalyticsService provides advanced security analytics

func NewAnalyticsService added in v0.0.7

func NewAnalyticsService(repo Repository) *AnalyticsService

NewAnalyticsService creates a new analytics service

type Anomaly added in v0.0.7

type Anomaly struct {
	Type        string                 `json:"type"`     // geo_velocity, unusual_action, frequency_spike, etc.
	Severity    string                 `json:"severity"` // low, medium, high, critical
	Score       float64                `json:"score"`    // 0-100
	Event       *Event                 `json:"event"`
	Baseline    *Baseline              `json:"baseline,omitempty"`
	Description string                 `json:"description"`
	Evidence    map[string]interface{} `json:"evidence"`
	DetectedAt  time.Time              `json:"detectedAt"`
}

Anomaly represents a detected anomaly

type AnomalyDetector added in v0.0.7

type AnomalyDetector struct {
	// contains filtered or unexported fields
}

AnomalyDetector detects anomalies in audit events

func NewAnomalyDetector added in v0.0.7

func NewAnomalyDetector() *AnomalyDetector

NewAnomalyDetector creates a new anomaly detector

func (*AnomalyDetector) DetectAnomalies added in v0.0.7

func (ad *AnomalyDetector) DetectAnomalies(ctx context.Context, event *Event, baseline *Baseline) ([]*Anomaly, error)

DetectAnomalies detects anomalies in an event against baseline

func (*AnomalyDetector) SetBaselineCalculator added in v0.0.7

func (ad *AnomalyDetector) SetBaselineCalculator(calc *BaselineCalculator)

SetBaselineCalculator sets the baseline calculator

type AuditProvider added in v0.0.7

type AuditProvider interface {
	// OnEvent is called when an audit event is created
	OnEvent(ctx context.Context, event *Event) error

	// Healthy checks if the provider is operational
	Healthy(ctx context.Context) error
}

AuditProvider allows external systems to receive audit events Useful for forwarding to SIEM, analytics engines, etc.

type Baseline added in v0.0.7

type Baseline struct {
	UserID           xid.ID                 `json:"userId"`
	OrganizationID   *xid.ID                `json:"organizationId,omitempty"` // Optional org scope
	Period           time.Duration          `json:"period"`
	EventsPerHour    float64                `json:"eventsPerHour"`
	TopActions       map[string]int         `json:"topActions"`
	TopResources     map[string]int         `json:"topResources"`
	TopLocations     []string               `json:"topLocations"`
	TypicalHours     []int                  `json:"typicalHours"` // Hours of day (0-23)
	TypicalDays      []time.Weekday         `json:"typicalDays"`  // Days of week
	UniqueIPCount    int                    `json:"uniqueIpCount"`
	AvgSessionLength time.Duration          `json:"avgSessionLength"`
	CalculatedAt     time.Time              `json:"calculatedAt"`
	Metadata         map[string]interface{} `json:"metadata"`
}

Baseline represents statistical baseline for user behavior

type BaselineCache added in v0.0.7

type BaselineCache struct {
	// contains filtered or unexported fields
}

BaselineCache caches user baselines in memory

func NewBaselineCache added in v0.0.7

func NewBaselineCache() *BaselineCache

NewBaselineCache creates a new baseline cache

func (*BaselineCache) Get added in v0.0.7

func (bc *BaselineCache) Get(userID xid.ID) (*Baseline, bool)

Get retrieves a baseline from cache

func (*BaselineCache) Set added in v0.0.7

func (bc *BaselineCache) Set(userID xid.ID, baseline *Baseline)

Set stores a baseline in cache

type BaselineCalculator added in v0.0.7

type BaselineCalculator struct {
	// contains filtered or unexported fields
}

BaselineCalculator calculates behavioral baselines

func NewBaselineCalculator added in v0.0.7

func NewBaselineCalculator(repo Repository) *BaselineCalculator

NewBaselineCalculator creates a new baseline calculator

func (*BaselineCalculator) Calculate added in v0.0.7

func (bc *BaselineCalculator) Calculate(ctx context.Context, userID xid.ID, period time.Duration) (*Baseline, error)

Calculate calculates baseline for a user over a period

func (*BaselineCalculator) CalculateWithOptions added in v0.0.9

func (bc *BaselineCalculator) CalculateWithOptions(ctx context.Context, userID xid.ID, period time.Duration, organizationID *xid.ID) (*Baseline, error)

CalculateWithOptions calculates baseline for a user over a period with optional organization scope

type ClientStats added in v0.0.7

type ClientStats struct {
	ID         string        `json:"id"`
	BufferSize int           `json:"bufferSize"`
	Connected  time.Duration `json:"connected"`
}

ClientStats contains per-client statistics

type CountEventsRequest added in v0.0.9

type CountEventsRequest struct {
	Filter *ListEventsFilter `json:"filter,omitempty"`
}

CountEventsRequest represents a request to count audit events

type CountEventsResponse added in v0.0.9

type CountEventsResponse struct {
	Count int64 `json:"count"`
}

CountEventsResponse represents the response for counting audit events

type CreateEventRequest

type CreateEventRequest struct {
	AppID          xid.ID  `json:"appId,omitempty"`          // Optional - will be read from context if not provided
	OrganizationID *xid.ID `json:"organizationId,omitempty"` // Optional - user-created organization
	EnvironmentID  *xid.ID `json:"environmentId,omitempty"`  // Optional - will be read from context if not provided
	UserID         *xid.ID `json:"userId,omitempty"`
	Action         string  `json:"action" validate:"required"`
	Resource       string  `json:"resource" validate:"required"`
	IPAddress      string  `json:"ipAddress,omitempty"`
	UserAgent      string  `json:"userAgent,omitempty"`
	Metadata       string  `json:"metadata,omitempty"`
}

CreateEventRequest represents a request to create an audit event

type CreateEventResponse

type CreateEventResponse struct {
	Event *Event `json:"event"`
}

CreateEventResponse represents the response after creating an audit event

type DateStatistic added in v0.0.9

type DateStatistic struct {
	Date  string `json:"date"` // YYYY-MM-DD format
	Count int64  `json:"count"`
}

DateStatistic represents event count for a specific date

type DayStatistic added in v0.0.9

type DayStatistic struct {
	Day      string `json:"day"`      // Monday, Tuesday, etc.
	DayIndex int    `json:"dayIndex"` // 0=Sunday, 1=Monday, etc.
	Count    int64  `json:"count"`
}

DayStatistic represents event count for a specific day of week

type DeleteFilter added in v0.0.9

type DeleteFilter struct {
	// Filter by app
	AppID *xid.ID `json:"appId,omitempty"`

	// Filter by organization
	OrganizationID *xid.ID `json:"organizationId,omitempty"`

	// Filter by environment
	EnvironmentID *xid.ID `json:"environmentId,omitempty"`

	// Filter by user
	UserID *xid.ID `json:"userId,omitempty"`

	// Filter by action
	Action *string `json:"action,omitempty"`

	// Filter by resource
	Resource *string `json:"resource,omitempty"`

	// Metadata filters
	MetadataFilters []MetadataFilter `json:"metadataFilters,omitempty"`
}

DeleteFilter defines filters for delete operations (subset of ListEventsFilter)

type DeleteOlderThanRequest added in v0.0.9

type DeleteOlderThanRequest struct {
	Before time.Time     `json:"before" validate:"required"`
	Filter *DeleteFilter `json:"filter,omitempty"`
}

DeleteOlderThanRequest represents a request to delete old audit events

type DeleteOlderThanResponse added in v0.0.9

type DeleteOlderThanResponse struct {
	DeletedCount int64 `json:"deletedCount"`
}

DeleteOlderThanResponse represents the response for deleting audit events

type Event

type Event struct {
	ID             xid.ID    `json:"id"`
	AppID          xid.ID    `json:"appId"`
	OrganizationID *xid.ID   `json:"organizationId,omitempty"`
	EnvironmentID  *xid.ID   `json:"environmentId,omitempty"`
	UserID         *xid.ID   `json:"userId,omitempty"`
	Action         string    `json:"action"`
	Resource       string    `json:"resource"`
	IPAddress      string    `json:"ipAddress,omitempty"`
	UserAgent      string    `json:"userAgent,omitempty"`
	Metadata       string    `json:"metadata,omitempty"` // JSON string or plain text
	CreatedAt      time.Time `json:"createdAt"`
	UpdatedAt      time.Time `json:"updatedAt"`
}

Event represents an audit trail record DTO This is separate from schema.AuditEvent to maintain proper separation of concerns

func FromSchemaEvent

func FromSchemaEvent(ae *schema.AuditEvent) *Event

FromSchemaEvent converts a schema.AuditEvent model to Event DTO

func FromSchemaEvents

func FromSchemaEvents(events []*schema.AuditEvent) []*Event

FromSchemaEvents converts a slice of schema.AuditEvent to Event DTOs

func (*Event) ToSchema

func (e *Event) ToSchema() *schema.AuditEvent

ToSchema converts the Event DTO to a schema.AuditEvent model

type GenericOrganization added in v0.0.7

type GenericOrganization struct {
	ID          string                 `json:"id"`
	Name        string                 `json:"name"`
	DisplayName string                 `json:"displayName,omitempty"`
	Status      string                 `json:"status"` // "active", "suspended", "deleted"
	ParentID    *string                `json:"parentId,omitempty"`
	Members     int                    `json:"members"`
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
	CreatedAt   time.Time              `json:"createdAt"`
	UpdatedAt   time.Time              `json:"updatedAt"`
}

GenericOrganization represents an organization/tenant from any system

type GenericUser added in v0.0.7

type GenericUser struct {
	ID               string                 `json:"id"`
	Email            string                 `json:"email"`
	Username         string                 `json:"username,omitempty"`
	DisplayName      string                 `json:"displayName,omitempty"`
	MFAEnabled       bool                   `json:"mfaEnabled"`
	MFAMethods       []string               `json:"mfaMethods"` // ["totp", "sms", "webauthn"]
	PasswordChanged  time.Time              `json:"passwordChanged"`
	LastLogin        time.Time              `json:"lastLogin"`
	LoginCount       int                    `json:"loginCount"`
	FailedLoginCount int                    `json:"failedLoginCount"`
	Status           string                 `json:"status"` // "active", "suspended", "deleted", "locked"
	Roles            []string               `json:"roles"`
	Groups           []string               `json:"groups,omitempty"`
	Metadata         map[string]interface{} `json:"metadata,omitempty"` // Extensible
	CreatedAt        time.Time              `json:"createdAt"`
	UpdatedAt        time.Time              `json:"updatedAt"`
}

GenericUser represents a user from any system

type GeoVelocityDetector added in v0.0.7

type GeoVelocityDetector struct {
}

GeoVelocityDetector detects impossible travel based on IP geolocation

func (*GeoVelocityDetector) DetectImpossibleTravel added in v0.0.7

func (gvd *GeoVelocityDetector) DetectImpossibleTravel(event1, event2 *Event) (*Anomaly, error)

DetectImpossibleTravel checks if travel between two locations is physically impossible

type GetEventRequest

type GetEventRequest struct {
	ID xid.ID `json:"id" validate:"required"`
}

GetEventRequest represents a request to get an audit event by ID

type GetEventResponse

type GetEventResponse struct {
	Event *Event `json:"event"`
}

GetEventResponse represents the response for getting an audit event

type GetGrowthRateResponse added in v0.0.9

type GetGrowthRateResponse struct {
	Metrics *GrowthMetrics    `json:"metrics"`
	Filter  *StatisticsFilter `json:"filter,omitempty"`
}

GetGrowthRateResponse wraps growth metrics

type GetOldestEventRequest added in v0.0.9

type GetOldestEventRequest struct {
	Filter *ListEventsFilter `json:"filter,omitempty"`
}

GetOldestEventRequest represents a request to get the oldest event

type GetOldestEventResponse added in v0.0.9

type GetOldestEventResponse struct {
	Event *Event `json:"event,omitempty"`
}

GetOldestEventResponse represents the response for the oldest event

type GetStatisticsByActionAndUserResponse added in v0.0.9

type GetStatisticsByActionAndUserResponse struct {
	Statistics []*ActionUserStatistic `json:"statistics"`
	Total      int64                  `json:"total"`
}

GetStatisticsByActionAndUserResponse wraps action-user statistics

type GetStatisticsByActionRequest added in v0.0.9

type GetStatisticsByActionRequest struct {
	Filter *StatisticsFilter `json:"filter,omitempty"`
}

GetStatisticsByActionRequest represents a request to get action statistics

type GetStatisticsByActionResponse added in v0.0.9

type GetStatisticsByActionResponse struct {
	Statistics []*ActionStatistic `json:"statistics"`
	Total      int64              `json:"total"`
}

GetStatisticsByActionResponse represents the response for action statistics

type GetStatisticsByDateResponse added in v0.0.9

type GetStatisticsByDateResponse struct {
	Statistics []*DateStatistic `json:"statistics"`
	Total      int64            `json:"total"`
}

GetStatisticsByDateResponse wraps date statistics

type GetStatisticsByDayResponse added in v0.0.9

type GetStatisticsByDayResponse struct {
	Statistics []*DayStatistic `json:"statistics"`
	Total      int64           `json:"total"`
}

GetStatisticsByDayResponse wraps day statistics

type GetStatisticsByHourResponse added in v0.0.9

type GetStatisticsByHourResponse struct {
	Statistics []*HourStatistic `json:"statistics"`
	Total      int64            `json:"total"`
}

GetStatisticsByHourResponse wraps hour statistics

type GetStatisticsByIPAddressResponse added in v0.0.9

type GetStatisticsByIPAddressResponse struct {
	Statistics []*IPStatistic `json:"statistics"`
	Total      int64          `json:"total"`
}

GetStatisticsByIPAddressResponse wraps IP statistics

type GetStatisticsByResourceAndActionResponse added in v0.0.9

type GetStatisticsByResourceAndActionResponse struct {
	Statistics []*ResourceActionStatistic `json:"statistics"`
	Total      int64                      `json:"total"`
}

GetStatisticsByResourceAndActionResponse wraps resource-action statistics

type GetStatisticsByResourceRequest added in v0.0.9

type GetStatisticsByResourceRequest struct {
	Filter *StatisticsFilter `json:"filter,omitempty"`
}

GetStatisticsByResourceRequest represents a request to get resource statistics

type GetStatisticsByResourceResponse added in v0.0.9

type GetStatisticsByResourceResponse struct {
	Statistics []*ResourceStatistic `json:"statistics"`
	Total      int64                `json:"total"`
}

GetStatisticsByResourceResponse represents the response for resource statistics

type GetStatisticsByUserRequest added in v0.0.9

type GetStatisticsByUserRequest struct {
	Filter *StatisticsFilter `json:"filter,omitempty"`
}

GetStatisticsByUserRequest represents a request to get user statistics

type GetStatisticsByUserResponse added in v0.0.9

type GetStatisticsByUserResponse struct {
	Statistics []*UserStatistic `json:"statistics"`
	Total      int64            `json:"total"`
}

GetStatisticsByUserResponse represents the response for user statistics

type GetTimeSeriesResponse added in v0.0.9

type GetTimeSeriesResponse struct {
	Points   []*TimeSeriesPoint `json:"points"`
	Interval TimeSeriesInterval `json:"interval"`
	Total    int64              `json:"total"`
}

GetTimeSeriesResponse wraps time series results

type GetTrendsResponse added in v0.0.9

type GetTrendsResponse struct {
	Events    *TrendData `json:"events"`
	Users     *TrendData `json:"users,omitempty"`
	Actions   *TrendData `json:"actions,omitempty"`
	Resources *TrendData `json:"resources,omitempty"`
}

GetTrendsResponse wraps trend analysis results

type GrowthMetrics added in v0.0.9

type GrowthMetrics struct {
	// Growth rates as percentage change
	DailyGrowth   float64 `json:"dailyGrowth"`   // vs yesterday
	WeeklyGrowth  float64 `json:"weeklyGrowth"`  // vs last week
	MonthlyGrowth float64 `json:"monthlyGrowth"` // vs last month

	// Absolute counts for context
	TodayCount     int64 `json:"todayCount"`
	YesterdayCount int64 `json:"yesterdayCount"`
	ThisWeekCount  int64 `json:"thisWeekCount"`
	LastWeekCount  int64 `json:"lastWeekCount"`
	ThisMonthCount int64 `json:"thisMonthCount"`
	LastMonthCount int64 `json:"lastMonthCount"`
}

GrowthMetrics provides growth rate analysis over multiple time windows

type HourStatistic added in v0.0.9

type HourStatistic struct {
	Hour  int   `json:"hour"` // 0-23
	Count int64 `json:"count"`
}

HourStatistic represents event count for a specific hour of day

type IPStatistic added in v0.0.9

type IPStatistic struct {
	IPAddress     string    `json:"ipAddress"`
	Count         int64     `json:"count"`
	FirstOccurred time.Time `json:"firstOccurred"`
	LastOccurred  time.Time `json:"lastOccurred"`
}

IPStatistic represents aggregated statistics for an IP address

type ListEventsFilter

type ListEventsFilter struct {
	pagination.PaginationParams

	// ========== Full-Text Search ==========
	// Full-text search query across action, resource, metadata
	SearchQuery *string `json:"searchQuery,omitempty" query:"q"`
	// Fields to search (empty = all fields)
	SearchFields []string `json:"searchFields,omitempty" query:"search_fields"`

	// ========== Exact Match Filters ==========
	// Filter by app
	AppID *xid.ID `json:"appId,omitempty" query:"app_id"`

	// Filter by organization (user-created org)
	OrganizationID *xid.ID `json:"organizationId,omitempty" query:"organization_id"`

	// Filter by environment
	EnvironmentID *xid.ID `json:"environmentId,omitempty" query:"environment_id"`

	// Filter by user (single)
	UserID *xid.ID `json:"userId,omitempty" query:"user_id"`

	// Filter by action (single, exact match)
	Action *string `json:"action,omitempty" query:"action"`

	// Filter by resource (single, exact match)
	Resource *string `json:"resource,omitempty" query:"resource"`

	// Filter by IP address (single, exact match)
	IPAddress *string `json:"ipAddress,omitempty" query:"ip_address"`

	// ========== Multiple Value Filters (IN clauses) ==========
	// Filter by multiple apps
	AppIDs []xid.ID `json:"appIds,omitempty" query:"app_ids"`

	// Filter by multiple organizations
	OrganizationIDs []xid.ID `json:"organizationIds,omitempty" query:"organization_ids"`

	// Filter by multiple users
	UserIDs []xid.ID `json:"userIds,omitempty" query:"user_ids"`

	// Filter by multiple actions
	Actions []string `json:"actions,omitempty" query:"actions"`

	// Filter by multiple resources
	Resources []string `json:"resources,omitempty" query:"resources"`

	// Filter by multiple IP addresses
	IPAddresses []string `json:"ipAddresses,omitempty" query:"ip_addresses"`

	// ========== Pattern Matching Filters (ILIKE) ==========
	// Action pattern match (use % for wildcards)
	ActionPattern *string `json:"actionPattern,omitempty" query:"action_pattern"`

	// Resource pattern match (use % for wildcards)
	ResourcePattern *string `json:"resourcePattern,omitempty" query:"resource_pattern"`

	// ========== IP Range Filtering ==========
	// IP range in CIDR notation (e.g., "192.168.1.0/24")
	IPRange *string `json:"ipRange,omitempty" query:"ip_range"`

	// ========== Metadata Filtering ==========
	// Metadata key-value filters (for structured metadata)
	MetadataFilters []MetadataFilter `json:"metadataFilters,omitempty" query:"metadata_filters"`

	// ========== Time Range Filters ==========
	Since *time.Time `json:"since,omitempty" query:"since"`
	Until *time.Time `json:"until,omitempty" query:"until"`

	// ========== Sort Order ==========
	SortBy    *string `json:"sortBy,omitempty" query:"sort_by"`       // created_at, action, resource, rank (for search)
	SortOrder *string `json:"sortOrder,omitempty" query:"sort_order"` // asc, desc
}

ListEventsFilter defines filters for listing audit events with pagination

type ListEventsResponse

type ListEventsResponse = pagination.PageResponse[*Event]

ListEventsResponse represents a paginated list of audit events

type MetadataFilter added in v0.0.8

type MetadataFilter struct {
	Key      string      `json:"key"`      // Metadata key to filter on
	Value    interface{} `json:"value"`    // Value to match
	Operator string      `json:"operator"` // equals, contains, exists, not_exists
}

MetadataFilter defines a filter for metadata field

type MetricsQuery added in v0.0.7

type MetricsQuery struct {
	Metrics     []string   `json:"metrics"` // ["total_users", "mfa_adoption", "inactive_users"]
	GroupBy     []string   `json:"groupBy,omitempty"`
	StartDate   *time.Time `json:"startDate,omitempty"`
	EndDate     *time.Time `json:"endDate,omitempty"`
	Granularity string     `json:"granularity,omitempty"` // "day", "week", "month"
}

MetricsQuery defines aggregated metrics to retrieve

type OrgFilter added in v0.0.7

type OrgFilter struct {
	IDs      []string `json:"ids,omitempty"`
	Status   *string  `json:"status,omitempty"`
	ParentID *string  `json:"parentId,omitempty"`
	Limit    int      `json:"limit"`
	Offset   int      `json:"offset"`
}

OrgFilter defines criteria for filtering organizations

type OrganizationProvider added in v0.0.7

type OrganizationProvider interface {
	// GetOrganization retrieves organization details
	GetOrganization(ctx context.Context, orgID string) (*GenericOrganization, error)

	// ListOrganizations retrieves organizations matching filter
	ListOrganizations(ctx context.Context, filter *OrgFilter) ([]*GenericOrganization, error)
}

OrganizationProvider provides access to organization/tenant data

type PollingStreamService added in v0.0.7

type PollingStreamService struct {
	// contains filtered or unexported fields
}

PollingStreamService provides streaming for SQLite using polling

func NewPollingStreamService added in v0.0.7

func NewPollingStreamService(repo Repository) *PollingStreamService

NewPollingStreamService creates a polling-based stream service (for SQLite)

func (*PollingStreamService) Shutdown added in v0.0.7

func (s *PollingStreamService) Shutdown()

func (*PollingStreamService) Subscribe added in v0.0.7

func (s *PollingStreamService) Subscribe(ctx context.Context, filter *StreamFilter) (<-chan *Event, string, error)

Subscribe creates a subscription (same interface as StreamService)

func (*PollingStreamService) Unsubscribe added in v0.0.7

func (s *PollingStreamService) Unsubscribe(clientID string)

type ProviderRegistry added in v0.0.7

type ProviderRegistry struct {
	// contains filtered or unexported fields
}

ProviderRegistry manages all provider instances

func NewProviderRegistry added in v0.0.7

func NewProviderRegistry() *ProviderRegistry

NewProviderRegistry creates a new provider registry

func (*ProviderRegistry) AddAuditProvider added in v0.0.7

func (r *ProviderRegistry) AddAuditProvider(provider AuditProvider)

AddAuditProvider registers an audit event consumer

func (*ProviderRegistry) GetAuditProviders added in v0.0.7

func (r *ProviderRegistry) GetAuditProviders() []AuditProvider

GetAuditProviders returns all registered audit providers

func (*ProviderRegistry) GetOrgProvider added in v0.0.7

func (r *ProviderRegistry) GetOrgProvider() OrganizationProvider

GetOrgProvider returns the registered organization provider

func (*ProviderRegistry) GetUserProvider added in v0.0.7

func (r *ProviderRegistry) GetUserProvider() UserProvider

GetUserProvider returns the registered user provider

func (*ProviderRegistry) NotifyAuditEvent added in v0.0.7

func (r *ProviderRegistry) NotifyAuditEvent(ctx context.Context, event *Event)

NotifyAuditEvent sends event to all audit providers (non-blocking)

func (*ProviderRegistry) SetOrgProvider added in v0.0.7

func (r *ProviderRegistry) SetOrgProvider(provider OrganizationProvider)

SetOrgProvider registers an organization provider

func (*ProviderRegistry) SetUserProvider added in v0.0.7

func (r *ProviderRegistry) SetUserProvider(provider UserProvider)

SetUserProvider registers a user provider

type Repository

type Repository interface {
	// Core CRUD operations
	Create(ctx context.Context, e *schema.AuditEvent) error
	Get(ctx context.Context, id xid.ID) (*schema.AuditEvent, error)
	List(ctx context.Context, filter *ListEventsFilter) (*pagination.PageResponse[*schema.AuditEvent], error)

	// Count operations
	Count(ctx context.Context, filter *ListEventsFilter) (int64, error)

	// Retention/cleanup operations
	DeleteOlderThan(ctx context.Context, filter *DeleteFilter, before time.Time) (int64, error)

	// Statistics/aggregation operations
	GetStatisticsByAction(ctx context.Context, filter *StatisticsFilter) ([]*ActionStatistic, error)
	GetStatisticsByResource(ctx context.Context, filter *StatisticsFilter) ([]*ResourceStatistic, error)
	GetStatisticsByUser(ctx context.Context, filter *StatisticsFilter) ([]*UserStatistic, error)

	// Time-based aggregation operations
	GetTimeSeries(ctx context.Context, filter *TimeSeriesFilter) ([]*TimeSeriesPoint, error)
	GetStatisticsByHour(ctx context.Context, filter *StatisticsFilter) ([]*HourStatistic, error)
	GetStatisticsByDay(ctx context.Context, filter *StatisticsFilter) ([]*DayStatistic, error)
	GetStatisticsByDate(ctx context.Context, filter *StatisticsFilter) ([]*DateStatistic, error)

	// IP/Network aggregation operations
	GetStatisticsByIPAddress(ctx context.Context, filter *StatisticsFilter) ([]*IPStatistic, error)
	GetUniqueIPCount(ctx context.Context, filter *StatisticsFilter) (int64, error)

	// Multi-dimensional aggregation operations
	GetStatisticsByActionAndUser(ctx context.Context, filter *StatisticsFilter) ([]*ActionUserStatistic, error)
	GetStatisticsByResourceAndAction(ctx context.Context, filter *StatisticsFilter) ([]*ResourceActionStatistic, error)

	// Utility operations
	GetOldestEvent(ctx context.Context, filter *ListEventsFilter) (*schema.AuditEvent, error)
}

Repository defines persistence for audit events

type ResourceActionStatistic added in v0.0.9

type ResourceActionStatistic struct {
	Resource string `json:"resource"`
	Action   string `json:"action"`
	Count    int64  `json:"count"`
}

ResourceActionStatistic represents statistics for resource-action combinations

type ResourceStatistic added in v0.0.9

type ResourceStatistic struct {
	Resource      string    `json:"resource"`
	Count         int64     `json:"count"`
	FirstOccurred time.Time `json:"firstOccurred"`
	LastOccurred  time.Time `json:"lastOccurred"`
}

ResourceStatistic represents aggregated statistics for a resource

type RiskEngine added in v0.0.7

type RiskEngine struct {
	// contains filtered or unexported fields
}

RiskEngine calculates risk scores for events

func NewRiskEngine added in v0.0.7

func NewRiskEngine() *RiskEngine

NewRiskEngine creates a new risk engine

func (*RiskEngine) Calculate added in v0.0.7

func (re *RiskEngine) Calculate(ctx context.Context, event *Event, anomalies []*Anomaly, baseline *Baseline) (*RiskScore, error)

Calculate calculates risk score for an event

type RiskScore added in v0.0.7

type RiskScore struct {
	Score        float64            `json:"score"` // 0-100
	Level        string             `json:"level"` // low, medium, high, critical
	Factors      map[string]float64 `json:"factors"`
	Anomalies    []*Anomaly         `json:"anomalies,omitempty"`
	Event        *Event             `json:"event"`
	CalculatedAt time.Time          `json:"calculatedAt"`
}

RiskScore represents a calculated risk score

type Scope added in v0.0.7

type Scope struct {
	Type     ScopeType `json:"type"`
	ID       string    `json:"id"`
	ParentID *string   `json:"parentId,omitempty"` // For inheritance
}

Scope represents a hierarchical compliance scope

type ScopeType added in v0.0.7

type ScopeType string

ScopeType defines the level of compliance scope

const (
	ScopeTypeSystem ScopeType = "system" // Global defaults
	ScopeTypeApp    ScopeType = "app"    // Customer/tenant level
	ScopeTypeOrg    ScopeType = "org"    // User-created workspace
	ScopeTypeTeam   ScopeType = "team"   // Department/team
	ScopeTypeRole   ScopeType = "role"   // Role-based (admin, user)
	ScopeTypeUser   ScopeType = "user"   // Individual user overrides
)

type SearchQuery added in v0.0.7

type SearchQuery struct {
	// Search query string (supports natural language and operators)
	Query string `json:"query"`

	// Fields to search in (empty = search all fields)
	Fields []string `json:"fields,omitempty"`

	// Enable fuzzy matching (stemming, similar words)
	FuzzyMatch bool `json:"fuzzyMatch"`

	// Pagination
	Limit  int `json:"limit"`
	Offset int `json:"offset"`

	// Standard filters (AND combined with search query)
	AppID          *xid.ID    `json:"appId,omitempty"`
	OrganizationID *xid.ID    `json:"organizationId,omitempty"` // Organization filtering (optional)
	EnvironmentID  *xid.ID    `json:"environmentId,omitempty"`  // Environment filtering
	UserID         *xid.ID    `json:"userId,omitempty"`
	Action         string     `json:"action,omitempty"`
	Since          *time.Time `json:"since,omitempty"`
	Until          *time.Time `json:"until,omitempty"`
}

SearchQuery represents a full-text search query with filters

type SearchQueryBuilder added in v0.0.7

type SearchQueryBuilder struct {
	// contains filtered or unexported fields
}

SearchQueryBuilder provides fluent API for building search queries

func NewSearchQuery added in v0.0.7

func NewSearchQuery(searchText string) *SearchQueryBuilder

NewSearchQuery creates a new search query builder

func (*SearchQueryBuilder) Build added in v0.0.7

func (b *SearchQueryBuilder) Build() *SearchQuery

Build returns the constructed query

func (*SearchQueryBuilder) ForApp added in v0.0.7

func (b *SearchQueryBuilder) ForApp(appID xid.ID) *SearchQueryBuilder

ForApp filters by app ID

func (*SearchQueryBuilder) ForEnvironment added in v0.0.9

func (b *SearchQueryBuilder) ForEnvironment(envID xid.ID) *SearchQueryBuilder

ForEnvironment filters by environment ID

func (*SearchQueryBuilder) ForOrganization added in v0.0.9

func (b *SearchQueryBuilder) ForOrganization(orgID xid.ID) *SearchQueryBuilder

ForOrganization filters by organization ID (optional)

func (*SearchQueryBuilder) ForUser added in v0.0.7

func (b *SearchQueryBuilder) ForUser(userID xid.ID) *SearchQueryBuilder

ForUser filters by user ID

func (*SearchQueryBuilder) Fuzzy added in v0.0.7

Fuzzy enables fuzzy matching

func (*SearchQueryBuilder) InFields added in v0.0.7

func (b *SearchQueryBuilder) InFields(fields ...string) *SearchQueryBuilder

InFields restricts search to specific fields

func (*SearchQueryBuilder) Limit added in v0.0.7

func (b *SearchQueryBuilder) Limit(limit int) *SearchQueryBuilder

Limit sets result limit

func (*SearchQueryBuilder) Offset added in v0.0.7

func (b *SearchQueryBuilder) Offset(offset int) *SearchQueryBuilder

Offset sets result offset

func (*SearchQueryBuilder) Since added in v0.0.7

Since filters events after timestamp

func (*SearchQueryBuilder) Until added in v0.0.7

Until filters events before timestamp

func (*SearchQueryBuilder) WithAction added in v0.0.7

func (b *SearchQueryBuilder) WithAction(action string) *SearchQueryBuilder

WithAction filters by action

type SearchRepository added in v0.0.7

type SearchRepository interface {
	// Search performs full-text search on audit events
	Search(ctx context.Context, query *SearchQuery) (*SearchResponse, error)

	// SearchPostgreSQL performs PostgreSQL tsvector search
	SearchPostgreSQL(ctx context.Context, query *SearchQuery) (*SearchResponse, error)

	// SearchSQLite performs SQLite FTS5 search
	SearchSQLite(ctx context.Context, query *SearchQuery) (*SearchResponse, error)
}

SearchRepository defines database-specific search implementation

type SearchResponse added in v0.0.7

type SearchResponse struct {
	Results    []*SearchResult      `json:"results"`
	Pagination *pagination.PageMeta `json:"pagination"`
	Query      string               `json:"query"`  // The processed query
	TookMs     int64                `json:"tookMs"` // Query execution time in milliseconds
}

SearchResponse represents paginated search results

type SearchResult added in v0.0.7

type SearchResult struct {
	Event *Event  `json:"event"`
	Rank  float64 `json:"rank"` // Relevance score (0-1)
}

SearchResult represents a single search result

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service handles audit logging

func NewService

func NewService(repo Repository, opts ...ServiceOption) *Service

NewService creates a new audit service with optional providers

func (*Service) Count added in v0.0.9

func (s *Service) Count(ctx context.Context, filter *ListEventsFilter) (int64, error)

Count returns the count of audit events matching the filter

func (*Service) CountEvents added in v0.0.9

func (s *Service) CountEvents(ctx context.Context, filter *ListEventsFilter) (int64, error)

CountEvents is an alias for Count for better readability

func (*Service) Create

func (s *Service) Create(ctx context.Context, req *CreateEventRequest) (*Event, error)

Create creates a new audit event from a request

func (*Service) DeleteOlderThan added in v0.0.9

func (s *Service) DeleteOlderThan(ctx context.Context, filter *DeleteFilter, before time.Time) (int64, error)

DeleteOlderThan deletes audit events older than the specified time Returns the number of deleted events

func (*Service) Get

func (s *Service) Get(ctx context.Context, req *GetEventRequest) (*Event, error)

Get retrieves an audit event by ID

func (*Service) GetActivitySummary added in v0.0.9

func (s *Service) GetActivitySummary(ctx context.Context, filter *StatisticsFilter) (*ActivitySummary, error)

GetActivitySummary returns a comprehensive activity summary dashboard

func (*Service) GetGrowthRate added in v0.0.9

func (s *Service) GetGrowthRate(ctx context.Context, filter *StatisticsFilter) (*GetGrowthRateResponse, error)

GetGrowthRate returns growth metrics across different time windows

func (*Service) GetOldestEvent added in v0.0.9

func (s *Service) GetOldestEvent(ctx context.Context, filter *ListEventsFilter) (*Event, error)

GetOldestEvent retrieves the oldest audit event matching the filter

func (*Service) GetProviders added in v0.0.7

func (s *Service) GetProviders() *ProviderRegistry

GetProviders returns the provider registry (for external use)

func (*Service) GetStatisticsByAction added in v0.0.9

func (s *Service) GetStatisticsByAction(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByActionResponse, error)

GetStatisticsByAction returns aggregated statistics grouped by action

func (*Service) GetStatisticsByActionAndUser added in v0.0.9

func (s *Service) GetStatisticsByActionAndUser(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByActionAndUserResponse, error)

GetStatisticsByActionAndUser returns event counts grouped by action and user

func (*Service) GetStatisticsByDate added in v0.0.9

func (s *Service) GetStatisticsByDate(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByDateResponse, error)

GetStatisticsByDate returns daily event counts for a date range

func (*Service) GetStatisticsByDay added in v0.0.9

func (s *Service) GetStatisticsByDay(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByDayResponse, error)

GetStatisticsByDay returns event distribution by day of week

func (*Service) GetStatisticsByHour added in v0.0.9

func (s *Service) GetStatisticsByHour(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByHourResponse, error)

GetStatisticsByHour returns event distribution by hour of day (0-23)

func (*Service) GetStatisticsByIPAddress added in v0.0.9

func (s *Service) GetStatisticsByIPAddress(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByIPAddressResponse, error)

GetStatisticsByIPAddress returns event counts grouped by IP address

func (*Service) GetStatisticsByResource added in v0.0.9

func (s *Service) GetStatisticsByResource(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByResourceResponse, error)

GetStatisticsByResource returns aggregated statistics grouped by resource

func (*Service) GetStatisticsByResourceAndAction added in v0.0.9

func (s *Service) GetStatisticsByResourceAndAction(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByResourceAndActionResponse, error)

GetStatisticsByResourceAndAction returns event counts grouped by resource and action

func (*Service) GetStatisticsByUser added in v0.0.9

func (s *Service) GetStatisticsByUser(ctx context.Context, filter *StatisticsFilter) (*GetStatisticsByUserResponse, error)

GetStatisticsByUser returns aggregated statistics grouped by user

func (*Service) GetTimeSeries added in v0.0.9

func (s *Service) GetTimeSeries(ctx context.Context, filter *TimeSeriesFilter) (*GetTimeSeriesResponse, error)

GetTimeSeries returns event counts over time with configurable intervals

func (*Service) GetTrends added in v0.0.9

func (s *Service) GetTrends(ctx context.Context, filter *TrendFilter) (*GetTrendsResponse, error)

GetTrends compares event counts between current and previous periods

func (*Service) GetUniqueIPCount added in v0.0.9

func (s *Service) GetUniqueIPCount(ctx context.Context, filter *StatisticsFilter) (int64, error)

GetUniqueIPCount returns the count of unique IP addresses

func (*Service) List

func (s *Service) List(ctx context.Context, filter *ListEventsFilter) (*ListEventsResponse, error)

List returns paginated audit events with optional filters

func (*Service) Log

func (s *Service) Log(ctx context.Context, userID *xid.ID, action, resource, ip, ua, metadata string) error

Log creates an audit event with timestamps

func (*Service) Search added in v0.0.7

func (s *Service) Search(ctx context.Context, query *SearchQuery) (*SearchResponse, error)

Search performs full-text search on audit events

type ServiceConfig added in v0.0.7

type ServiceConfig struct {
	Providers *ProviderRegistry
}

ServiceConfig holds configuration for the audit service

type ServiceOption added in v0.0.7

type ServiceOption func(*ServiceConfig)

ServiceOption is a functional option for configuring the audit service

func WithAuditProvider added in v0.0.7

func WithAuditProvider(provider AuditProvider) ServiceOption

WithAuditProvider adds an audit event consumer

func WithOrgProvider added in v0.0.7

func WithOrgProvider(provider OrganizationProvider) ServiceOption

WithOrgProvider configures an organization provider

func WithProviders added in v0.0.7

func WithProviders(providers *ProviderRegistry) ServiceOption

WithProviders configures the service to use custom providers

func WithUserProvider added in v0.0.7

func WithUserProvider(provider UserProvider) ServiceOption

WithUserProvider configures a user provider

type StatisticsFilter added in v0.0.9

type StatisticsFilter struct {
	// Filter by app
	AppID *xid.ID `json:"appId,omitempty"`

	// Filter by organization (user-created org)
	OrganizationID *xid.ID `json:"organizationId,omitempty"`

	// Filter by environment
	EnvironmentID *xid.ID `json:"environmentId,omitempty"`

	// Filter by user
	UserID *xid.ID `json:"userId,omitempty"`

	// Filter by action (for resource/user statistics)
	Action *string `json:"action,omitempty"`

	// Filter by resource (for action/user statistics)
	Resource *string `json:"resource,omitempty"`

	// Time range filters
	Since *time.Time `json:"since,omitempty"`
	Until *time.Time `json:"until,omitempty"`

	// Metadata filters
	MetadataFilters []MetadataFilter `json:"metadataFilters,omitempty"`

	// Limit for top N results (default: 100)
	Limit int `json:"limit,omitempty"`
}

StatisticsFilter defines filters for aggregation statistics queries

type StreamFilter added in v0.0.7

type StreamFilter struct {
	AppID      *xid.ID  `json:"appId,omitempty"`
	UserID     *xid.ID  `json:"userId,omitempty"`
	Actions    []string `json:"actions,omitempty"`    // Filter by specific actions
	BufferSize int      `json:"bufferSize,omitempty"` // Channel buffer size
}

StreamFilter defines filters for streaming audit events

type StreamService added in v0.0.7

type StreamService struct {
	// contains filtered or unexported fields
}

StreamService manages real-time audit event streaming Note: Requires PostgreSQL LISTEN/NOTIFY support via pgdriver.Listener

func NewStreamService added in v0.0.7

func NewStreamService(listener interface{}) *StreamService

NewStreamService creates a new stream service listener should be *pgdriver.Listener from github.com/uptrace/bun/driver/pgdriver

func (*StreamService) Shutdown added in v0.0.7

func (s *StreamService) Shutdown()

Shutdown gracefully shuts down the stream service

func (*StreamService) Stats added in v0.0.7

func (s *StreamService) Stats() StreamStats

Stats returns streaming statistics

func (*StreamService) Subscribe added in v0.0.7

func (s *StreamService) Subscribe(ctx context.Context, filter *StreamFilter) (<-chan *Event, string, error)

Subscribe subscribes to audit event stream with optional filters

func (*StreamService) Unsubscribe added in v0.0.7

func (s *StreamService) Unsubscribe(clientID string)

Unsubscribe removes a client subscription

func (*StreamService) UpdateHeartbeat added in v0.0.7

func (s *StreamService) UpdateHeartbeat(clientID string)

UpdateHeartbeat updates client's last seen time (called by WebSocket ping)

type StreamStats added in v0.0.7

type StreamStats struct {
	ActiveClients int           `json:"activeClients"`
	Clients       []ClientStats `json:"clients"`
}

StreamStats contains streaming service statistics

type TimeSeriesFilter added in v0.0.9

type TimeSeriesFilter struct {
	StatisticsFilter

	// Interval for time series grouping
	Interval TimeSeriesInterval `json:"interval"`
}

TimeSeriesFilter extends StatisticsFilter with interval configuration

type TimeSeriesInterval added in v0.0.9

type TimeSeriesInterval string

TimeSeriesInterval defines the grouping interval for time series data

const (
	// IntervalHourly groups data by hour
	IntervalHourly TimeSeriesInterval = "hourly"
	// IntervalDaily groups data by day
	IntervalDaily TimeSeriesInterval = "daily"
	// IntervalWeekly groups data by week
	IntervalWeekly TimeSeriesInterval = "weekly"
	// IntervalMonthly groups data by month
	IntervalMonthly TimeSeriesInterval = "monthly"
)

type TimeSeriesPoint added in v0.0.9

type TimeSeriesPoint struct {
	Timestamp time.Time `json:"timestamp"`
	Count     int64     `json:"count"`
}

TimeSeriesPoint represents a single data point in a time series

type TrendData added in v0.0.9

type TrendData struct {
	CurrentPeriod   int64   `json:"currentPeriod"`
	PreviousPeriod  int64   `json:"previousPeriod"`
	ChangeAbsolute  int64   `json:"changeAbsolute"`
	ChangePercent   float64 `json:"changePercent"`
	ChangeDirection string  `json:"changeDirection"` // "up", "down", "stable"
}

TrendData represents comparison between current and previous periods

type TrendFilter added in v0.0.9

type TrendFilter struct {
	StatisticsFilter

	// Period duration for comparison (e.g., 24h, 7d, 30d)
	// Current period: Since to Until (or now if Until is nil)
	// Previous period: calculated automatically as same duration before Since
	PeriodDuration time.Duration `json:"periodDuration,omitempty"`
}

TrendFilter extends StatisticsFilter with period configuration

type UserFilter added in v0.0.7

type UserFilter struct {
	IDs               []string   `json:"ids,omitempty"`
	Emails            []string   `json:"emails,omitempty"`
	Status            *string    `json:"status,omitempty"`
	MFAEnabled        *bool      `json:"mfaEnabled,omitempty"`
	Roles             []string   `json:"roles,omitempty"`
	CreatedAfter      *time.Time `json:"createdAfter,omitempty"`
	CreatedBefore     *time.Time `json:"createdBefore,omitempty"`
	LastLoginAfter    *time.Time `json:"lastLoginAfter,omitempty"`
	LastLoginBefore   *time.Time `json:"lastLoginBefore,omitempty"`
	PasswordExpired   *bool      `json:"passwordExpired,omitempty"`
	PasswordExpiryAge *int       `json:"passwordExpiryAge,omitempty"` // Days
	Limit             int        `json:"limit"`
	Offset            int        `json:"offset"`
}

UserFilter defines criteria for filtering users

type UserMetrics added in v0.0.7

type UserMetrics struct {
	TotalUsers        int                    `json:"totalUsers"`
	ActiveUsers       int                    `json:"activeUsers"`
	InactiveUsers     int                    `json:"inactiveUsers"`
	MFAAdoptionRate   float64                `json:"mfaAdoptionRate"` // 0-100
	UsersWithMFA      int                    `json:"usersWithMFA"`
	UsersWithoutMFA   int                    `json:"usersWithoutMFA"`
	ExpiredPasswords  int                    `json:"expiredPasswords"`
	LockedAccounts    int                    `json:"lockedAccounts"`
	SuspendedAccounts int                    `json:"suspendedAccounts"`
	ByRole            map[string]int         `json:"byRole,omitempty"`
	ByStatus          map[string]int         `json:"byStatus,omitempty"`
	CustomMetrics     map[string]interface{} `json:"customMetrics,omitempty"`
}

UserMetrics contains aggregated user metrics

type UserProvider added in v0.0.7

type UserProvider interface {
	// GetUser retrieves a single user by ID
	GetUser(ctx context.Context, scope *Scope, userID string) (*GenericUser, error)

	// ListUsers retrieves users matching filter criteria
	ListUsers(ctx context.Context, scope *Scope, filter *UserFilter) ([]*GenericUser, error)

	// QueryUserMetrics retrieves aggregated metrics about users
	QueryUserMetrics(ctx context.Context, scope *Scope, query *MetricsQuery) (*UserMetrics, error)
}

UserProvider provides access to user data from any source (authsome, LDAP, custom DB) This breaks the tight coupling to authsome's internal user service

type UserStatistic added in v0.0.9

type UserStatistic struct {
	UserID        *xid.ID   `json:"userId"`
	Count         int64     `json:"count"`
	FirstOccurred time.Time `json:"firstOccurred"`
	LastOccurred  time.Time `json:"lastOccurred"`
}

UserStatistic represents aggregated statistics for a user

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL