app

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: May 30, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package app holds Hallmark's usecases and the repository ports they depend on. Persistence and transport adapters implement these ports.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuditEventFilter

type AuditEventFilter struct {
	ActorID      string
	ResourceType string
	ResourceID   string
	Action       string
	From         *time.Time
	To           *time.Time
	Limit        int
}

AuditEventFilter narrows a Query over the stream. Zero-value fields are not constrained; From/To bound the timestamp range inclusively.

func (AuditEventFilter) Matches

func (f AuditEventFilter) Matches(e domain.AuditEvent) bool

Matches reports whether an event satisfies the filter. It's the in-memory twin of QueryOptions used by the live broker, so a subscriber and a query with the same filter select the same events. Pure — unit-tested.

func (AuditEventFilter) QueryOptions

func (f AuditEventFilter) QueryOptions() []search.Option

QueryOptions translates a filter into the kit search options the repository applies. Newest-first ordering and a defaulted limit are part of the stream's read contract, so they live here rather than in the db layer.

type AuditEventRepository

AuditEventRepository persists and reads the append-only event stream. List backs the JSON:API REST surface (filters parsed from the request); Query backs the gRPC surface (a typed filter). Both read the same rows.

type AuditEventUsecase

type AuditEventUsecase interface {
	repository.Getter[domain.AuditEvent]
	repository.Lister[domain.AuditEvent]
	Append(ctx context.Context, event domain.AuditEvent) (domain.AuditEvent, error)
	Query(ctx context.Context, f AuditEventFilter) (resource.ListResponse[domain.AuditEvent], error)
	// Subscribe opens a filtered live feed of appended events. It errors when
	// the service runs without a broker (live tail disabled).
	Subscribe(f AuditEventFilter) (*Subscription, error)
}

AuditEventUsecase is the ingest + read surface for the stream. Append validates and records one event; Query/List read with an applied filter.

type AuditEventUsecaseOption

type AuditEventUsecaseOption func(*auditEventUsecase)

AuditEventUsecaseOption configures the usecase.

func WithBroker

func WithBroker(b *Broker) AuditEventUsecaseOption

WithBroker enables the live tail: Subscribe hands out feeds backed by this broker. The broker should also be registered in the Fanout so appended events reach it.

func WithFanout

func WithFanout(f *Fanout) AuditEventUsecaseOption

WithFanout fans every appended event out to the registered forwarders.

type Broker

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

Broker is the in-process fan-out hub behind the live tail. It implements Forwarder, so registering it in the Fanout makes every appended event available to subscribers; Subscribe hands a caller a filtered channel.

func NewBroker

func NewBroker() *Broker

func (*Broker) Forward

func (b *Broker) Forward(ctx context.Context, event domain.AuditEvent) error

Forward publishes an event to every matching subscriber, non-blocking: a full subscriber channel drops the event so one slow consumer never stalls ingest or the other subscribers.

func (*Broker) Name

func (b *Broker) Name() string

func (*Broker) Subscribe

func (b *Broker) Subscribe(filter AuditEventFilter) *Subscription

Subscribe registers a filtered live feed and returns its Subscription.

type Fanout

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

Fanout delivers each event to every registered forwarder, best-effort: a forwarder failure is logged and never blocks ingest or the others. (Async queueing is a later refinement.)

func NewFanout

func NewFanout(forwarders ...Forwarder) *Fanout

func (*Fanout) Forward

func (f *Fanout) Forward(ctx context.Context, event domain.AuditEvent)

type Forwarder

type Forwarder interface {
	Name() string
	Forward(ctx context.Context, event domain.AuditEvent) error
}

Forwarder fans a stored audit event out to an external sink (Kafka, NATS, S3, a SIEM…). Built-in: LogForwarder. Others satisfy the same port.

type LogForwarder

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

LogForwarder is the zero-config forwarder: it writes events to the log. A useful default and a template for real sinks.

func NewLogForwarder

func NewLogForwarder() *LogForwarder

func (*LogForwarder) Forward

func (f *LogForwarder) Forward(ctx context.Context, e domain.AuditEvent) error

func (LogForwarder) Name

func (LogForwarder) Name() string

type PartitionStore

type PartitionStore interface {
	ListMonthlyPartitions(ctx context.Context) ([]string, error)
	DropPartition(ctx context.Context, name string) error
}

PartitionStore lists and drops the monthly audit-event partitions.

type RetentionSweeper

type RetentionSweeper interface {
	Sweep(ctx context.Context, before time.Time) (int, error)
}

RetentionSweeper drops monthly partitions whose entire month precedes the cutoff — TTL enforced by dropping whole partitions, not row deletes (the table is append-only).

func NewRetentionSweeper

func NewRetentionSweeper(partitions PartitionStore) RetentionSweeper

type Subscription

type Subscription struct {
	C <-chan domain.AuditEvent
	// contains filtered or unexported fields
}

Subscription is a live feed of matching events. Close detaches it and releases the channel; callers must Close when done (e.g. on stream end).

func (*Subscription) Close

func (s *Subscription) Close()

Close detaches the subscription. It's safe to call more than once.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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