Documentation
¶
Overview ¶
Package activity provides default persistence helpers for the go-users ActivitySink. The Repository implements both the sink (writes) and the ActivityRepository read-side contract so transports can log lifecycle events and later query them for dashboards. The ActivitySink interface lives in pkg/types and is intentionally minimal (`Log(ctx, ActivityRecord) error`) so hosts can swap sinks without breaking changes.
Index ¶
- Constants
- func ApplyCursorPagination(q *bun.SelectQuery, cursor *ActivityCursor, limit int) *bun.SelectQuery
- func AttachSessionID(ctx context.Context, record types.ActivityRecord, provider SessionIDProvider, ...) types.ActivityRecord
- func AttachSessionIDValue(record types.ActivityRecord, sessionID, key string) types.ActivityRecord
- func BuildFilterFromActor(actor *auth.ActorContext, role string, req types.ActivityFilter, ...) (types.ActivityFilter, error)
- func BuildRecordFromActor(actor *auth.ActorContext, verb, objectType, objectID string, ...) (types.ActivityRecord, error)
- func BuildRecordFromUUID(actorID uuid.UUID, verb, objectType, objectID string, metadata map[string]any, ...) (types.ActivityRecord, error)
- func DefaultAdminRoleAliases() []string
- func DefaultMachineActorTypes() []string
- func DefaultMachineDataKeys() []string
- func DefaultMasker() *masker.Masker
- func DefaultSuperadminRoleAliases() []string
- func SanitizeRecord(mask *masker.Masker, record types.ActivityRecord) types.ActivityRecord
- func SanitizeRecords(mask *masker.Masker, records []types.ActivityRecord) []types.ActivityRecord
- func StampEnrichment(record types.ActivityRecord, now time.Time, version string) types.ActivityRecord
- func ToActivityRecord(entry *LogEntry) types.ActivityRecord
- type AccessPolicyOption
- type ActivityAccessPolicy
- type ActivityCursor
- type ActivityEnricher
- type ActivityEnrichmentFilter
- type ActivityEnrichmentPage
- type ActivityEnrichmentQuery
- type ActivityEnrichmentStore
- type ActivityEnrichmentStoreWithOptions
- type ActivityEnrichmentUpdateOptions
- type ActivityStatsPolicy
- type ActorInfo
- type ActorResolver
- type DefaultAccessPolicy
- func (p *DefaultAccessPolicy) Apply(actor *auth.ActorContext, role string, req types.ActivityFilter) (types.ActivityFilter, error)
- func (p *DefaultAccessPolicy) ApplyStats(actor *auth.ActorContext, role string, req types.ActivityStatsFilter) (types.ActivityStatsFilter, error)
- func (p *DefaultAccessPolicy) Sanitize(actor *auth.ActorContext, role string, records []types.ActivityRecord) []types.ActivityRecord
- type EnrichedSink
- type EnricherChain
- type EnricherFunc
- type EnricherWithHandler
- type EnrichmentErrorHandler
- type EnrichmentErrorStrategy
- type EnrichmentScope
- type EnrichmentWriteMode
- type FilterConfig
- type FilterOption
- func WithChannelAllowlist(channels ...string) FilterOption
- func WithChannelDenylist(channels ...string) FilterOption
- func WithMachineActivityEnabled(enabled bool) FilterOption
- func WithMachineActorTypes(types ...string) FilterOption
- func WithMachineDataKeys(keys ...string) FilterOption
- func WithRoleAliases(adminAliases, superadminAliases []string) FilterOption
- func WithSuperadminScope(enabled bool) FilterOption
- type LogEntry
- type ObjectInfo
- type ObjectResolver
- type RecordOption
- type Repository
- func (r *Repository) ActivityStats(ctx context.Context, filter types.ActivityStatsFilter) (types.ActivityStats, error)
- func (r *Repository) ListActivity(ctx context.Context, filter types.ActivityFilter) (types.ActivityPage, error)
- func (r *Repository) ListActivityForEnrichment(ctx context.Context, filter ActivityEnrichmentFilter) (ActivityEnrichmentPage, error)
- func (r *Repository) Log(ctx context.Context, record types.ActivityRecord) error
- func (r *Repository) UpdateActivityData(ctx context.Context, id uuid.UUID, data map[string]any) error
- func (r *Repository) UpdateActivityDataWithOptions(ctx context.Context, id uuid.UUID, data map[string]any, ...) error
- type RepositoryConfig
- type ResolveContext
- type SanitizerConfig
- type SessionIDProvider
- type SessionIDProviderFunc
Constants ¶
const ( DataKeyActorDisplay = "actor_display" DataKeyActorEmail = "actor_email" DataKeyActorID = "actor_id" DataKeyActorType = "actor_type" DataKeyObjectDisplay = "object_display" DataKeyObjectType = "object_type" DataKeyObjectID = "object_id" DataKeyObjectDeleted = "object_deleted" DataKeySessionID = "session_id" DataKeyEnrichedAt = "enriched_at" DataKeyEnricherVersion = "enricher_version" )
Enrichment metadata keys. These are flat JSONB keys and should remain stable.
const DefaultEnricherVersion = "v1"
DefaultEnricherVersion is the built-in fallback version string when enrichment is enabled.
Variables ¶
This section is empty.
Functions ¶
func ApplyCursorPagination ¶ added in v0.10.0
func ApplyCursorPagination(q *bun.SelectQuery, cursor *ActivityCursor, limit int) *bun.SelectQuery
ApplyCursorPagination applies cursor pagination using created_at/id ordering. Results are ordered by created_at DESC, id DESC, and filtered to items older than the supplied cursor.
func AttachSessionID ¶ added in v0.14.0
func AttachSessionID(ctx context.Context, record types.ActivityRecord, provider SessionIDProvider, key string) types.ActivityRecord
AttachSessionID adds a session identifier to the record data if available.
func AttachSessionIDValue ¶ added in v0.14.0
func AttachSessionIDValue(record types.ActivityRecord, sessionID, key string) types.ActivityRecord
AttachSessionIDValue adds a session identifier to the record data if missing.
func BuildFilterFromActor ¶ added in v0.10.0
func BuildFilterFromActor(actor *auth.ActorContext, role string, req types.ActivityFilter, opts ...FilterOption) (types.ActivityFilter, error)
BuildFilterFromActor constructs a safe ActivityFilter using the auth actor context plus role-aware constraints and optional channel rules.
func BuildRecordFromActor ¶
func BuildRecordFromActor(actor *auth.ActorContext, verb, objectType, objectID string, metadata map[string]any, opts ...RecordOption) (types.ActivityRecord, error)
BuildRecordFromActor constructs an ActivityRecord using the actor metadata supplied by go-auth middleware plus verb/object details and optional metadata. It normalizes actor, tenant, and org identifiers into UUIDs and defensively copies metadata to avoid caller mutation.
func BuildRecordFromUUID ¶ added in v0.3.0
func BuildRecordFromUUID(actorID uuid.UUID, verb, objectType, objectID string, metadata map[string]any, opts ...RecordOption) (types.ActivityRecord, error)
BuildRecordFromUUID constructs an ActivityRecord when only the actor UUID is available. It trims verb/object fields, validates required values, copies metadata defensively, and applies RecordOptions.
func DefaultAdminRoleAliases ¶ added in v0.10.0
func DefaultAdminRoleAliases() []string
DefaultAdminRoleAliases returns the default admin role aliases.
func DefaultMachineActorTypes ¶ added in v0.10.0
func DefaultMachineActorTypes() []string
DefaultMachineActorTypes returns the default machine actor type identifiers.
func DefaultMachineDataKeys ¶ added in v0.10.0
func DefaultMachineDataKeys() []string
DefaultMachineDataKeys returns the default machine data keys.
func DefaultMasker ¶ added in v0.10.0
DefaultMasker returns a configured masker instance with the default denylist.
func DefaultSuperadminRoleAliases ¶ added in v0.10.0
func DefaultSuperadminRoleAliases() []string
DefaultSuperadminRoleAliases returns the default superadmin role aliases.
func SanitizeRecord ¶ added in v0.10.0
func SanitizeRecord(mask *masker.Masker, record types.ActivityRecord) types.ActivityRecord
SanitizeRecord masks sensitive values in the activity record data payload.
func SanitizeRecords ¶ added in v0.10.0
func SanitizeRecords(mask *masker.Masker, records []types.ActivityRecord) []types.ActivityRecord
SanitizeRecords masks sensitive values for every record in the slice.
func StampEnrichment ¶ added in v0.14.0
func StampEnrichment(record types.ActivityRecord, now time.Time, version string) types.ActivityRecord
StampEnrichment sets enriched_at and enricher_version on the activity record.
func ToActivityRecord ¶
func ToActivityRecord(entry *LogEntry) types.ActivityRecord
ToActivityRecord converts the Bun model into the domain activity record.
Types ¶
type AccessPolicyOption ¶ added in v0.10.0
type AccessPolicyOption func(*DefaultAccessPolicy)
AccessPolicyOption customizes the default activity access policy.
func WithIPRedaction ¶ added in v0.10.0
func WithIPRedaction(enabled bool) AccessPolicyOption
WithIPRedaction toggles IP redaction for non-superadmin roles.
func WithPolicyFilterOptions ¶ added in v0.10.0
func WithPolicyFilterOptions(opts ...FilterOption) AccessPolicyOption
WithPolicyFilterOptions configures filter options applied during policy enforcement.
func WithPolicyMasker ¶ added in v0.10.0
func WithPolicyMasker(masker *masker.Masker) AccessPolicyOption
WithPolicyMasker overrides the masker used for sanitization.
func WithPolicyStatsSelfOnly ¶ added in v0.10.0
func WithPolicyStatsSelfOnly(enabled bool) AccessPolicyOption
WithPolicyStatsSelfOnly toggles self-only stats for non-admin roles.
type ActivityAccessPolicy ¶ added in v0.10.0
type ActivityAccessPolicy interface {
Apply(actor *auth.ActorContext, role string, req types.ActivityFilter) (types.ActivityFilter, error)
Sanitize(actor *auth.ActorContext, role string, records []types.ActivityRecord) []types.ActivityRecord
}
ActivityAccessPolicy applies role-aware constraints and sanitization to activity feeds.
type ActivityCursor ¶ added in v0.10.0
ActivityCursor defines the cursor shape for activity feeds.
type ActivityEnricher ¶ added in v0.14.0
type ActivityEnricher interface {
Enrich(ctx context.Context, record types.ActivityRecord) (types.ActivityRecord, error)
}
ActivityEnricher mutates or returns an enriched ActivityRecord.
type ActivityEnrichmentFilter ¶ added in v0.14.0
type ActivityEnrichmentFilter struct {
Scope types.ScopeFilter
MissingKeys []string
EnrichedBefore *time.Time
Cursor *ActivityCursor
Limit int
}
ActivityEnrichmentFilter narrows enrichment backfill selection.
type ActivityEnrichmentPage ¶ added in v0.14.0
type ActivityEnrichmentPage struct {
Records []types.ActivityRecord
NextCursor *ActivityCursor
}
ActivityEnrichmentPage returns selected activity records and the next cursor.
type ActivityEnrichmentQuery ¶ added in v0.14.0
type ActivityEnrichmentQuery interface {
ListActivityForEnrichment(ctx context.Context, filter ActivityEnrichmentFilter) (ActivityEnrichmentPage, error)
}
ActivityEnrichmentQuery exposes helper queries for missing/stale enrichment.
type ActivityEnrichmentStore ¶ added in v0.14.0
type ActivityEnrichmentStore interface {
UpdateActivityData(ctx context.Context, id uuid.UUID, data map[string]any) error
}
ActivityEnrichmentStore updates activity metadata for backfill jobs.
type ActivityEnrichmentStoreWithOptions ¶ added in v0.14.0
type ActivityEnrichmentStoreWithOptions interface {
UpdateActivityDataWithOptions(ctx context.Context, id uuid.UUID, data map[string]any, opts ActivityEnrichmentUpdateOptions) error
}
ActivityEnrichmentStoreWithOptions supports optional forced updates.
type ActivityEnrichmentUpdateOptions ¶ added in v0.14.0
type ActivityEnrichmentUpdateOptions struct {
// ForceKeys allows overwriting specific keys (e.g., enriched_at) when needed.
ForceKeys []string
}
ActivityEnrichmentUpdateOptions controls missing-key update behavior.
type ActivityStatsPolicy ¶ added in v0.10.0
type ActivityStatsPolicy interface {
ApplyStats(actor *auth.ActorContext, role string, req types.ActivityStatsFilter) (types.ActivityStatsFilter, error)
}
ActivityStatsPolicy applies role-aware constraints to activity stats.
type ActorResolver ¶ added in v0.14.0
type ActorResolver interface {
ResolveActors(ctx context.Context, ids []uuid.UUID, meta ResolveContext) (map[uuid.UUID]ActorInfo, error)
}
ActorResolver resolves actor enrichment details in batch.
type DefaultAccessPolicy ¶ added in v0.10.0
type DefaultAccessPolicy struct {
// contains filtered or unexported fields
}
DefaultAccessPolicy applies BuildFilterFromActor and sanitizes records on read.
func NewDefaultAccessPolicy ¶ added in v0.10.0
func NewDefaultAccessPolicy(opts ...AccessPolicyOption) *DefaultAccessPolicy
NewDefaultAccessPolicy returns the default policy implementation.
func (*DefaultAccessPolicy) Apply ¶ added in v0.10.0
func (p *DefaultAccessPolicy) Apply(actor *auth.ActorContext, role string, req types.ActivityFilter) (types.ActivityFilter, error)
Apply enforces role-aware scope/visibility rules on the requested filter.
func (*DefaultAccessPolicy) ApplyStats ¶ added in v0.10.0
func (p *DefaultAccessPolicy) ApplyStats(actor *auth.ActorContext, role string, req types.ActivityStatsFilter) (types.ActivityStatsFilter, error)
ApplyStats enforces role-aware scope/visibility rules on stats filters.
func (*DefaultAccessPolicy) Sanitize ¶ added in v0.10.0
func (p *DefaultAccessPolicy) Sanitize(actor *auth.ActorContext, role string, records []types.ActivityRecord) []types.ActivityRecord
Sanitize applies masking rules and IP redaction to activity records.
type EnrichedSink ¶ added in v0.14.0
type EnrichedSink struct {
Sink types.ActivitySink
Enricher ActivityEnricher
ErrorHandler EnrichmentErrorHandler
}
EnrichedSink enriches activity records before logging them to a sink.
func (*EnrichedSink) Log ¶ added in v0.14.0
func (s *EnrichedSink) Log(ctx context.Context, record types.ActivityRecord) error
Log enriches the record (if configured) and forwards it to the sink.
type EnricherChain ¶ added in v0.14.0
type EnricherChain []ActivityEnricher
EnricherChain composes multiple enrichers in order.
func (EnricherChain) Enrich ¶ added in v0.14.0
func (c EnricherChain) Enrich(ctx context.Context, record types.ActivityRecord) (types.ActivityRecord, error)
Enrich applies the chain sequentially and stops on the first error.
func (EnricherChain) EnrichWithHandler ¶ added in v0.14.0
func (c EnricherChain) EnrichWithHandler(ctx context.Context, record types.ActivityRecord, handler EnrichmentErrorHandler) (types.ActivityRecord, error)
EnrichWithHandler applies the chain and delegates error handling when provided.
type EnricherFunc ¶ added in v0.14.0
type EnricherFunc func(ctx context.Context, record types.ActivityRecord) (types.ActivityRecord, error)
EnricherFunc adapts a function into an ActivityEnricher.
func (EnricherFunc) Enrich ¶ added in v0.14.0
func (f EnricherFunc) Enrich(ctx context.Context, record types.ActivityRecord) (types.ActivityRecord, error)
Enrich executes the function and satisfies ActivityEnricher.
type EnricherWithHandler ¶ added in v0.14.0
type EnricherWithHandler interface {
EnrichWithHandler(ctx context.Context, record types.ActivityRecord, handler EnrichmentErrorHandler) (types.ActivityRecord, error)
}
EnricherWithHandler allows enrichment with an explicit error handler.
type EnrichmentErrorHandler ¶ added in v0.14.0
type EnrichmentErrorHandler func(ctx context.Context, err error, enricher ActivityEnricher, current types.ActivityRecord, original types.ActivityRecord) (types.ActivityRecord, error)
EnrichmentErrorHandler decides how to handle errors during enrichment. Return a non-nil error to stop the chain. Return nil to continue using the returned record. Best-effort handlers should return the last successful record to allow partial enrichment.
func DefaultEnrichmentErrorHandler ¶ added in v0.14.0
func DefaultEnrichmentErrorHandler(strategy EnrichmentErrorStrategy) EnrichmentErrorHandler
DefaultEnrichmentErrorHandler returns a handler for the chosen strategy.
type EnrichmentErrorStrategy ¶ added in v0.14.0
type EnrichmentErrorStrategy int
EnrichmentErrorStrategy chooses how enrichment errors are handled.
const ( // EnrichmentFailFast stops on the first error and returns the original record. EnrichmentFailFast EnrichmentErrorStrategy = iota // EnrichmentBestEffort keeps the last successful record and continues the chain. EnrichmentBestEffort )
type EnrichmentScope ¶ added in v0.14.0
type EnrichmentScope string
EnrichmentScope determines when enrichment should apply.
const ( EnrichmentScopeWrite EnrichmentScope = "write" EnrichmentScopeBackfill EnrichmentScope = "backfill" EnrichmentScopeBoth EnrichmentScope = "both" )
type EnrichmentWriteMode ¶ added in v0.14.0
type EnrichmentWriteMode string
EnrichmentWriteMode determines how write-time enrichment is applied.
const ( EnrichmentWriteModeNone EnrichmentWriteMode = "none" EnrichmentWriteModeWrapper EnrichmentWriteMode = "wrapper" EnrichmentWriteModeRepo EnrichmentWriteMode = "repo" EnrichmentWriteModeHybrid EnrichmentWriteMode = "hybrid" )
type FilterConfig ¶ added in v0.10.0
type FilterConfig struct {
ChannelAllowlist []string
ChannelDenylist []string
// Machine activity settings are reserved for policy layers that can inspect
// records (actor type/data); BuildFilterFromActor does not use them directly.
MachineActivityEnabled bool
MachineActorTypes []string
MachineDataKeys []string
SuperadminScope bool
AdminRoleAliases []string
SuperadminRoleAliases []string
}
FilterConfig controls how BuildFilterFromActor applies role and channel rules.
type FilterOption ¶ added in v0.10.0
type FilterOption func(*FilterConfig)
FilterOption mutates the filter configuration.
func WithChannelAllowlist ¶ added in v0.10.0
func WithChannelAllowlist(channels ...string) FilterOption
WithChannelAllowlist restricts results to the provided channels.
func WithChannelDenylist ¶ added in v0.10.0
func WithChannelDenylist(channels ...string) FilterOption
WithChannelDenylist excludes the provided channels.
func WithMachineActivityEnabled ¶ added in v0.10.0
func WithMachineActivityEnabled(enabled bool) FilterOption
WithMachineActivityEnabled toggles machine activity visibility.
func WithMachineActorTypes ¶ added in v0.10.0
func WithMachineActorTypes(types ...string) FilterOption
WithMachineActorTypes overrides the machine actor type identifiers.
func WithMachineDataKeys ¶ added in v0.10.0
func WithMachineDataKeys(keys ...string) FilterOption
WithMachineDataKeys overrides the data keys used to flag machine activity.
func WithRoleAliases ¶ added in v0.10.0
func WithRoleAliases(adminAliases, superadminAliases []string) FilterOption
WithRoleAliases overrides the admin/superadmin role alias lists.
func WithSuperadminScope ¶ added in v0.10.0
func WithSuperadminScope(enabled bool) FilterOption
WithSuperadminScope allows superadmins to widen scope beyond actor context.
type LogEntry ¶
type LogEntry struct {
bun.BaseModel `bun:"table:user_activity"`
ID uuid.UUID `bun:",pk,type:uuid"`
UserID uuid.UUID `bun:"user_id,type:uuid"`
ActorID uuid.UUID `bun:"actor_id,type:uuid"`
TenantID uuid.UUID `bun:"tenant_id,type:uuid"`
OrgID uuid.UUID `bun:"org_id,type:uuid"`
Verb string `bun:"verb"`
ObjectType string `bun:"object_type"`
ObjectID string `bun:"object_id"`
Channel string `bun:"channel"`
IP string `bun:"ip"`
Data map[string]any `bun:"data,type:jsonb"`
CreatedAt time.Time `bun:"created_at"`
}
LogEntry models the persisted row in user_activity.
func FromActivityRecord ¶
func FromActivityRecord(record types.ActivityRecord) *LogEntry
FromActivityRecord converts a domain activity record into the Bun model so it can be reused by transports without duplicating conversion logic.
type ObjectInfo ¶ added in v0.14.0
ObjectInfo defines enrichment details for an object.
type ObjectResolver ¶ added in v0.14.0
type ObjectResolver interface {
ResolveObjects(ctx context.Context, objectType string, ids []string, meta ResolveContext) (map[string]ObjectInfo, error)
}
ObjectResolver resolves object enrichment details in batch.
type RecordOption ¶
type RecordOption func(*types.ActivityRecord)
RecordOption mutates the ActivityRecord produced by BuildRecordFromActor.
func WithChannel ¶
func WithChannel(channel string) RecordOption
WithChannel sets the channel/module field used for downstream filtering.
func WithOccurredAt ¶ added in v0.3.0
func WithOccurredAt(occurredAt time.Time) RecordOption
WithOccurredAt overrides the default occurrence timestamp.
func WithOrg ¶ added in v0.3.0
func WithOrg(orgID uuid.UUID) RecordOption
WithOrg sets the organization identifier for the record.
func WithTenant ¶ added in v0.3.0
func WithTenant(tenantID uuid.UUID) RecordOption
WithTenant sets the tenant identifier for the record.
type Repository ¶
type Repository struct {
// contains filtered or unexported fields
}
Repository persists activity logs and exposes query helpers.
func NewRepository ¶
func NewRepository(cfg RepositoryConfig) (*Repository, error)
NewRepository constructs a repository that implements both ActivitySink and ActivityRepository interfaces.
func (*Repository) ActivityStats ¶
func (r *Repository) ActivityStats(ctx context.Context, filter types.ActivityStatsFilter) (types.ActivityStats, error)
ActivityStats aggregates counts grouped by verb.
func (*Repository) ListActivity ¶
func (r *Repository) ListActivity(ctx context.Context, filter types.ActivityFilter) (types.ActivityPage, error)
ListActivity returns a paginated feed filtered by the supplied criteria.
func (*Repository) ListActivityForEnrichment ¶ added in v0.14.0
func (r *Repository) ListActivityForEnrichment(ctx context.Context, filter ActivityEnrichmentFilter) (ActivityEnrichmentPage, error)
ListActivityForEnrichment returns activity records missing enrichment keys or stale by cutoff.
func (*Repository) Log ¶
func (r *Repository) Log(ctx context.Context, record types.ActivityRecord) error
Log persists an activity record into the database.
func (*Repository) UpdateActivityData ¶ added in v0.14.0
func (r *Repository) UpdateActivityData(ctx context.Context, id uuid.UUID, data map[string]any) error
UpdateActivityData merges missing keys into the activity data payload.
func (*Repository) UpdateActivityDataWithOptions ¶ added in v0.14.0
func (r *Repository) UpdateActivityDataWithOptions(ctx context.Context, id uuid.UUID, data map[string]any, opts ActivityEnrichmentUpdateOptions) error
UpdateActivityDataWithOptions merges missing keys and optionally forces updates for specific keys.
type RepositoryConfig ¶
type RepositoryConfig struct {
DB *bun.DB
Repository repository.Repository[*LogEntry]
Clock types.Clock
IDGen types.IDGenerator
Enricher ActivityEnricher
// EnrichmentErrorHandler controls fail-fast vs best-effort behavior.
EnrichmentErrorHandler EnrichmentErrorHandler
}
RepositoryConfig wires the Bun-backed activity repository.
type ResolveContext ¶ added in v0.14.0
type ResolveContext struct {
TenantID uuid.UUID
ActorID uuid.UUID
Verb string
Source string
Metadata map[string]any
}
ResolveContext provides request-scoped data used by resolvers.
type SanitizerConfig ¶ added in v0.10.0
SanitizerConfig controls the masker used for activity sanitization.
type SessionIDProvider ¶ added in v0.14.0
SessionIDProvider extracts a session identifier from the request context.
type SessionIDProviderFunc ¶ added in v0.14.0
SessionIDProviderFunc adapts a function into a SessionIDProvider.