task ep.1.3.md

This commit is contained in:
phaichayon
2026-07-13 11:00:49 +07:00
parent e96320a24d
commit d78c56148e
18 changed files with 2944 additions and 8 deletions

View File

@@ -0,0 +1,211 @@
# Task EP.1.3 Business Event Foundation - 2026-07-13
## Scope
- introduced canonical Business Event contract
- added machine-readable registry, alias resolution, ownership metadata, naming rules, and payload validation
- added transport-independent publisher abstraction and in-process dispatcher
- added idempotent subscriber handling and unsupported-version detection
- published initial Activity lifecycle business events from Activity service layer
- documented projection consumer contracts, event sequence matrix, replay readiness, compatibility mapping, and versioning strategy
- preserved existing notification, approval, follow-up, dashboard, report, and audit behavior
## Review Summary
Reviewed before and during implementation:
- `AGENTS.md`
- `plans/task-ep.1.3.md`
- `docs/standards/task-catalog.md`
- `docs/standards/project-foundations.md`
- `docs/standards/architecture-rules.md`
- `docs/standards/ui-ux-rules.md`
- `docs/standards/task-review-checklist.md`
- `docs/security/crm-authorization-boundaries.md`
- `docs/implementation/task-ep1.1-activity-domain-foundation-2026-07-10.md`
- `docs/implementation/task-ep1.2-activity-integration-legacy-followup-adapter-2026-07-13.md`
- existing Activity lifecycle service operations
- existing notification event service
- existing approval notification publication behavior
- existing audit-log foundation
## Implementation Summary
### Canonical Contract
Added `BusinessEvent<TPayload>` in `src/features/foundation/business-events/types.ts`.
The envelope includes:
- globally unique `eventId`
- registered `eventType`
- explicit `schemaVersion`
- organization, branch, entity, primary record, and related records
- actor, `occurredAt`, `correlationId`, and `causationId`
- visibility metadata for product type, pricing sensitivity, and internal-only events
- payload and metadata
### Registry And Naming
Added `src/features/foundation/business-events/registry.ts`.
The registry freezes canonical names and ownership for Activity, Lead, Opportunity, Quotation, Approval, Customer, and PO families. Naming follows lowercase `<entity>.<past-tense-action>` where practical, with compatibility aliases for existing approval notification names such as `approval.step.approved`.
Unknown event types are rejected by publisher validation.
### Publisher And Dispatcher
Added:
- `src/features/foundation/business-events/publisher.ts`
- `src/features/foundation/business-events/dispatcher.ts`
The initial dispatcher is in-process and transport-independent. It supports independent subscriber registration, no-subscriber dispatch, duplicate detection by `consumerName:eventId`, subscriber isolation, unsupported-version reporting, and publish-many ordering.
No Kafka, RabbitMQ, Redis Streams, persistent event store, replay table, or projection table was introduced.
### Initial Activity Event Publishing
Activity lifecycle events now publish from `src/features/crm/activities/server/service.ts`, after successful service-layer mutations:
- `activity.created`
- `activity.assigned`
- `activity.reassigned`
- `activity.started`
- `activity.rescheduled`
- `activity.completed`
- `activity.cancelled`
- `activity.deleted`
Route handlers do not publish events directly.
Activity payloads redact narrative fields when an Activity is pricing-sensitive or internal-only. Visibility metadata remains available so future consumers can enforce CRM authorization before re-querying source details.
Legacy follow-up adapters do not publish events in EP.1.3.
### Event Sequence Matrix
Added `BUSINESS_EVENT_SEQUENCE_MATRIX` in `src/features/foundation/business-events/matrices.ts`.
It freezes expected order for key operations:
- Create Activity
- Assign Existing Activity
- Start Activity
- Reschedule Activity
- Complete Activity
- Cancel Activity
- Convert Lead
- Submit Approval
- Receive PO
### Event Consumer Matrix
Added `BUSINESS_EVENT_CONSUMER_MATRIX` in `src/features/foundation/business-events/matrices.ts`.
Consumers are explicitly non-owning:
- Timeline
- Calendar
- Dashboard
- Notification
- My Day
- Relationship Health
- Forecast
All listed projection consumers are forbidden from mutating source-domain lifecycle state.
### Replay Contracts
Added `src/features/foundation/business-events/replay.ts`.
Replay is contract-only in EP.1.3:
- request must be organization-scoped
- dry-run defaults to true
- ordering is `occurred_at_then_event_id`
- idempotency is required
- no replay route or persistent event store was added
### Existing Event Compatibility
Added `src/features/foundation/business-events/compatibility.ts`.
Existing approval notification event behavior remains untouched. Compatibility aliases map current names to canonical business event names where needed:
- `approval.step.approved` -> `approval.step-approved`
- `approval.step.rejected` -> `approval.step-rejected`
## Versioning Strategy
- Every event includes `schemaVersion`.
- Additive optional payload fields can remain on the same event type and schema version when existing consumers are unaffected.
- Incompatible semantic changes require a new schema version.
- Consumers can declare supported versions per event type.
- Unsupported versions are reported by the dispatcher and do not silently process.
- Deprecated event definitions must specify `replacementEventType`.
## Ordering And Idempotency Rules
- Global ordering across all domains is not guaranteed.
- Related events in one operation share `correlationId`.
- Child events use `causationId` when one event directly triggers another.
- Consumers must not rely on undocumented timing.
- Dispatcher duplicate handling is in-memory for EP.1.3 tests and contracts only.
- Persistent checkpointing remains a future projection-foundation concern.
## Observability Hooks
The dispatch result captures:
- event id and type
- dispatch status
- dispatch duration
- subscriber name
- subscriber status
- subscriber duration
- subscriber error message
- duplicate and unsupported-version outcomes
Structured persistence of these observations is intentionally deferred until persistent event/projection infrastructure is approved.
## Projection Readiness
Ready for EP.1.4 to define projection storage and consumers using:
- `BusinessEvent`
- `BusinessEventConsumer`
- `BusinessEventPublisher`
- `BusinessEventDispatcher`
- event registry definitions
- sequence matrix
- consumer matrix
- replay contract
Not implemented in EP.1.3:
- Timeline projection
- Calendar projection
- Dashboard projection replacement
- Notification expansion
- My Day
- Manager Workspace
- Executive Workspace
- Relationship Health
- Forecast projection
- Automation engine
- external broker
- persistent replay engine
- projection storage tables
## Verification
- `npm run typecheck`
- `node --disable-warning=ExperimentalWarning --disable-warning=MODULE_TYPELESS_PACKAGE_JSON --experimental-strip-types --test src/features/foundation/business-events/*.test.ts src/features/crm/activities/server/business-events.test.ts`
## Residual Risks
- Business events are currently in-process only; no cross-process delivery guarantee exists.
- No persistent event store exists, so replay remains a contract and testing surface only.
- Subscriber failures will fail publisher dispatch; no production subscriber is registered in EP.1.3.
- Existing approval notifications still use the current notification event service and are mapped for compatibility rather than migrated.