Configuration and command reference

Copy Markdown View Source

Use this page when you need the exact application configuration Threadline reads. These settings are global to the :threadline application; pass operation-specific options directly to a public function when that function offers them.

The reference separates literal application keys from adapter-module options. That distinction matters: literal keys select Threadline behavior, while a configured adapter owns the options stored under its module name.

Runtime configuration

The following fourteen keys are Threadline's supported application-environment contract. An omitted key has the default or absence behavior stated here.

KeyPurpose and accepted shapeDefault or absence behaviorPrimary owner
config :threadline, ecto_repos: [MyApp.Repo]A non-empty list of Ecto repository modules. The first repository is the fallback used by Threadline's runtime and Mix tasks; explicit repo: options still take precedence where offered.[]; repository-dependent runtime children are not started, and commands that require a repository raise with setup guidance.Threadline and Getting Started
config :threadline, retention: [...]A keyword list for the global retention policy and its supervised pruner. Set enabled: true and exactly one positive keep_days: or max_age_seconds: value before destructive purge is allowed. delete_empty_transactions: defaults to true; runtime scheduling accepts interval_ms: and sleep_ms:.[]; scheduled pruning is disabled and Threadline.Retention.purge/1 returns {:error, :disabled}. When enabled, the pruner interval is 60 minutes and its between-batch sleep is 50 ms unless overridden.Threadline.Retention.Policy, Threadline.Retention, and Production Checklist
config :threadline, exports: [...]A keyword list for export lifecycle timing. retention_ttl_hours: controls terminal export expiry; cleanup_interval_ms: controls cleanup cadence; stale_running_cutoff_hours: controls when an abandoned running export is marked failed.[]; terminal exports expire after 168 hours, cleanup runs every 60 minutes, and running jobs are considered abandoned after 24 hours.Threadline.Export and Operator Surface
config :threadline, trigger_capture: [...]A keyword list or map whose tables: map configures capture-time exclude:, mask:, mask_placeholder:, store_changed_from:, except_columns:, and primary_key: rules per host table. primary_key: declares the key columns for a table with no primary key (a non-empty list of column names, such as ["post_id", "tag_id"] for a join table), enforced at migrate time against a qualifying unique index. Redaction is applied when trigger SQL is generated, not dynamically on each write.Missing configuration normalizes to an empty table map, so trigger generation uses no per-table capture overrides; a table with a real primary key needs no primary_key: entry. Malformed configuration raises ArgumentError (the health and coverage tasks stop with Mix.raise); it is never reported as a health finding.Domain Reference and Getting Started
config :threadline, verify_coverage: [...]A keyword list with a non-empty expected_tables: list of table-name strings. It defines the positive list checked by the coverage verification task.Missing, malformed, or empty configuration causes the verification task to raise instead of passing vacuously.Threadline.Verify.CoveragePolicy and Production Checklist
config :threadline, storage_adapter: MyApp.AuditStorageA module implementing Threadline.Storage. Threadline validates the adapter at application startup and uses it for background export persistence and delivery.Threadline.Storage.Local.Threadline.Storage; adapter details are documented under Adapter-module options
config :threadline, health: [...]A keyword list accepted by Threadline.Health.Policy: expected_uncovered_tables: adds intentionally uncovered tables and audit_anyway: removes names from that set. Both values are duplicate-free lists of strings.[]; only Threadline's built-in schema_migrations expected-uncovered baseline applies.Threadline.Health, Threadline.Health.Policy, and Operator Surface
config :threadline, coverage_poll_ms: 30_000A positive integer number of milliseconds between trigger-coverage refreshes in the mounted operator surface.30_000.Operator Surface
config :threadline, operator_surface_embed_fonts: falseA boolean controlling whether the operator surface embeds its bundled webfonts as data URIs.true; bundled fonts are embedded. false uses the documented system-font fallback chains.Operator Surface
config :threadline, export_status_poll_ms: 5_000A positive integer number of milliseconds between background-export status refreshes in the mounted operator surface.5_000.Operator Surface
config :threadline, export_queue_adapter: MyApp.AuditExportQueueA module implementing Threadline.ExportQueue. Threadline validates it at application startup and uses it to enqueue background exports.Threadline.ExportQueue.TaskAdapter.Threadline.ExportQueue; adapter details are documented under Adapter-module options
config :threadline, retention_poll_ms: 5_000A positive integer number of milliseconds between retention-history refreshes in the mounted operator surface.5_000.Operator Surface
config :threadline, operator_surface_embed_scripts: falseA boolean controlling the operator surface's inline, dependency-free copy helper.true; the copy helper is embedded. false removes the script and presents identifiers for native text selection.Operator Surface
config :threadline, storage_schema: "audit"A PostgreSQL identifier naming the schema that stores Threadline-owned tables and functions. Strings and atoms are accepted after identifier validation."public", your host's default schema, so an existing install keeps reading the tables it already has. A new install can opt into a dedicated schema such as "threadline"; set it before mix threadline.install, because the generated migrations freeze the choice.Threadline.StorageSchema and Getting Started

Known limitation: primary_key: only accepts bare identifiers

A declared primary_key: column name must match ^[A-Za-z_][A-Za-z0-9_]*$ (letters, digits, underscore, not starting with a digit) and be at most 63 bytes — the same rule Threadline applies to schema, table, and function identifiers. This is stricter than what PostgreSQL itself allows: a double-quoted identifier such as "1code", "post-id", or "post id" is legal DDL, and Threadline would capture it correctly if it were auto-detected as part of a real primary key. But that same column name cannot currently be declared through primary_key: for a table that has no real primary key — there is no quoting escape hatch in this option today.

If your join table (or other PK-less table) needs primary_key: and its key columns were created with quoted, non-bare names, rename the columns to bare identifiers before declaring the override, or create a real primary key / unique index over bare-identifier columns instead.

Advanced operator polling

The three polling keys control browser-facing LiveView refreshes only:

config :threadline, coverage_poll_ms: 30_000
config :threadline, export_status_poll_ms: 5_000
config :threadline, retention_poll_ms: 5_000

Set each to a positive integer number of milliseconds. These values do not change retention-pruner cadence, export cleanup cadence, or queue execution. Those schedules live in the :retention and :exports keyword lists described above. Polling test hooks and socket assigns are internal implementation details, not router mount options.

Adapter-module options

After selecting an adapter with :storage_adapter or :export_queue_adapter, Threadline reads a keyword list stored under that adapter module. This is a separate dynamic key class, not another literal atom key.

For example, the built-in S3 adapter requires a bucket:

config :threadline, storage_adapter: Threadline.Storage.S3
config :threadline, Threadline.Storage.S3, bucket: "my-audit-exports"

The built-in Oban queue adapter accepts :oban_name, :queue, and :worker_mod options:

config :threadline, export_queue_adapter: Threadline.ExportQueue.Oban

config :threadline, Threadline.ExportQueue.Oban,
  oban_name: Oban,
  queue: :threadline_exports

A custom adapter owns and documents its own keyword options. Threadline passes those options to the adapter's init/1 callback during application startup. Use the public Threadline.Storage and Threadline.ExportQueue behaviours as the implementation contracts; do not depend on another adapter's private options.

Commands available to host projects

Adding Threadline as a dependency makes these eleven Mix tasks available to the host project. Run them from the host project's root so they load its configuration and dependencies.

CommandUse it toImplementation owner
mix threadline.installGenerate the migration that creates Threadline's audit schema.Mix.Tasks.Threadline.Install
mix threadline.gen.triggersGenerate an Ecto migration that installs capture triggers on selected host tables.Mix.Tasks.Threadline.Gen.Triggers
mix threadline.gen.row_history_indexGenerate a non-blocking CREATE INDEX CONCURRENTLY migration that adds the row-history index to an install that predates it.Mix.Tasks.Threadline.Gen.RowHistoryIndex
mix threadline.verify_coverageFail a CI or deployment check when a table in :verify_coverage is missing, uncovered, or has an error-severity trigger finding.Mix.Tasks.Threadline.VerifyCoverage
mix threadline.health.coverageView trigger coverage and findings, as a table or JSON. Viewer by default (exits 0); --strict turns :error-severity findings into exit 1. --all-schemas checks every reportable schema at once instead of one --schema.Mix.Tasks.Threadline.Health.Coverage
mix threadline.continuityInspect and establish the explicit starting boundary for capture in an existing database.Mix.Tasks.Threadline.Continuity
mix threadline.retention.purgePreview or execute the configured batched retention purge. Preview before using --execute.Mix.Tasks.Threadline.Retention.Purge
mix threadline.exportExport captured audit rows to CSV or JSON using the same filter vocabulary as the timeline API.Mix.Tasks.Threadline.Export
mix threadline.incidentShow the changes and context linked to one audit transaction, in human-readable or JSON form.Mix.Tasks.Threadline.Incident
mix threadline.evidence.showShow the latest or historical Threadline evidence records and proof classifications.Mix.Tasks.Threadline.Evidence.Show
mix threadline.policy.showCompare configured capture redaction with the trigger policy deployed in PostgreSQL.Mix.Tasks.Threadline.Policy.Show

These tasks are the supported command interface for adopters. Their module pages and the linked guides define their options and safety boundaries.

Commands for this repository

Mix aliases belong to the project that defines them. Therefore none of the aliases below is installed into a host application when it adds Threadline as a dependency. They are supported contributor commands only when working in the Threadline repository.

Repository aliasRepository purpose
mix verify.formatCheck the formatter-owned source tree.
mix verify.credoRun the repository's Credo policy.
mix verify.dialyzerRun the configured Dialyzer analysis without rebuilding the PLT.
mix verify.testRun the root ExUnit suite, including every public documentation contract test.
mix verify.threadlineRun the configured positive-list trigger-coverage gate.
mix verify.releaseValidate the clean, taggable release shape, documentation, and Hex archive.
mix verify.topologyInvoke the repository-only PgBouncer topology task.
mix verify.exampleCompile and test the Phoenix reference application.
mix verify.example_browserRun the reference application's voting browser projects.
mix verify.example_browser_lightRun the focused light/system-theme browser lane.
mix verify.operator_stressRun the operator-surface stress browser specification.
mix verify.mechanicalCheck deterministic operator-surface mechanical constraints.
mix verify.critic_trustCheck the committed, deterministic critic-trust evidence without calling an LLM.
mix verify.hex_evaluatorCompile, migrate, and test the isolated Hex evaluator.
mix verify.benchRun the repository benchmark scripts.
mix verify.compile_no_optionalCompile without optional dependencies and treat warnings as errors.
mix verify.xref_cyclesFail if any compile-connected cycle exists between modules.
mix verify.flakeRe-run tests with fresh seeds until a failure appears or the repeat limit is reached.
mix test.setupPrepare example dependencies, then run the root test setup path.
mix test.resetRecreate the root test database before running setup.
mix ci.allRun the complete local equivalent of the required CI gates.

mix threadline.verify_topology is also repository-only. It requires the repository's PgBouncer test topology and is not part of the adopter command contract.

Maintainer-only commands

The following tools are shipped from source today but are not supported adopter or contributor interfaces. They operate on maintainer evidence, local credentials, or a repository-specific capture corpus:

  • mix critic.measure
  • mix critic.synth
  • mix verify.ui_critique
  • mix verify.capture
  • mix verify.operator_component_contracts

There are no additional internal Mix tasks or aliases in the current source inventory. Adding a task or alias requires placing it in exactly one of these classes and updating this reference.

Next steps