# Phase 3 Event Bus And Automation Foundation Report

Date: 2026-05-21

Status: implemented with bounded wiring.

## Scope Decision

Phase 3 follows the approved safety posture:

- Safety over coverage.
- Lifecycle events exist as contracts before broad automation grows around them.
- Current emitters are wired only from extracted Actions and clear, tested seams.
- Transactional workflow facts dispatch after commit.
- Listener examples stay idempotent and non-mutating in this phase.
- Legacy enrollment, payment, attendance, and broad Corporate workflows are not rewritten here.

## Implementation Plan

The implementation plan is stored in:

- `docs/superpowers/plans/2026-05-21-event-bus-automation-foundation.md`

The approved design is stored in:

- `docs/superpowers/specs/2026-05-21-event-bus-automation-foundation-design.md`

The plan executed in four slices:

1. Lock the EventBus contract with architecture tests.
2. Add readonly scalar lifecycle events and safe after-commit emitters.
3. Add listener provider, idempotency foundation, and architecture checks.
4. Document event catalog, listener rules, planned emitters, and verify regressions.

## Implemented Event Contracts

Phase 3 creates or normalizes lifecycle contracts for:

- Enrollments:
  - `EnrollmentCreated`
  - `EnrollmentConfirmed`
  - `EnrollmentCancelled`
  - `DepositPaymentApproved`
- Finance:
  - `DepositPaymentStarted`
  - `PaymentReceiptUploaded`
  - `BalancePaymentCompleted`
- Attendance and Scheduling:
  - `AttendanceSessionCreated`
  - `AttendanceMarked`
  - `StudentNoShowDetected`
- Corporate:
  - `B2bLeadCreated`
  - `B2bLeadConverted`
  - `ProposalSent`
  - `ProposalAccepted`
  - `AgreementActivated`
  - `CorporateCohortStarted`
  - `CorporateReportGenerated`
  - `CorporateInvoiceIssued`
  - `CorporatePaymentAllocated`
- WhatsApp:
  - `WhatsAppLeadCreated`
  - `WhatsAppConversationAssigned`
  - `WhatsAppReplySent`
- Events/Webinars:
  - `EventRegistrationCreated`
  - `WebinarReminderTriggered`
  - `WebinarAttended`
- Tracking:
  - `ConversionTracked`
  - `FunnelStepCompleted`

The contracts use readonly scalar payloads and avoid Eloquent model payloads, Livewire state, provider payload dumps, tokens, and private file paths.

## Current Safe Wiring

The current emitters intentionally stay narrow:

| Action | Event | Dispatch rule |
| --- | --- | --- |
| `ConvertB2bLeadToOrganizationAction` | `B2bLeadConverted` | Explicit `DB::afterCommit()` after conversion transaction |
| `CreateB2bLeadFromConversationAction` | `WhatsAppLeadCreated` | Explicit `DB::afterCommit()` only when a new lead is created |
| `SendWhatsAppReplyAction` | `WhatsAppReplySent` | Explicit `DB::afterCommit()` after message persistence |
| `CreateAttendanceSessionAction` | `AttendanceSessionCreated` | Explicit `DB::afterCommit()` after session/audit transaction |

The rest of the lifecycle contracts are documented planned emitters. They should be wired only when the owning workflow has a safe Action/service seam and focused regression coverage.

## Listener And Idempotency Foundation

Phase 3 adds:

- `app/Domain/Common/Automation/ListenerIdempotency.php`
- `app/Domain/Tracking/Listeners/TrackB2bLeadConverted.php`
- `app/Providers/DomainEventBusServiceProvider.php`

`TrackB2bLeadConverted` is the first event-driven listener slice:

- queued
- after-commit aware
- retry/backoff configured
- guarded by `ListenerIdempotency`
- tracking-only and non-mutating

## Architecture Guardrails

`php artisan app:architecture-check` now reports baseline findings for:

- direct Livewire notification/provider side effects
- direct Livewire tracking side effects
- direct WhatsApp provider calls from non-WhatsApp Actions
- direct listener writes to Enrollment or Payment state

The scans remain baseline-first because existing legacy debt still needs incremental remediation.

Phase 3 also excludes owned Messaging WhatsApp provider contracts from the non-owner WhatsApp Action scan so the command reports actionable debt instead of adapter false positives.

## Documentation Produced

Phase 3 documentation now includes:

- `docs/event_catalog.md`
  - event owner
  - payload summary
  - current emitter or planned emitter
  - listener status
  - automation and idempotency notes
- `docs/event_driven_architecture.md`
  - event lifecycle shape
  - after-commit rule
  - listener boundaries
  - retry/failure posture
  - tracking and notification direction
- `docs/domain_boundaries.md`
  - updated EventBus and architecture-check cross references

## Verification

The regression verification command executed for the bounded slice:

```bash
php artisan test tests/Feature/Architecture/DomainBoundaryTest.php tests/Feature/Architecture/EventBusTest.php tests/Feature/Architecture/AutomationBoundaryTest.php tests/Feature/Architecture/WorkflowActionTest.php tests/Feature/Admin/CohortSessionsPageTest.php tests/Feature/WhatsApp/WhatsAppDirectIntegrationTest.php
```

Observed result:

- 35 tests passed.
- 298 assertions passed.

Syntax checks were also run for the touched listener, provider, architecture-check, event, and Action PHP files.

## Architecture Check Result

The baseline command executed:

```bash
php artisan app:architecture-check
```

Observed result after the Phase 3 scan refinement:

- Command completed in baseline mode.
- 22 findings remain.

Current reported debt is concentrated in:

- WhatsApp enrollment journey direct Enrollment/Payment write checks.
- Registration and Student Livewire tracking side-effect checks.

Those findings are intentionally not refactored in Phase 3 because the approved scope forbids broad legacy rewrites.

## Recommended Next Wiring Slices

The next safe event wiring steps should be chosen one workflow at a time:

1. Extract or identify a payment Action with focused deposit approval tests before wiring `DepositPaymentApproved`.
2. Extract attendance mark/no-show Actions before wiring `AttendanceMarked` and `StudentNoShowDetected`.
3. Move selected Registration Livewire tracking calls behind lifecycle facts after the enrollment/payment seam is protected.
4. Wire Corporate proposal/agreement/invoice facts after each workflow Action has focused permission and state-transition tests.

