Install

Works with Drupal: ^11.3 || ^12

Using Composer to manage Drupal site dependencies

Alternative installation files

Download tar.gz 1.46 MB
MD5: 2208d81fdeaac37df3bc002c86d6882e
SHA-1: f08b12f8b438a16b7bed13c481874fe436349e43
SHA-256: b9049c8132f29cbe5a1229394056e05f541c3176d8af7224f272ef40a6877740
Download zip 1.8 MB
MD5: 38bbad257dc177918b5ac549052fae18
SHA-1: bdfc7a6e7bdfad3c0ddc1368a35ccc83a6c40f95
SHA-256: 08cb21abc4fe4f4dcaca250b4e133518947a62a80eac7c974cbae6207a330aa9

Release notes

This release prepares the module for beta. Signing secrets and timestamp CA certificates can be pinned in settings.php, so a secret or certificate added through the database is refused. Every retention stage now holds a range to what was signed, so a database edit made before or during retention is recorded instead of purged away. Archive files can be opened again as Archived entries, and the entries list shows what the last verification found of each row.

Upgrading

Warning: no migration path. There is no update hook until the first beta release, so an existing install cannot be upgraded in place: reinstall the module. Uninstalling drops its tables, and with them every chained entry, segment and acknowledgment the site holds. Archive what you need to keep first; archive files written by earlier releases cannot be restored into this one.

The schema changes are:

  • audit_trail has a verdict column (one byte) and a chain_verdict index.
  • A new audit_trail_archived table holds the rows opened from archive files.
  • audit_trail_outbox stores a content_hmac and its secret_id in place of content_hash.
  • Segment and acknowledgment ids, a segment's row_count and its verification_failed_at_purge are 64-bit.

The archive file format changed: a file's footer records what the archive stage found and signs it with the rows, and each row line carries its signature. After upgrading, run drush audit_trail:verify --full once to fill the Check column.

New

  • Pinned secrets and certificates (#3620479). $settings['audit_trail_trusted_secrets'] and $settings['audit_trail_tsa_trusted_ca_certs'] list the trusted signing secrets and timestamp CA certificates by fingerprint. Once pinned, a secret that is not listed, or whose Key holds other bytes, verifies nothing and signs nothing, and a row naming a secret id nobody pinned reads as forged. The lines to paste are on the secrets page, the timestamp providers page, the status report and drush audit_trail:secret-fingerprints. Without the settings nothing changes, and the status report warns. See docs/trusted-secrets.md.
  • Archived entries (#3620479, #3620481). Reports » Audit trail » Archived entries, Open in archived entries on a segment, or drush audit_trail:archive-open opens archive files of any chain, several at once, to read and search their rows with the entries filters. Each row shows what its file says of it. Nothing there is part of a chain, and the operator closes the archives when done (drush audit_trail:archive-close). See docs/archived-entries.md.
  • A Check column on the entries list (#3620479, #3620480). Verification records what it found of each row, and the list shows it as a small dot: sound, broken, acknowledged, unchecked, or not verified yet. A Check filter lists one of them, every broken row for instance. The value is a convenience outside the signed payload: no check reads it, and the next walk over a row rewrites a wrong one.
  • Checking an archive file on its own (#3620479). drush audit_trail:archive-verify --path=<file> checks a file without a segment: its footer signature, its rows, the breaks it records and the signature over them.
  • Failed logins on the JSON routes (#3620475). audit_trail_user_auth records failed logins and password reset probes made through core's JSON login routes, behind a setting that leaves core's routes untouched when off.
  • A signed entry when a chain's data is wiped (#3620464). Clearing a chain records it on the chain it empties.

Changed

  • Retention records what it finds (#3620479). The archive stage checks every row it archives and writes the broken runs into the file; the live-purge reads them from the file it holds to the signed digest, and marks the segment unexplained or seals the acknowledgment covering it. A file with no record of its findings counts as broken over its whole range.
  • Import only an archive of the chain as it is (#3620479). An import is refused when the chain's own segment events still place a segment over the range (rebuild it with drush audit_trail:reindex-segments instead), when the footer is signed under a secret this site does not have, when the file's rows or recorded breaks no longer match their signature, or when a copy of rows still live is not signed. An archive of a chain cleared or rebuilt since is read in Archived entries.
  • The entries list fits the page (#3620480). An entry's message has a line of its own under the entry, in italic, and the date and time share one line, so the table no longer scrolls sideways.
  • Retention and auto-verify in services (#3620455). Their logic moved out of the cron hook classes; the module was also cleaned of duplicated code, unused wrappers and stale texts (#3620456, #3620457, #3620462, #3620463, #3620466, #3620482).

Fixed

  • Forged signatures and records. A segment naming a secret no secret has is refused before any walk crosses it (#3620473); the segment index is rebuilt only from events whose signature holds, and a staged outbox row is signed (#3620472); an acknowledgment covering its own record is ignored and a forged checkpoint is reported (#3620470, #3620471); a forged acknowledgment event inside an acknowledged range is checked (#3620474); a replaced checkpoint row is reported and outbox copies are matched on signed columns (#3620476).
  • Retention over edited rows. A purged segment is held to the rows at its ends, compaction checks what it folds, and a used secret cannot be deleted (#3620478); acknowledgments and the range check read the chain's previous row on a site with several chains (#3620458).
  • Archive files. A file with a value that is not text is read without a warning, each signing secret is read once per file instead of once per row, and the uploaded copy is always deleted (#3620482); every stream wrapper the web server serves is refused as an archive directory (#3620460); segment rows are read in bounded batches when archived and checked (#3620459).
  • Performance. Finding the first uncovered row walks the segment gaps instead of anti-joining the whole chain on every cron run (#3620451); the chain-write lock is held until a restore commits (#3620452).
  • Admin pages. Entity and user names on the entries pages respect label access (#3620453); the warning when every secret or TSA provider is retired says which (#3620454); six form defects, from archive import without private files to multibyte labels (#3620461); a chain plugin removed no longer hands its settings to the next one (#3620469); the Check reason and the message line are announced to screen readers (#3620482).
  • Bridges and configuration. A typed login name is bounded and cut where the user authentication bridge records it (#3620474, #3620477); a private file download over any method is recorded (#3620474); a chain without filter_other_loggers or shortened_original_length stays valid (#3620449); three defects from the third release audit (#3620468).
Created by: mably
Created on: 12 Nov 2026 at 13:45 UTC
Last updated: 12 Nov 2026 at 18:12 UTC
Bug fixes
New features

Other releases