auditstore

package
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package auditstore owns the heterogeneous audit persistence boundary. Public consumers read typed audit records; this infrastructure model is not a DTO.

Index

Constants

This section is empty.

Variables

View Source
var Entries = orm.Define("foundry_audit", func(b orm.Builder[Entry], m *Entry) EntryTable {
	table := orm.TableOf(b, &m.ID)
	return EntryTable{Table: table, ID: table.Key(), Sequence: orm.NumberOf(b, &m.Sequence), Area: orm.TextOf(b, &m.Area), Operation: orm.ColumnOf(b, &m.Operation), Action: orm.TextOf(b, &m.Action), Version: orm.NumberOf(b, &m.Version), Subject: orm.NullableJSONOf(b, &m.Subject), SubjectKey: orm.NullableTextOf(b, &m.SubjectKey), Payload: orm.JSONOf(b, &m.Payload), Redacted: orm.ColumnOf(b, &m.Redacted), Redaction: orm.NumberOf(b, &m.Redaction), Origin: orm.JSONOf(b, &m.Origin), ActorKey: orm.NullableTextOf(b, &m.ActorKey), Correlation: orm.NullableTextOf(b, &m.Correlation), RequestMethod: orm.TextOf(b, &m.RequestMethod), RequestRoute: orm.TextOf(b, &m.RequestRoute), CreatedAt: orm.TimeOf(b, &m.CreatedAt)}
})

Entries owns the immutable Entry declaration. Example: orm.First(ctx, tx, Entries.Query()).

Functions

func Activities

func Activities(q orm.Query[Entry]) rows.Query[Entry, Activity]

Activities selects only the declared Activity fields. Example: Activities(Entries.Query()).All(ctx,tx).

func CountBefore

func CountBefore(ctx context.Context, executor database.Executor, area string, cutoff temporal.DateTime) (int64, error)

CountBefore counts the entries Prune would remove for area and cutoff without reading payloads. It uses the same predicate as Prune.

func Page

func Page(ctx context.Context, executor database.Executor, q orm.Query[Entry], request orm.PageRequest) (orm.PageResult[Entry], error)

Page retains the ordinary query layer's count/snapshot and row-limit contract. Rows are newest first by database insertion sequence, so writes made in one transaction keep their actual order despite sharing a transaction timestamp.

func Prune

func Prune(ctx context.Context, tx *database.Tx, area string, cutoff temporal.DateTime, limit int) (int64, error)

Prune selects a bounded oldest window and removes only that window through the existing typed set-based write compiler. No payloads are hydrated and no per-model observers run. A concurrent pruner may remove fewer rows.

Types

type Activity

type Activity struct {
	ID            model.ID[Entry]
	Sequence      int64
	Area          string
	Operation     lifecycle.Operation
	Action        string
	Version       uint32
	Subject       value.Nullable[value.JSON[model.Identity]]
	Origin        value.JSON[attribution.Origin]
	Correlation   value.Nullable[string]
	RequestMethod string
	RequestRoute  string
	CreatedAt     temporal.DateTime
}

Activity is the payload-free projection used by heterogeneous timelines.

func RecentActivity

func RecentActivity(ctx context.Context, executor database.Executor, q orm.Query[Entry], before int64, limit int) ([]Activity, error)

RecentActivity is Recent without selecting or decoding stored payloads.

func (Activity) Format

func (Activity) Format(state fmt.State, _ rune)

type Entry

type Entry struct {
	ID            model.ID[Entry]
	Sequence      int64 `foundry:"default=database"`
	Area          string
	Operation     lifecycle.Operation
	Action        string
	Version       uint32
	Subject       value.Nullable[value.JSON[model.Identity]]
	SubjectKey    value.Nullable[string] `foundry:"default=database"`
	Payload       value.JSON[json.RawMessage]
	Redacted      bool
	Redaction     uint8
	Origin        value.JSON[attribution.Origin]
	ActorKey      value.Nullable[string] `foundry:"default=database"`
	Correlation   value.Nullable[string]
	RequestMethod string
	RequestRoute  string
	CreatedAt     temporal.DateTime `foundry:"default=database"`
}

Entry stores either a model operation or a versioned domain action. Model capture owns field redaction; domain capture owns its document redaction flag. Redaction records the sensitive-name policy that wrote the row. Sequence is the database-assigned insertion order. SubjectKey and ActorKey are generated lookup keys derived from Subject and Origin; they are never written directly. Registration never installs audit observers for this private storage model.

func Append

func Append(ctx context.Context, tx *database.Tx, draft []orm.Assignment[Entry]) (Entry, error)

Append requires already validated, captured input. Normal declaration writes retain savepoint behavior and never commit the supplied outer transaction.

func Recent

func Recent(ctx context.Context, executor database.Executor, q orm.Query[Entry], before int64, limit int) ([]Entry, error)

Recent reads at most limit complete rows newest first, strictly before the supplied sequence when one is given. It is the keyset step of typed history.

func (Entry) Format

func (Entry) Format(state fmt.State, _ rune)

type EntryTable

type EntryTable struct {
	// Table provides model queries and writes. Example: orm.First(ctx, tx, Entries.Query()).
	orm.Table[Entry, model.ID[Entry]]
	// ID binds Entry.ID.
	// Example: orm.KeySet(Entries.ID, id).
	ID orm.Key[Entry, model.ID[Entry]]
	// Sequence binds Entry.Sequence. Omission retains the database default.
	// Example: orm.NumberSet(Entries.Sequence, sequence).
	Sequence orm.Number[Entry, int64]
	// Area binds Entry.Area.
	// Example: orm.TextSet(Entries.Area, area).
	Area orm.Text[Entry, string]
	// Operation binds Entry.Operation.
	// Example: orm.ColumnSet(Entries.Operation, operation).
	Operation orm.Column[Entry, lifecycle.Operation]
	// Action binds Entry.Action.
	// Example: orm.TextSet(Entries.Action, action).
	Action orm.Text[Entry, string]
	// Version binds Entry.Version.
	// Example: orm.NumberSet(Entries.Version, version).
	Version orm.Number[Entry, uint32]
	// Subject binds Entry.Subject.
	// Example: orm.NullableJSONSetNull(Entries.Subject).
	Subject orm.NullableJSON[Entry, model.Identity]
	// SubjectKey binds Entry.SubjectKey. Omission retains the database default.
	// Example: orm.NullableTextSetNull(Entries.SubjectKey).
	SubjectKey orm.NullableText[Entry, string]
	// Payload binds Entry.Payload.
	// Example: encoded, err := value.NewJSON(payload); if err == nil { _ = orm.JSONSet(Entries.Payload, encoded) }.
	Payload orm.JSON[Entry, json.RawMessage]
	// Redacted binds Entry.Redacted.
	// Example: orm.ColumnSet(Entries.Redacted, redacted).
	Redacted orm.Column[Entry, bool]
	// Redaction binds Entry.Redaction.
	// Example: orm.NumberSet(Entries.Redaction, redaction).
	Redaction orm.Number[Entry, uint8]
	// Origin binds Entry.Origin.
	// Example: encoded, err := value.NewJSON(origin); if err == nil { _ = orm.JSONSet(Entries.Origin, encoded) }.
	Origin orm.JSON[Entry, attribution.Origin]
	// ActorKey binds Entry.ActorKey. Omission retains the database default.
	// Example: orm.NullableTextSetNull(Entries.ActorKey).
	ActorKey orm.NullableText[Entry, string]
	// Correlation binds Entry.Correlation.
	// Example: orm.NullableTextSetNull(Entries.Correlation).
	Correlation orm.NullableText[Entry, string]
	// RequestMethod binds Entry.RequestMethod.
	// Example: orm.TextSet(Entries.RequestMethod, requestMethod).
	RequestMethod orm.Text[Entry, string]
	// RequestRoute binds Entry.RequestRoute.
	// Example: orm.TextSet(Entries.RequestRoute, requestRoute).
	RequestRoute orm.Text[Entry, string]
	// CreatedAt preserves an explicit creation time; omitted values use the database default.
	// Example: orm.TimeSet(Entries.CreatedAt, createdAt).
	CreatedAt orm.Time[Entry, temporal.DateTime]
}

EntryTable binds the persisted Entry columns. Example: Entries.Query().Limit(10).

Jump to

Keyboard shortcuts

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