Some checks failed
ci / build (push) Has been cancelled
Completes FLUID-WP-0003. The evidence store is append-only at the database, not by convention in Go: a trigger blocks UPDATE and DELETE on fluid_events in both SQLite and Postgres, so the guarantee binds a psql session and the CLI equally, not just callers who go through the Go API. Records are derived summary state and may be superseded; the event log stays the authority. The intent store makes a recorded version immutable and content addressed, since reassigning what governed a revision after the fact would break the one audit question Blueprint 27 exists to answer. The unfilled InterfaceEvolutionIntent template is rejected rather than defaulted, because a template still listing every FLUID-N mode has not been completed and defaulting it would pick a permissive authority by accident. The CLI reads the evidence store directly rather than through the control-plane API, so an operator can reconstruct history when the control plane is down. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014KmVxhJ35tCo7rE7UnLwWu Assistant: claude-code Assistant-Model: opus Assistant-Process: 1116572@bnt-lap001 Assistant-Session: 8ba9bb93-a72a-4883-b189-2499cce5c400
73 lines
2.6 KiB
Go
73 lines
2.6 KiB
Go
// 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
|
|
}
|