Skip to content

Audit and keys

Option Default Purpose
$audit true models are audited unless they opt out ($auditable = false)
$auditTable, $auditChainTable anvil_audit_log, anvil_audit_chain tables of the log and its hash chain
$auditMaskedFields password, passphrase, secret, token, api_key, private_key, pin, otp, recovery, iban values of fields containing these names are masked
$auditMask '[masked]' replacement of masked values
$auditIgnoredFields created_at, updated_at fields left out of change sets
  • Masking is case-insensitive and matches substrings: password masks password_hash. Extend the list for sensitive fields of your domain (e.g. salary, diagnosis). Setting the property replaces the list, so repeat the defaults:

    public array $auditMaskedFields = [
    'password', 'passphrase', 'secret', 'token', 'api_key', 'private_key', 'pin', 'otp', 'recovery', 'iban',
    'salary', 'diagnosis',
    ];
  • Models add their own ignored fields with $auditIgnore.

  • Switching $audit off removes the traceability of changes; ISO 27001 and data protection usually require it.

What is logged and how the chain works: Audit log.

Option Default Purpose
$auditKey '' → derived from encryption.key key of the hash chain, anvil.auditKey in .env
$auditPreviousKeys '' previous audit keys, comma separated, oldest first; they only verify old entries
$rekeyers [] stores of sealed secrets of packages that anvil:rekey encrypts again after a rotation of encryption.key
.env
encryption.key = hex2bin:…
anvil.auditKey = base64:… # php spark anvil:audit:generate-key
anvil.auditPreviousKeys = base64:… # after a rotation
  • A separate $auditKey can be rotated without touching other encryption, see Key rotation.

  • Secrets that Anvil seals (TOTP, API secrets) are re-encrypted by php spark anvil:rekey after encryption.key changed. Stores of other sealed secrets implement Anvil\Security\Rekeyable (rekeyLabel(), rekey()) and are listed in $rekeyers. Packages register theirs with a registrar, e.g. AnvilIdoit its connection secrets; your application only lists its own stores:

    public array $rekeyers = [\App\Security\WebhookSecrets::class];

See Deployment → Keys and secrets.