Ledger Overview | Docs | TitaniumGuard

Ledger Overview

Ledger Documentation

TitaniumGuard Ledger is delivered as a PostgreSQL extension, not a standalone service. The current repository ships versioned PostgreSQL packaging for PostgreSQL 16, 17, and 18.

What Ledger does now

  • Adds opt-in ledgering to specific tables inside PostgreSQL
  • Computes a hash chain for inserted rows and optional deterministic backfill
  • Stores ledger metadata in table columns managed by the extension
  • Tracks checkpoints, schema history, table policies, and external anchor records inside the extension schema
  • Rejects UPDATE and DELETE on protected tables and installs a DDL event trigger for guardrails
  • Ships both Linux host-install packages and published PostgreSQL container images on GHCR

Exposed SQL functions

  • ledger_status() checks whether the extension is installed in the current database.
  • ledger_version() returns the installed tg_ledger extension version from PostgreSQL metadata.
  • ledger_enable(table_identifier text, backfill boolean default false, order_by text default null) adds ledger columns/triggers and supports deterministic backfill for existing rows.
  • ledger_disable(table_identifier text) removes those triggers and drops the ledger columns from the table.
  • ledger_register_checkpoint_policy(table_identifier text, frequency bigint) configures automatic checkpoint cadence.
  • ledger_unregister_checkpoint_policy(table_identifier text) disables automatic checkpointing for a table.
  • ledger_set_policy(table_identifier text, ...) upserts table-level policy controls.
  • ledger_get_policy(table_identifier text) reads active table-level policy controls.
  • ledger_list_checkpoints(table_identifier text) lists recorded checkpoints for a table.
  • ledger_create_checkpoint(table_identifier text) creates an ad-hoc checkpoint at the current head.
  • ledger_export_proof(table_identifier text, start_seq bigint, end_seq bigint) exports a proof bundle for a sequence range.
  • ledger_debug_row(table_identifier text, seq bigint) returns canonical payload and hash-debugging data for one row.
  • ledger_compute_schema_fingerprint(table_identifier text) returns the canonical schema definition/hash for a table.
  • ledger_get_active_schema(table_identifier text) returns the active schema-history entry.
  • ledger_list_schema_history(table_identifier text) lists schema-history entries in sequence order.
  • ledger_get_schema_for_seq(table_identifier text, seq bigint) resolves the schema entry used for a specific sequence.
  • ledger_export_anchor_payload(table_identifier text, checkpoint_to_seq bigint) exports the serialized payload used for external anchoring.
  • ledger_export_anchor_signing_payload(table_identifier text, checkpoint_to_seq bigint) returns the signing digest for an anchor payload.
  • ledger_verify_anchor_payload(table_identifier text, checkpoint_to_seq bigint, expected_anchor_hash bytea) rechecks a computed anchor hash.
  • ledger_register_anchor(...), ledger_update_anchor_status(...), ledger_attach_anchor_signature(...), and ledger_list_external_anchors(...) manage anchor records and signatures.
  • ledger_check_hardening(table_identifier text) reports whether required hardening controls remain intact.
  • ledger_verify_table(table_identifier text) runs full-table structural and hash-chain verification.
  • ledger_verify_range(table_identifier text, start_seq bigint, end_seq bigint) verifies a bounded sequence range.
  • ledger_verify_progress(job_id text) returns progress/status for resumable verification jobs. The current implementation reports UNAVAILABLE because background persistence is not shipped yet.
  • ledger_verify_from_checkpoint(table_identifier text, checkpoint_to_seq bigint) verifies from a stored checkpoint head forward.
  • ledger_table_head(table_identifier text) returns row-count/head-hash style operational signals.
  • ledger_table_heads view provides quick operational per-table head/checkpoint/schema visibility.

The trigger functions exist for PostgreSQL to call internally; operators should use the SQL functions above rather than invoking trigger wrappers directly.

Table behavior

When you enable Ledger on a table, the extension manages these columns:

  • ledger_seq BIGINT
  • ledger_ts TIMESTAMPTZ
  • row_hash BYTEA
  • prev_hash BYTEA

It also installs:

  • A BEFORE INSERT trigger that computes the chained hash for each new row
  • Automatic checkpoint insertion on configured sequence boundaries
  • A BEFORE UPDATE OR DELETE trigger that rejects in-place mutation
  • A database-level DDL event trigger that blocks destructive changes against ledger-enabled tables

Operational notes

  • Existing rows are backfilled when you enable Ledger, using the same hash-chain inputs as insert-time ledgering.
  • Schema history is recorded at enablement and on schema-affecting DDL so verification can use sequence-appropriate schema fingerprints.
  • External anchor helpers are available now, but operators still own the surrounding publication workflow.
  • PostgreSQL continues to handle replication, backups, permissions, and transaction semantics.
  • Today the extension supports PostgreSQL only.

Next steps