UAT: ReactiveEventBus does not persist events to durable audit_log SQLite table — only in-memory log maintained #3936

Open
opened 2026-04-06 07:37:36 +00:00 by freemo · 0 comments
Owner

Metadata

  • Branch: fix/reactive-event-bus-audit-log-persistence
  • Commit Message: fix(events): persist domain events to audit_log SQLite table in ReactiveEventBus
  • Milestone: None (Backlog)
  • Parent Epic: #397

Summary

The ReactiveEventBus in src/cleveragents/infrastructure/events/reactive.py only maintains a volatile in-memory audit log (deque). The specification requires that all domain events be persisted to the durable audit_log SQLite table. The current implementation explicitly acknowledges this gap in its docstring but does not implement the required persistence.

Expected Behavior (from spec)

Per docs/specification.md §Event System (line ~45834):

  1. Persistent Event Log: All events are written to the audit_log table for post-hoc analysis and compliance.

The ReactiveEventBus.emit() method should persist every event to the audit_log database table, in addition to pushing to the RxPY stream and dispatching to handlers.

The spec's ReactiveEventBus pseudocode shows:

def emit(self, event: DomainEvent) -> None:
    self._subject.on_next(event)
    self._persist_audit(event)  # ← persist to audit_log table
    for handler in self._subscriptions.get(event.event_type, []):
        handler(event)

Actual Behavior

The current ReactiveEventBus.emit() method (src/cleveragents/infrastructure/events/reactive.py, lines 95-137):

  1. Pushes to RxPY subject
  2. Only appends to in-memory deque (volatile, lost on restart)
  3. Dispatches to type-specific handlers

The class docstring explicitly acknowledges this:

"This is a volatile, in-memory log intended for runtime inspection and testing. It does not replace the durable audit_log SQLite table described in the specification (§Persistence Schema). Durable persistence is wired separately via the audit service layer."

However, the "audit service layer" wiring is not implemented — the ReactiveEventBus is registered as a singleton in the DI container without any audit persistence bridge.

Root Cause

The ReactiveEventBus was implemented without the _persist_audit() method that writes to the SQLite audit_log table. The comment says it's "wired separately" but no such wiring exists in the DI container or application bootstrap.

Impact

  • All domain events are lost on application restart
  • Compliance audit trail is incomplete — events are not durably persisted
  • Post-hoc analysis of plan execution is impossible without the audit log
  • The spec's audit log retention policy (audit.retention-days) cannot be enforced on non-existent records

Code Location

  • src/cleveragents/infrastructure/events/reactive.pyReactiveEventBus.emit()
  • src/cleveragents/application/container.py — DI container wiring

Subtasks

  • Implement _persist_audit(event: DomainEvent) method in ReactiveEventBus that writes to audit_log table
  • Wire AuditService or AuditRepository into ReactiveEventBus via DI
  • Alternatively, implement an AuditEventSubscriber that subscribes to all events and persists them
  • Verify audit log entries are created for all event types
  • Add integration tests verifying durable persistence
  • Verify coverage ≥ 97%

Definition of Done

  • All domain events emitted via ReactiveEventBus are persisted to the audit_log SQLite table
  • Events survive application restart
  • Integration tests verify durable persistence
  • PR merged
  • All nox stages pass
  • Coverage >= 97%

Backlog note: This issue was discovered during autonomous operation
on milestone v3.7.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.


Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/reactive-event-bus-audit-log-persistence` - **Commit Message**: `fix(events): persist domain events to audit_log SQLite table in ReactiveEventBus` - **Milestone**: None (Backlog) - **Parent Epic**: #397 ## Summary The `ReactiveEventBus` in `src/cleveragents/infrastructure/events/reactive.py` only maintains a volatile in-memory audit log (`deque`). The specification requires that all domain events be persisted to the durable `audit_log` SQLite table. The current implementation explicitly acknowledges this gap in its docstring but does not implement the required persistence. ## Expected Behavior (from spec) Per `docs/specification.md` §Event System (line ~45834): > 2. **Persistent Event Log**: All events are written to the `audit_log` table for post-hoc analysis and compliance. The `ReactiveEventBus.emit()` method should persist every event to the `audit_log` database table, in addition to pushing to the RxPY stream and dispatching to handlers. The spec's `ReactiveEventBus` pseudocode shows: ```python def emit(self, event: DomainEvent) -> None: self._subject.on_next(event) self._persist_audit(event) # ← persist to audit_log table for handler in self._subscriptions.get(event.event_type, []): handler(event) ``` ## Actual Behavior The current `ReactiveEventBus.emit()` method (`src/cleveragents/infrastructure/events/reactive.py`, lines 95-137): 1. ✅ Pushes to RxPY subject 2. ❌ Only appends to in-memory `deque` (volatile, lost on restart) 3. ✅ Dispatches to type-specific handlers The class docstring explicitly acknowledges this: > "This is a **volatile, in-memory** log intended for runtime inspection and testing. It does **not** replace the durable `audit_log` SQLite table described in the specification (§Persistence Schema). Durable persistence is wired separately via the audit service layer." However, the "audit service layer" wiring is not implemented — the `ReactiveEventBus` is registered as a singleton in the DI container without any audit persistence bridge. ## Root Cause The `ReactiveEventBus` was implemented without the `_persist_audit()` method that writes to the SQLite `audit_log` table. The comment says it's "wired separately" but no such wiring exists in the DI container or application bootstrap. ## Impact - All domain events are lost on application restart - Compliance audit trail is incomplete — events are not durably persisted - Post-hoc analysis of plan execution is impossible without the audit log - The spec's audit log retention policy (`audit.retention-days`) cannot be enforced on non-existent records ## Code Location - `src/cleveragents/infrastructure/events/reactive.py` — `ReactiveEventBus.emit()` - `src/cleveragents/application/container.py` — DI container wiring ## Subtasks - [ ] Implement `_persist_audit(event: DomainEvent)` method in `ReactiveEventBus` that writes to `audit_log` table - [ ] Wire `AuditService` or `AuditRepository` into `ReactiveEventBus` via DI - [ ] Alternatively, implement an `AuditEventSubscriber` that subscribes to all events and persists them - [ ] Verify audit log entries are created for all event types - [ ] Add integration tests verifying durable persistence - [ ] Verify coverage ≥ 97% ## Definition of Done - [ ] All domain events emitted via `ReactiveEventBus` are persisted to the `audit_log` SQLite table - [ ] Events survive application restart - [ ] Integration tests verify durable persistence - [ ] PR merged - [ ] All nox stages pass - [ ] Coverage >= 97% > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.7.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#397 Epic: Server & Autonomy Infrastructure
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#3936
No description provided.