exposure

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2026 License: GPL-3.0 Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrExposureEventNotFound  = errors.New("exposure event not found")
	ErrExposureEventExists    = errors.New("exposure event already exists")
	ErrStateHistoryNotFound   = errors.New("state history not found")
	ErrInvalidStateTransition = errors.New("invalid state transition")
)

Domain errors for exposure events.

Functions

func AllowedSortFields

func AllowedSortFields() map[string]string

AllowedSortFields returns the allowed sort fields for exposure events.

func IsExposureEventExists

func IsExposureEventExists(err error) bool

IsExposureEventExists checks if the error is an exposure event exists error.

func IsExposureEventNotFound

func IsExposureEventNotFound(err error) bool

IsExposureEventNotFound checks if the error is an exposure event not found error.

func IsInvalidStateTransition

func IsInvalidStateTransition(err error) bool

IsInvalidStateTransition checks if the error is an invalid state transition error.

func IsStateHistoryNotFound

func IsStateHistoryNotFound(err error) bool

IsStateHistoryNotFound checks if the error is a state history not found error.

func NewExposureEventExistsError

func NewExposureEventExistsError(fingerprint string) error

NewExposureEventExistsError creates a new exposure event exists error.

func NewExposureEventNotFoundError

func NewExposureEventNotFoundError(id string) error

NewExposureEventNotFoundError creates a new exposure event not found error.

func NewInvalidStateTransitionError

func NewInvalidStateTransitionError(from, to State) error

NewInvalidStateTransitionError creates a new invalid state transition error.

Types

type EventType

type EventType string

EventType represents the type of exposure event.

const (
	EventTypePortOpen            EventType = "port_open"
	EventTypePortClosed          EventType = "port_closed"
	EventTypeServiceDetected     EventType = "service_detected"
	EventTypeServiceChanged      EventType = "service_changed"
	EventTypeSubdomainDiscovered EventType = "subdomain_discovered"
	EventTypeSubdomainRemoved    EventType = "subdomain_removed"
	EventTypeCertificateExpiring EventType = "certificate_expiring"
	EventTypeCertificateExpired  EventType = "certificate_expired"
	EventTypeBucketPublic        EventType = "bucket_public"
	EventTypeBucketPrivate       EventType = "bucket_private"
	EventTypeRepoPublic          EventType = "repo_public"
	EventTypeRepoPrivate         EventType = "repo_private"
	EventTypeAPIExposed          EventType = "api_exposed"
	EventTypeAPIRemoved          EventType = "api_removed"
	EventTypeCredentialLeaked    EventType = "credential_leaked"
	EventTypeSensitiveData       EventType = "sensitive_data_exposed"
	EventTypeMisconfiguration    EventType = "misconfiguration"
	EventTypeDNSChange           EventType = "dns_change"
	EventTypeSSLIssue            EventType = "ssl_issue"
	EventTypeHeaderMissing       EventType = "header_missing"
	EventTypeCustom              EventType = "custom"
)

func AllEventTypes

func AllEventTypes() []EventType

AllEventTypes returns all valid event types.

func ParseEventType

func ParseEventType(s string) (EventType, error)

ParseEventType parses a string into an EventType.

func (EventType) IsPositiveExposure

func (t EventType) IsPositiveExposure() bool

IsPositiveExposure returns true if the event type indicates increased exposure.

func (EventType) IsValid

func (t EventType) IsValid() bool

IsValid checks if the event type is valid.

func (EventType) String

func (t EventType) String() string

String returns the string representation.

type ExposureEvent

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

ExposureEvent represents an attack surface change that is NOT a vulnerability. Examples: open ports, public buckets, exposed APIs, certificate expiry, etc.

func NewExposureEvent

func NewExposureEvent(
	tenantID shared.ID,
	eventType EventType,
	severity Severity,
	title string,
	source string,
	details map[string]any,
) (*ExposureEvent, error)

NewExposureEvent creates a new ExposureEvent.

func Reconstitute

func Reconstitute(
	id shared.ID,
	tenantID shared.ID,

	assetID *shared.ID,
	eventType EventType,
	severity Severity,
	state State,
	title string,
	description string,
	details map[string]any,
	fingerprint string,
	source string,
	firstSeenAt, lastSeenAt time.Time,
	resolvedAt *time.Time,
	resolvedBy *shared.ID,
	resolutionNotes string,
	createdAt, updatedAt time.Time,
) *ExposureEvent

Reconstitute recreates an ExposureEvent from persistence.

func (*ExposureEvent) Accept

func (e *ExposureEvent) Accept(acceptedBy shared.ID, notes string) error

Accept marks the exposure as accepted risk.

func (*ExposureEvent) AssetID

func (e *ExposureEvent) AssetID() *shared.ID

AssetID returns the asset ID.

func (*ExposureEvent) CreatedAt

func (e *ExposureEvent) CreatedAt() time.Time

CreatedAt returns the creation timestamp.

func (*ExposureEvent) Description

func (e *ExposureEvent) Description() string

Description returns the description.

func (*ExposureEvent) Details

func (e *ExposureEvent) Details() map[string]any

Details returns a copy of the details.

func (*ExposureEvent) EventType

func (e *ExposureEvent) EventType() EventType

EventType returns the event type.

func (*ExposureEvent) Fingerprint

func (e *ExposureEvent) Fingerprint() string

Fingerprint returns the deduplication fingerprint.

func (*ExposureEvent) FirstSeenAt

func (e *ExposureEvent) FirstSeenAt() time.Time

FirstSeenAt returns when the exposure was first seen.

func (*ExposureEvent) GetDetail

func (e *ExposureEvent) GetDetail(key string) (any, bool)

GetDetail gets a detail value by key.

func (*ExposureEvent) ID

func (e *ExposureEvent) ID() shared.ID

ID returns the exposure event ID.

func (*ExposureEvent) IsActive

func (e *ExposureEvent) IsActive() bool

IsActive returns true if the exposure is active.

func (*ExposureEvent) IsCritical

func (e *ExposureEvent) IsCritical() bool

IsCritical returns true if the exposure is critical severity.

func (*ExposureEvent) IsHighOrCritical

func (e *ExposureEvent) IsHighOrCritical() bool

IsHighOrCritical returns true if the exposure is high or critical severity.

func (*ExposureEvent) LastSeenAt

func (e *ExposureEvent) LastSeenAt() time.Time

LastSeenAt returns when the exposure was last seen.

func (*ExposureEvent) MarkFalsePositive

func (e *ExposureEvent) MarkFalsePositive(markedBy shared.ID, notes string) error

MarkFalsePositive marks the exposure as a false positive.

func (*ExposureEvent) MarkSeen

func (e *ExposureEvent) MarkSeen()

MarkSeen updates the last seen timestamp.

func (*ExposureEvent) Reactivate

func (e *ExposureEvent) Reactivate() error

Reactivate marks the exposure as active again.

func (*ExposureEvent) ResolutionNotes

func (e *ExposureEvent) ResolutionNotes() string

ResolutionNotes returns the resolution notes.

func (*ExposureEvent) Resolve

func (e *ExposureEvent) Resolve(resolvedBy shared.ID, notes string) error

Resolve marks the exposure as resolved.

func (*ExposureEvent) ResolvedAt

func (e *ExposureEvent) ResolvedAt() *time.Time

ResolvedAt returns when the exposure was resolved.

func (*ExposureEvent) ResolvedBy

func (e *ExposureEvent) ResolvedBy() *shared.ID

ResolvedBy returns who resolved the exposure.

func (*ExposureEvent) SetAssetID

func (e *ExposureEvent) SetAssetID(id *shared.ID)

SetAssetID sets the asset ID.

func (*ExposureEvent) SetDetail

func (e *ExposureEvent) SetDetail(key string, value any)

SetDetail sets a detail key-value pair.

func (*ExposureEvent) Severity

func (e *ExposureEvent) Severity() Severity

Severity returns the severity level.

func (*ExposureEvent) Source

func (e *ExposureEvent) Source() string

Source returns the source of the exposure event.

func (*ExposureEvent) State

func (e *ExposureEvent) State() State

State returns the current state.

func (*ExposureEvent) TenantID

func (e *ExposureEvent) TenantID() shared.ID

TenantID returns the tenant ID.

func (*ExposureEvent) Title

func (e *ExposureEvent) Title() string

Title returns the title.

func (*ExposureEvent) UpdateDescription

func (e *ExposureEvent) UpdateDescription(description string)

UpdateDescription updates the description.

func (*ExposureEvent) UpdateSeverity

func (e *ExposureEvent) UpdateSeverity(severity Severity) error

UpdateSeverity updates the severity level.

func (*ExposureEvent) UpdatedAt

func (e *ExposureEvent) UpdatedAt() time.Time

UpdatedAt returns the last update timestamp.

type Filter

type Filter struct {
	TenantID        *string     // Filter by tenant ID
	AssetID         *string     // Filter by asset ID
	EventTypes      []EventType // Filter by event types
	Severities      []Severity  // Filter by severities
	States          []State     // Filter by states
	Sources         []string    // Filter by sources
	Search          *string     // Full-text search across title and description
	FirstSeenAfter  *int64      // Filter by first seen after (unix timestamp)
	FirstSeenBefore *int64      // Filter by first seen before (unix timestamp)
	LastSeenAfter   *int64      // Filter by last seen after (unix timestamp)
	LastSeenBefore  *int64      // Filter by last seen before (unix timestamp)
}

Filter defines the filtering options for listing exposure events.

func NewFilter

func NewFilter() Filter

NewFilter creates an empty filter.

func (Filter) IsEmpty

func (f Filter) IsEmpty() bool

IsEmpty returns true if no filters are set.

func (Filter) WithAssetID

func (f Filter) WithAssetID(id string) Filter

WithAssetID adds an asset ID filter.

func (Filter) WithEventTypes

func (f Filter) WithEventTypes(types ...EventType) Filter

WithEventTypes adds an event types filter.

func (Filter) WithFirstSeenAfter

func (f Filter) WithFirstSeenAfter(timestamp int64) Filter

WithFirstSeenAfter adds a first seen after filter.

func (Filter) WithFirstSeenBefore

func (f Filter) WithFirstSeenBefore(timestamp int64) Filter

WithFirstSeenBefore adds a first seen before filter.

func (Filter) WithLastSeenAfter

func (f Filter) WithLastSeenAfter(timestamp int64) Filter

WithLastSeenAfter adds a last seen after filter.

func (Filter) WithLastSeenBefore

func (f Filter) WithLastSeenBefore(timestamp int64) Filter

WithLastSeenBefore adds a last seen before filter.

func (Filter) WithSearch

func (f Filter) WithSearch(search string) Filter

WithSearch adds a full-text search filter.

func (Filter) WithSeverities

func (f Filter) WithSeverities(severities ...Severity) Filter

WithSeverities adds a severities filter.

func (Filter) WithSources

func (f Filter) WithSources(sources ...string) Filter

WithSources adds a sources filter.

func (Filter) WithStates

func (f Filter) WithStates(states ...State) Filter

WithStates adds a states filter.

func (Filter) WithTenantID

func (f Filter) WithTenantID(tenantID string) Filter

WithTenantID adds a tenant ID filter.

type ListOptions

type ListOptions struct {
	Sort *pagination.SortOption
}

ListOptions contains options for listing (sorting).

func NewListOptions

func NewListOptions() ListOptions

NewListOptions creates empty list options.

func (ListOptions) WithSort

func (o ListOptions) WithSort(sort *pagination.SortOption) ListOptions

WithSort adds sorting options.

type Repository

type Repository interface {
	// Create persists a new exposure event.
	Create(ctx context.Context, event *ExposureEvent) error

	// CreateInTx persists a new exposure event within an existing transaction.
	// This is used for the transactional outbox pattern.
	CreateInTx(ctx context.Context, tx *sql.Tx, event *ExposureEvent) error

	// GetByID retrieves an exposure event by its ID.
	GetByID(ctx context.Context, id shared.ID) (*ExposureEvent, error)

	// GetByTenantAndID retrieves an exposure event by tenant and ID (tenant-scoped access control).
	GetByTenantAndID(ctx context.Context, tenantID, id shared.ID) (*ExposureEvent, error)

	// GetByFingerprint retrieves an exposure event by fingerprint within a tenant.
	GetByFingerprint(ctx context.Context, tenantID shared.ID, fingerprint string) (*ExposureEvent, error)

	// Update updates an existing exposure event.
	Update(ctx context.Context, event *ExposureEvent) error

	// Delete removes an exposure event by its ID.
	Delete(ctx context.Context, id shared.ID) error

	// List retrieves exposure events with filtering, sorting, and pagination.
	List(ctx context.Context, filter Filter, opts ListOptions, page pagination.Pagination) (pagination.Result[*ExposureEvent], error)

	// Count returns the total number of exposure events matching the filter.
	Count(ctx context.Context, filter Filter) (int64, error)

	// ListByAsset retrieves all exposure events for an asset.
	ListByAsset(ctx context.Context, assetID shared.ID, page pagination.Pagination) (pagination.Result[*ExposureEvent], error)

	// ExistsByFingerprint checks if an exposure event with the given fingerprint exists.
	ExistsByFingerprint(ctx context.Context, tenantID shared.ID, fingerprint string) (bool, error)

	// Upsert creates or updates an exposure event based on fingerprint.
	// If the fingerprint exists, updates last_seen_at. Otherwise creates a new event.
	Upsert(ctx context.Context, event *ExposureEvent) error

	// BulkUpsert creates or updates multiple exposure events based on fingerprint.
	// Uses batch INSERT with ON CONFLICT for better performance.
	BulkUpsert(ctx context.Context, events []*ExposureEvent) error

	// CountByState returns counts grouped by state for a tenant.
	CountByState(ctx context.Context, tenantID shared.ID) (map[State]int64, error)

	// CountBySeverity returns counts grouped by severity for a tenant.
	CountBySeverity(ctx context.Context, tenantID shared.ID) (map[Severity]int64, error)
}

Repository defines the interface for exposure event persistence.

type Severity

type Severity string

Severity represents the severity level of an exposure event.

const (
	SeverityCritical Severity = "critical"
	SeverityHigh     Severity = "high"
	SeverityMedium   Severity = "medium"
	SeverityLow      Severity = "low"
	SeverityInfo     Severity = "info"
)

func AllSeverities

func AllSeverities() []Severity

AllSeverities returns all valid severity levels.

func ParseSeverity

func ParseSeverity(str string) (Severity, error)

ParseSeverity parses a string into a Severity.

func (Severity) IsValid

func (s Severity) IsValid() bool

IsValid checks if the severity is valid.

func (Severity) Score

func (s Severity) Score() int

Score returns the numeric score for the severity (0-100).

func (Severity) String

func (s Severity) String() string

String returns the string representation.

type State

type State string

State represents the state of an exposure event.

const (
	StateActive        State = "active"
	StateResolved      State = "resolved"
	StateAccepted      State = "accepted"
	StateFalsePositive State = "false_positive"
)

func AllStates

func AllStates() []State

AllStates returns all valid states.

func ParseState

func ParseState(str string) (State, error)

ParseState parses a string into a State.

func (State) CanTransitionTo

func (s State) CanTransitionTo(target State) bool

CanTransitionTo checks if a state transition is valid.

func (State) IsClosed

func (s State) IsClosed() bool

IsClosed returns true if the state is not active.

func (State) IsOpen

func (s State) IsOpen() bool

IsOpen returns true if the state is active.

func (State) IsValid

func (s State) IsValid() bool

IsValid checks if the state is valid.

func (State) String

func (s State) String() string

String returns the string representation.

type StateHistory

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

StateHistory represents an audit trail entry for exposure state changes.

func NewStateHistory

func NewStateHistory(
	exposureEventID shared.ID,
	previousState State,
	newState State,
	changedBy *shared.ID,
	reason string,
) (*StateHistory, error)

NewStateHistory creates a new StateHistory entry.

func ReconstituteStateHistory

func ReconstituteStateHistory(
	id shared.ID,
	exposureEventID shared.ID,
	previousState State,
	newState State,
	changedBy *shared.ID,
	reason string,
	createdAt time.Time,
) *StateHistory

ReconstituteStateHistory recreates a StateHistory from persistence.

func (*StateHistory) ChangedBy

func (h *StateHistory) ChangedBy() *shared.ID

ChangedBy returns who changed the state.

func (*StateHistory) CreatedAt

func (h *StateHistory) CreatedAt() time.Time

CreatedAt returns when the change occurred.

func (*StateHistory) ExposureEventID

func (h *StateHistory) ExposureEventID() shared.ID

ExposureEventID returns the exposure event ID.

func (*StateHistory) ID

func (h *StateHistory) ID() shared.ID

ID returns the history entry ID.

func (*StateHistory) NewState

func (h *StateHistory) NewState() State

NewState returns the new state.

func (*StateHistory) PreviousState

func (h *StateHistory) PreviousState() State

PreviousState returns the previous state.

func (*StateHistory) Reason

func (h *StateHistory) Reason() string

Reason returns the reason for the change.

type StateHistoryRepository

type StateHistoryRepository interface {
	// Create persists a new state history entry.
	Create(ctx context.Context, history *StateHistory) error

	// ListByExposureEvent retrieves all state history for an exposure event.
	ListByExposureEvent(ctx context.Context, exposureEventID shared.ID) ([]*StateHistory, error)

	// GetLatest retrieves the most recent state change for an exposure event.
	GetLatest(ctx context.Context, exposureEventID shared.ID) (*StateHistory, error)
}

StateHistoryRepository defines the interface for state history persistence.

Jump to

Keyboard shortcuts

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