StatifierPersistence.Ecto (StatifierPersistence v0.15.1)

Copy Markdown View Source

Compile-time Ecto configuration on the host's own module (ADR-0002).

A host declares its persistence module once:

defmodule MyApp.Persistence do
  use StatifierPersistence.Ecto, repo: MyApp.Repo
end

and gets, with zero further options: the resolved configuration readable via MyApp.Persistence.__statifier_persistence__/1, and four Ecto schema modules - MyApp.Persistence.Chart, MyApp.Persistence.Position, MyApp.Persistence.Execution, MyApp.Persistence.Input - over the statifier_charts / statifier_positions / statifier_executions / statifier_inputs tables with UXID string primary keys (chart_ / pos_ / exec_ / input_ prefixes).

Every knob is compile-time, on this use, never in application env (ADR-0002 decision 3), and the migrations helper consumes the same resolved configuration so schemas and DDL cannot disagree. See StatifierPersistence.Ecto.Config for the options (:key, :table_prefix, :tables, :prefix, :blob_type, :leading_columns).

The engine identity columns (content_hash, session_id, execution_id) are stored verbatim as strings and are never touched by the configured key scheme - ADR-0002 decision 1.

The chart schema also carries retired_at and retired_by, the two tombstone columns V07 adds (ADR-0012 decision 6). Both are nil on every chart that has not been retired, which is every chart until a host asks for one to be; a row carrying a retired_at has had its identity_blob and chart_blob nulled, and both chart doors answer for it with the retired arm rather than with its bytes.

The execution schema also carries metadata, the optional opaque map of host identities ADR-0006 grants, as a jsonb column (V02 of the migrations helper). It holds identities only, never personal data: :blob_type does not reach it, so anything filed there is at rest in the clear no matter how the blob columns are configured.

:blob_type reaches the payload columns and nothing else: identity_blob, chart_blob, position_blob, outcome_blob, and input_blob on the inputs table (ADR-0010 decision 4). A host wanting encryption at rest for those columns passes a custom Ecto.Type or Ecto.ParameterizedType there and gets it applied with zero further wiring. The identity and lookup columns (content_hash, session_id, execution_id, status, failure, and the input log's seq and door) stay plain regardless - the identity guard and the unique indexes depend on reading them back verbatim, and metadata stays jsonb regardless for the same reason: it is the column a host queries (ADR-0006 decision 3).

The inputs table is ADR-0010's per-execution input log: one row per input the interpreter saw, carrying the execution it belongs to, its dense zero-based seq, the public door it entered by, and the opaque input_blob. A nil input_blob is decision 6's closed marker. The log holds document payload - an event's data is the host's own values - which is why :blob_type reaches input_blob and why turning the log on is a data-retention decision rather than a debugging switch (StatifierPersistence.Storage.Adapter's moduledoc).