// Package evidence implements the FLUID evidence store. // // ArchitectureBlueprint.md section 26 requires append-only history, with // mutable summary views derived from immutable events. Auditability is a core // invariant (FluidAPIStandards.md section 25): the store must be able to answer // what changed, why, on what evidence, and how the prior state is restored. package evidence import ( "context" "errors" "time" "github.com/tegwick/fluid-core/internal/contract" ) // Store is the append-only evidence log plus the queries built on it. // // Nothing in this interface updates or deletes. That is deliberate: history // that can be rewritten is not evidence, and Blueprint section 28.1 gives the // evidence writer permission to append but not to revise. type Store interface { // AppendEvent records a lifecycle transition. AppendEvent(context.Context, contract.FluidEvent) error // Events returns matching events in occurrence order. Events(context.Context, EventFilter) ([]contract.FluidEvent, error) // WriteTelemetry records a normalized interaction event. WriteTelemetry(context.Context, contract.FluidTelemetry) error // Telemetry returns matching telemetry in occurrence order. Telemetry(context.Context, TelemetryFilter) ([]contract.FluidTelemetry, error) // PutRecord stores or supersedes a FLUID record (pressure, hypothesis, // revision, experiment, feedback, backend requirement). // // Records are summary state derived from events; the event log remains the // authority. A record may be rewritten, an event may not. PutRecord(ctx context.Context, kind contract.EntityKind, id string, body []byte) error // Record returns one stored record. Record(ctx context.Context, kind contract.EntityKind, id string) ([]byte, error) // Records returns every record of a kind, ordered by id. Records(ctx context.Context, kind contract.EntityKind) (map[string][]byte, error) Close() error } // ErrNotFound reports a record or event that does not exist. var ErrNotFound = errors.New("not found") // ErrImmutable reports an attempt to rewrite history. var ErrImmutable = errors.New("evidence events are append-only") // EventFilter narrows an event query. Zero values mean "no constraint". type EventFilter struct { EntityType contract.EntityKind EntityID string EventType string Since time.Time Until time.Time Limit int } // TelemetryFilter narrows a telemetry query. type TelemetryFilter struct { InterfaceID contract.InterfaceID Revision contract.RevisionID Experiment contract.ExperimentID Cohort contract.CohortID Kind contract.FluidTelemetryKind Since time.Time Until time.Time Limit int }