task-ep.1.5

This commit is contained in:
phaichayon
2026-07-13 15:03:17 +07:00
parent bba4c8d97d
commit 2bc8dd184c
19 changed files with 9722 additions and 5 deletions

View File

@@ -0,0 +1,155 @@
# Task EP.1.5 Timeline Projection Foundation - 2026-07-13
## Scope
- introduced first production CRM Business Projection: Timeline
- added `crm_timeline_projection` materialized read model schema
- added Timeline event builder and Activity event mapping
- added Timeline projection consumer contract and active CRM registration
- added Timeline list/query storage service
- added Timeline rebuild and legacy adapter contracts
- added reusable Timeline UI components
- added optional Activity detail Timeline integration seam
- preserved Activity, Audit Log, Approval History, follow-up APIs, Dashboard, Reports, Notifications, and current detail-page behavior
## Review Summary
Reviewed before and during implementation:
- `AGENTS.md`
- `plans/task-ep.1.5.md`
- `LAYOUT.md`
- `docs/standards/engineering-constitution.md`
- `docs/standards/project-foundations.md`
- `docs/standards/architecture-rules.md`
- `docs/standards/ui-ux-rules.md`
- `docs/business/relationship-sales-workspace-blueprint-v1.md`
- `docs/security/crm-authorization-boundaries.md`
- `docs/implementation/task-ep1.4-projection-foundation-delivery-reliability-2026-07-13.md`
- `docs/implementation/task-ep1.4.1-transactional-outbox-activation-worker-runtime-2026-07-13.md`
- existing Activity business event adapter
- existing Projection Runtime and Worker
- existing CRM detail/audit UI patterns
## Implementation Summary
### Timeline Schema
Added table:
- `crm_timeline_projection`
Generated migration:
- `drizzle/0005_freezing_wendigo.sql`
The table stores organization-scoped, rebuildable read-model rows with entity references, event provenance, visibility metadata, display fields, and projection version. It has indexes for event id/version idempotency, organization chronology, customer chronology, and activity/event lookup.
### Timeline Builder
Added:
- `src/features/crm/timeline/server/builder.ts`
Builder maps Business Events into business-readable Timeline items. Initial active mappings cover Activity lifecycle events:
- `activity.created`
- `activity.assigned`
- `activity.reassigned`
- `activity.started`
- `activity.rescheduled`
- `activity.completed`
- `activity.cancelled`
- `activity.deleted`
Generic mapping is available for registered future CRM events until their business copy is specialized.
### Timeline Consumer
Added:
- `src/features/crm/timeline/server/consumer.ts`
- `src/features/crm/timeline/server/registration.ts`
The consumer builds a Timeline item and persists it with idempotent `eventId + sourceProjectionVersion` storage. Foundation default consumers remain safe skeletons; CRM worker startup can opt into `CRM_TIMELINE_PROJECTION_CONSUMERS` for the active Timeline projection set.
### Timeline Storage And Query Contract
Added:
- `src/features/crm/timeline/api/types.ts`
- `src/features/crm/timeline/server/service.ts`
Supported filters include organization, customer, lead, opportunity, quotation, activity, event, category, actor, search, date range, and cursor/limit contract. Timeline remains read-only.
### Legacy Adapter And Rebuild Contracts
Added:
- `src/features/crm/timeline/server/legacy-adapters.ts`
- `src/features/crm/timeline/server/rebuild.ts`
Legacy adapters are explicitly read-only rebuild inputs for lead follow-up, opportunity follow-up, quotation follow-up, activity, approval, and audit history. No data migration was introduced.
### Timeline UI
Added:
- `src/features/crm/timeline/components/timeline-list.tsx`
Components:
- `TimelineList`
- `TimelineCard`
- `TimelineEmpty`
- `TimelineSkeleton`
The UI follows the existing dashboard card language, uses deterministic shared date formatting, shadcn primitives, and app icon registry. It preserves a calm enterprise density while adding a clear vertical chronology.
### Workspace Integration
Added an optional `timelineItems` prop to Activity detail. Existing callers are unaffected; when supplied, Activity detail renders an additive Timeline card below the existing Activity detail card.
## Security Notes
- Timeline rows are organization-scoped.
- Timeline visibility stores product type, pricing sensitivity, and internal-only flags.
- Pricing-sensitive/internal-only event payloads continue to rely on source event minimization.
- Timeline query service is storage-ready; route/API exposure must still apply CRM resolved access, branch/product scope, ownership, and pricing visibility before becoming public.
- Timeline never mutates source domains and does not replace Audit Log.
## Delivery Matrix
Initial production path:
| Business Event | Timeline Item | Workspace | Consumer | Projection |
| --- | --- | --- | --- | --- |
| `activity.created` | Activity created | Customer / Lead / Opportunity / Quotation / Activity | `timeline.projection.consumer` | `crm_timeline_projection` |
| `activity.completed` | Activity completed | Customer / Lead / Opportunity / Quotation / Activity | `timeline.projection.consumer` | `crm_timeline_projection` |
| `activity.cancelled` | Activity cancelled | Customer / Lead / Opportunity / Quotation / Activity | `timeline.projection.consumer` | `crm_timeline_projection` |
Additional Activity events are supported in code and documented in the builder mapping.
## UX Review
- Layout: follows `LAYOUT.md` detail-card and timeline entry patterns.
- Density: Timeline cards stay compact, scannable, and fit existing CRM dashboard surfaces.
- Accessibility: items use semantic `article`, `time`, non-color badges, and text labels.
- Loading/empty states: `TimelineSkeleton` and `TimelineEmpty` included.
- Dark mode: tone classes include dark-mode variants.
- Date rendering: uses `src/lib/date-format.ts`.
## 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/foundation/projections/*.test.ts src/features/crm/activities/server/business-events.test.ts src/features/crm/timeline/server/*.test.ts`
- `npx oxlint src/features/crm/timeline src/features/foundation/projections/registry.ts src/features/foundation/projections/consumers.ts src/features/foundation/projections/server/store.ts src/features/crm/activities/components/activity-detail.tsx src/db/schema.ts`
- `npm run db:generate`
## Residual Risks / Follow-up
- Public Timeline route handlers and server-side CRM resolved-access filtering remain future work before exposing Timeline broadly.
- Customer, Lead, Opportunity, and Quotation detail pages are not yet wired to fetch Timeline data; Activity detail has a backward-compatible render seam.
- Approval, quotation, opportunity, customer, and PO event mappings have generic fallback support but need specialized business copy when those domains publish durable events.
- Legacy adapters are contract-only in this slice; source-query rebuild implementation should be expanded as each workspace adopts Timeline.
- EP.1.6 Calendar can reuse the same projection runtime and Activity event delivery path.