dulvac opened a new pull request, #3059:
URL: https://github.com/apache/jackrabbit-oak/pull/3059
Implementation half of OAK-12331. Pairs with #3058, which carries the
documentation; this PR touches no files under `oak-doc/`.
Draft for now: opening it early for feedback on the SPI shape before the
capture-site coverage grows.
## What this adds
A pluggable audit SPI, so a consumer bundle can observe repository
operations without patching Oak internals. Off by default behind the
`FT_OAK-12331` toggle. With the toggle off, or with no audit module
deployed, capture short-circuits through a NOOP sink.
The SPI lives in `oak-core-spi`, in the newly exported package
`org.apache.jackrabbit.oak.spi.audit`:
- `AuditEvent` / `AuditEventImpl`: immutable event carrying domain, type,
timestamp and payload
- `AuditEvents`: static facade over a pluggable `Sink`, NOOP until an audit
module installs one
- `AuditEventListener`: the consumer contract, selecting by domain and
ordering by rank
- `AuditEventEmitter`: OSGi-facing emitter for the fire-and-forget path
- `AuditBufferLifecycle`: session lifecycle callouts used by `MutableRoot`
`oak-security-spi` contributes the security domain name and the
user-management type vocabulary, in the newly exported
`org.apache.jackrabbit.oak.spi.security.audit` plus `UserAuditTypes`, so
listener bundles compile against a stable set of strings rather than the
producer-side helpers. The pipeline itself sits in `oak-core` under
`org.apache.jackrabbit.oak.security.audit` and stays bundle-internal.
## How it works
Capture sites buffer events per session in a `ThreadLocal`.
`AuditDrainObserver` runs as an `Observer` on the root NodeStore. Observers
fire after durable persistence and never for a failed merge, so a
dispatched event always corresponds to a persisted write. The drain is
destructive, so a store that invokes the observer twice for one merge
dedupes itself.
`CommitMetadataDecorator` stamps the three reserved `commit.*` keys at drain
time and overwrites anything a caller supplied. The fire-and-forget path
strips those keys instead. Their presence is therefore an attestation that
an event came from the commit-attached pipeline, which is what the tests in
`CommitMetadataDecoratorTest` pin.
An outer `Throwable` barrier in `contentChanged` keeps a failing listener
from surfacing as a commit failure to the merge caller. `CompositeObserver`
gives no per-observer isolation, so without the barrier a bad listener would
also break peer observers such as JCR observation.
`MutableRoot` drains on `refresh()` and on a failed merge. It deliberately
does not drain on `rebase()`, which keeps transient changes and replays them
on the new base; audit events captured alongside those surviving changes
have to survive with them.
`AuditConfigurationImpl` owns the lifecycle. It registers as
`AuditConfiguration` only, contributes no commit hooks, and is not a
`SecurityConfiguration`, so it stays out of
`SecurityProvider.getConfiguration()`. Under OSGi it publishes the observer
as a service for `ObserverTracker`; embedded callers get it from
`getDrainObserver()` and attach it themselves.
## Capture sites
Only the two `UserManagerImpl.onGroupUpdate` overloads so far, covering
single and bulk group membership changes. Path resolution failures there
drop the event and log rather than failing the surrounding update, with
repeat warnings demoted to DEBUG. More capture sites are meant to follow in
separate issues.
## Testing
| Module | Tests |
|---|---|
| `oak-core-spi` | 243, all passing |
| `oak-security-spi` | 1110, all passing |
| `oak-core` | 4873, all passing |
| `oak-run-commons` | 250, all passing |
`oak-benchmarks` compiles; it gains two runs measuring capture-site and
empty-commit overhead. Also adds an audit-enabled in-memory fixture to
`oak-run-commons`.
The `SecurityProviderRegistrationTest` change is a comment plus keeping the
existing count at 6, documenting that audit is deliberately not a
`SecurityConfiguration`. No assertion was weakened.
## Review notes
Both newly exported packages pass the `maven-bundle-plugin` baseline check.
Worth a look from anyone who has worked on `MutableRoot` or the observer
chain, since the commit-attached path depends on observer timing
guarantees.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]