Problem/Motivation
log() writes an unsigned row rather than dropping the entry when the configured signing key will not resolve. That is the right policy for ordinary auditing: an unsigned record is better than a missing one.
Evidence-required consumers invert that policy. If a governed mutation must not proceed without a signed precommit, an unsigned row is a failed guarantee. Those consumers can only check the key, append, and re-check. That narrows but cannot close the race in which the key vanishes during the append and returns after. They also have to replay the chain's key resolution themselves, which drifts if the chain's resolution changes.
Proposed resolution
Add two methods on AuditChainLoggerInterface:
logKeyed($channel, $operation, $metadata = [])— appends only when the row will be HMAC-signed with the currently configured key. If no key resolves, throwAuditChainSigningUnavailableExceptionand write nothing. Key resolution is re-checked inside the chain lock so a vanishing key cannot produce an unkeyed row on this path.signingStatus()— returns{keyed, key_id}from the chain's own key resolution, for cheap precondition checks and status reporting.
Ordinary log() is unchanged.
Remaining tasks
- Land the interface methods and kernel tests on 1.x. Done in 1.x-dev.
- Ship in 1.6.0.
User interface changes
None.
API changes
Additive methods on AuditChainLoggerInterface. Existing log() callers are unaffected.
Data model changes
None.
Comments
Comment #2
jmcerdaShipped in 1.6.0.
https://www.drupal.org/project/audit_chain/releases/1.6.0
The project page now documents
logKeyed()andsigningStatus()under Evidence-required consumers.