Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
295 commits
Select commit Hold shift + click to select a range
2675ac7
Review hardening: fix CA1873 warnings, agent reserve guard, Asterisk …
MikeAlhayek Jul 10, 2026
1a6a0fc
fix call flow
MikeAlhayek Jul 10, 2026
38d5ffb
Harden telephony state synchronization
MikeAlhayek Jul 10, 2026
6290e3c
Fix provider-authoritative soft phone recovery
MikeAlhayek Jul 10, 2026
983f9ea
Harden real-time telephony recovery
MikeAlhayek Jul 10, 2026
22180ad
Fix inbound telephony release synchronization
MikeAlhayek Jul 10, 2026
9b9df60
Fix recurring inbound call synchronization
MikeAlhayek Jul 10, 2026
4014064
Self-heal zombie inbound offers via provider truth
MikeAlhayek Jul 11, 2026
126afd4
Harden Contact Center telephony self-healing and event pipeline
MikeAlhayek Jul 11, 2026
7e5329b
Add omnichannel activity management enhancements
MikeAlhayek Jul 11, 2026
66932aa
Merge branch 'main' into ma/add-contact-center
MikeAlhayek Jul 11, 2026
2862813
Refine omnichannel activity enhancements
MikeAlhayek Jul 11, 2026
c156dcd
Reuse primary contact phone columns
MikeAlhayek Jul 11, 2026
8140691
Improve Contact Center queue operations
MikeAlhayek Jul 11, 2026
e1938d3
Fix Contact Center real-time routing
MikeAlhayek Jul 12, 2026
cb13543
Harden contact center call routing
MikeAlhayek Jul 12, 2026
4c12156
feat: harden contact center agent workflows
MikeAlhayek Jul 12, 2026
cf627af
fix: avoid storing phone numbers in browser storage
MikeAlhayek Jul 12, 2026
ab28d8a
feat: add enterprise contact center reports
MikeAlhayek Jul 13, 2026
9c28d64
Add enterprise contact center report catalog
MikeAlhayek Jul 13, 2026
c0be500
Add Reports chart resource dependency
MikeAlhayek Jul 13, 2026
9bca749
feat: render cached report display names
MikeAlhayek Jul 13, 2026
12cbb5e
fix: render report users through shapes
MikeAlhayek Jul 13, 2026
b27e6a5
improve report export placement
MikeAlhayek Jul 13, 2026
a266afd
fix report display name exports
MikeAlhayek Jul 13, 2026
fc6dbce
fix report user shape layout
MikeAlhayek Jul 13, 2026
5231110
Add AI voice media foundation
MikeAlhayek Jul 13, 2026
13c2d7f
Add multi-call soft phone controls
MikeAlhayek Jul 13, 2026
3173900
Improve multi-call conference and transfer UX
MikeAlhayek Jul 13, 2026
79807e5
Add campaign group reporting and multi-party conferencing
MikeAlhayek Jul 13, 2026
c0ce271
Harden Asterisk development tooling
MikeAlhayek Jul 13, 2026
be5772a
Finalize Contact Center production remediation plan
MikeAlhayek Jul 13, 2026
ba07ffa
Isolate SignalR destinations by tenant
MikeAlhayek Jul 13, 2026
04bd5e2
Prevent workflow preview stored XSS
MikeAlhayek Jul 13, 2026
cbfb5ef
Harden voice webhook request handling
MikeAlhayek Jul 13, 2026
ccb1076
Enforce agent queue entitlements
MikeAlhayek Jul 14, 2026
d2570c3
Pin Contact Center R0 baseline
MikeAlhayek Jul 14, 2026
99f088f
Define Contact Center GA support matrix
MikeAlhayek Jul 14, 2026
df1a152
Define Contact Center service objectives
MikeAlhayek Jul 14, 2026
ee96dba
Define Contact Center PR test controls
MikeAlhayek Jul 14, 2026
430086d
Add two-shell isolation reproductions
MikeAlhayek Jul 14, 2026
8a4570c
Characterize feature dependency violations
MikeAlhayek Jul 14, 2026
d54b14f
Characterize fake media success
MikeAlhayek Jul 14, 2026
b45a239
Modernize contact center reporting and phone UX
MikeAlhayek Jul 14, 2026
7f5c432
Fix Contact Center picker resource conflict
MikeAlhayek Jul 14, 2026
9cd36ed
Document Omnichannel ACS upgrade dependencies
MikeAlhayek Jul 14, 2026
8513602
Characterize agent capacity recovery gaps
MikeAlhayek Jul 14, 2026
120f47a
Characterize shared database reservation race
MikeAlhayek Jul 14, 2026
2f4bfa1
Characterize provider command outcome gaps
MikeAlhayek Jul 14, 2026
1388c0d
Characterize provider event ordering gaps
MikeAlhayek Jul 14, 2026
ac56c6e
Characterize outbox deployment replay gaps
MikeAlhayek Jul 14, 2026
3899bcf
Characterize ambiguous inbound attribution
MikeAlhayek Jul 14, 2026
162fe72
Characterize operational log privacy gaps
MikeAlhayek Jul 14, 2026
54cf246
Complete Contact Center R0 evidence ledger
MikeAlhayek Jul 14, 2026
f3e99a1
Centralize operational log redaction
MikeAlhayek Jul 14, 2026
8f77230
Limit provider webhook ingress
MikeAlhayek Jul 14, 2026
e644abc
Enforce provider webhook freshness
MikeAlhayek Jul 14, 2026
f0152ab
Persist provider webhook deliveries
MikeAlhayek Jul 14, 2026
d111b38
Split headless Contact Center feature
MikeAlhayek Jul 14, 2026
f28734f
Separate server voice from soft phone
MikeAlhayek Jul 14, 2026
6320a14
Move soft phone integration out of queues
MikeAlhayek Jul 14, 2026
05df77e
Add explicit Contact Center workflows feature
MikeAlhayek Jul 14, 2026
2ef0e89
Separate agent availability from real time
MikeAlhayek Jul 14, 2026
70b8cae
Separate routing from queue management
MikeAlhayek Jul 14, 2026
644d896
Add independent Contact Center agent desktop
MikeAlhayek Jul 14, 2026
ae88d6b
Add independent Contact Center supervision
MikeAlhayek Jul 14, 2026
0ec6c5c
Split compliance and automated dialing features
MikeAlhayek Jul 14, 2026
ea57bc1
Add independent Contact Center entry points
MikeAlhayek Jul 14, 2026
82604e4
Split contact center recording feature
MikeAlhayek Jul 14, 2026
7a0f7c8
Split contact center provider features
MikeAlhayek Jul 14, 2026
c58f443
Move provider contracts to abstractions
MikeAlhayek Jul 14, 2026
a9f2043
Remove reverse dialer dependencies
MikeAlhayek Jul 14, 2026
fe9cee1
Add browser audio provider foundation
MikeAlhayek Jul 14, 2026
ad42646
Track browser audio provider certification
MikeAlhayek Jul 14, 2026
8120b35
Harden contact center administration UX
MikeAlhayek Jul 14, 2026
2e2d0fb
Centralize Contact Center scope execution
MikeAlhayek Jul 14, 2026
aa75546
Add Contact Center Redis backplane harness
MikeAlhayek Jul 15, 2026
bdcf84a
Add Contact Center feature lifecycle contracts
MikeAlhayek Jul 15, 2026
89cff40
Add Contact Center feature activation matrix
MikeAlhayek Jul 15, 2026
1853167
Make Contact Center reservations atomic
MikeAlhayek Jul 15, 2026
0c1faa5
Add canonical agent availability recovery
MikeAlhayek Jul 15, 2026
e64f58a
Persist outbound provider command intent
MikeAlhayek Jul 15, 2026
6df58b1
Implement durable provider command state machine
MikeAlhayek Jul 15, 2026
2c0783e
Harden provider event ingestion identity
MikeAlhayek Jul 15, 2026
1f5df0f
Isolate poison message dispatch
MikeAlhayek Jul 15, 2026
a328017
Harden atomic Contact Center side effects
MikeAlhayek Jul 15, 2026
6a1dd9e
Drain active Contact Center feature work
MikeAlhayek Jul 15, 2026
c6d0abd
Split executable voice provider contracts
MikeAlhayek Jul 16, 2026
df2d629
Require provider-confirmed voice controls
MikeAlhayek Jul 16, 2026
b851f93
Harden duplicate provider stream ingestion
MikeAlhayek Jul 16, 2026
8465192
Bound PBX command execution
MikeAlhayek Jul 16, 2026
9dd4cb3
Fail GA media closed
MikeAlhayek Jul 16, 2026
2903456
Add explicit contact attribution
MikeAlhayek Jul 16, 2026
81bc74a
Harden unroutable inbound calls
MikeAlhayek Jul 16, 2026
3ea0c75
Add calendar-based outbound windows and regulated abandonment/AMD com…
MikeAlhayek Jul 16, 2026
bf2bd7f
Gate Power and Progressive modes on the Automated Dialer feature
MikeAlhayek Jul 16, 2026
778b885
Guard GA-Core profiles against enabling automated dialing
MikeAlhayek Jul 16, 2026
d778499
Normalize agent queue membership into a query-aligned index
MikeAlhayek Jul 16, 2026
846a774
Replace queue count broad loads with aggregate SQL
MikeAlhayek Jul 16, 2026
f819d65
Bound and lease callback and reconciliation background sweeps
MikeAlhayek Jul 16, 2026
d0e58e6
Add projection rebuild, drift detection, and replay checkpoint
MikeAlhayek Jul 16, 2026
2355df4
Resolve raw-SQL/enum portability and document the database matrix
MikeAlhayek Jul 16, 2026
42dce71
Add Contact Center telemetry and operational health checks
MikeAlhayek Jul 16, 2026
1afc6be
Document the supported multi-node Contact Center backplane
MikeAlhayek Jul 16, 2026
36c316e
Align event retention with replay horizon and legal holds
MikeAlhayek Jul 16, 2026
3521202
Document expand-migrate-contract upgrade safety for Contact Center
MikeAlhayek Jul 16, 2026
bb84ffa
Add Contact Center failure and deployment runbooks
MikeAlhayek Jul 16, 2026
8f81587
Define per-entity Contact Center data governance and complete R7
MikeAlhayek Jul 16, 2026
4229e1a
Remove unused Managements.Models using from Contact Center Startup
MikeAlhayek Jul 16, 2026
7d9cd40
Document R1 audit result and pin non-voice webhook ingress forward de…
MikeAlhayek Jul 16, 2026
7ab102b
Merge main into add-contact-center
Copilot Jul 16, 2026
1d8719c
Add Contact Center Plan 2 (single-node completion & credibility)
MikeAlhayek Jul 16, 2026
ddfff98
Refine Contact Center Plan 2: Aspire single-node harness + re-ratifie…
MikeAlhayek Jul 16, 2026
02c4140
Part 0: pin Asterisk/coturn media runner and wire Aspire Redis for si…
MikeAlhayek Jul 16, 2026
aae3fc9
Part A: typed CAS call-state authority, atomic queue, and webhook tom…
MikeAlhayek Jul 16, 2026
8023f64
Part 1a: fail-closed soft-phone call-ownership authorization (SEC-1/B…
MikeAlhayek Jul 16, 2026
9798444
DB-1: add YesSql integer-enum persistence regression guard for Activi…
MikeAlhayek Jul 16, 2026
9edc4ef
Part 0: two-tenant adversarial isolation harness + WebRTC audio-proof…
MikeAlhayek Jul 16, 2026
3d34902
Contact Center Plan 2: record Wave 1 complete and re-scope DB-1 after…
MikeAlhayek Jul 16, 2026
179a16c
Fix DB-1 at root cause: declare enum index columns with their enum type
MikeAlhayek Jul 16, 2026
d0b8b44
Fix DB-1 reservation/queue-item UpdateFrom1 to match YesSql integer s…
MikeAlhayek Jul 16, 2026
97f6fe3
Complete Contact Center Wave 2: call-control authz boundary + browser…
MikeAlhayek Jul 17, 2026
438e537
Complete Contact Center Wave 3: executable ACD connect + idempotent i…
MikeAlhayek Jul 18, 2026
ecac7a3
Add Asterisk ARI bridge recording and close DIST-8 metadata persistence
MikeAlhayek Jul 19, 2026
afad1ba
Add Asterisk supervisor monitoring (snoop-based Monitor/Whisper/Barge…
MikeAlhayek Jul 19, 2026
a92900a
Add Asterisk blind call-transfer-to-agent primitive (Contact Center P…
MikeAlhayek Jul 25, 2026
267f7ac
Restore lost bullet prefix on PLAN-2 monitoring progress entry
MikeAlhayek Jul 25, 2026
b59f892
Harden Asterisk durable transfer-claim with a version-checked owner swap
MikeAlhayek Jul 25, 2026
462484e
Add recording governance policy primitive (consent + retention + lega…
MikeAlhayek Jul 25, 2026
86519e4
Add recording access audit and right-to-erasure governance
MikeAlhayek Jul 25, 2026
1345f98
Add secure ARI recording ingest with encryption-at-rest and durable r…
MikeAlhayek Jul 26, 2026
a6e96cf
Record A-3 review APPROVE and workstream B design handoff in Contact …
MikeAlhayek Jul 26, 2026
51ec88f
Add Asterisk multi-party conference with race-safe bridge-ownership m…
MikeAlhayek Jul 26, 2026
40dde59
Add Asterisk attended (consultative) transfer over ARI
MikeAlhayek Jul 26, 2026
51b4d9c
Unblock hermetic builds and land W0.7 containment fixes
MikeAlhayek Jul 26, 2026
7ee4505
Add production health probes to Contact Center (W0.8)
MikeAlhayek Jul 26, 2026
6988496
Audit Contact Center feature dependencies and close a fail-open bound…
MikeAlhayek Jul 26, 2026
42d470d
Enforce Contact Center search independence and fix outbox completion
MikeAlhayek Jul 26, 2026
8b650f4
Enforce additive-only data migrations as a build gate (W15.2)
MikeAlhayek Jul 27, 2026
4052a52
Earn a production topology and enforce it at startup (W0.1, W0.2)
MikeAlhayek Jul 27, 2026
21f0cc1
Bind the Contact Center release ledger to real CI (W0.3)
MikeAlhayek Jul 27, 2026
4051feb
Repair the Contact Center CI gates and enforce the repairs (W0.4)
MikeAlhayek Jul 27, 2026
31049e0
Close the supply chain gaps (W0.5)
MikeAlhayek Jul 27, 2026
ae87f58
Replace Contact Center tests that never executed the code they guarded
MikeAlhayek Jul 27, 2026
c7f9cf2
Contact Center W18: fail-closed configuration validation
MikeAlhayek Jul 27, 2026
b18942b
Add preview export, quiesce, reset and verify tooling (W8.5)
MikeAlhayek Jul 27, 2026
9cb1783
Add N-1 rolling upgrade harness and fix install-path schema divergenc…
MikeAlhayek Jul 27, 2026
e6ea702
Bind Asterisk and DialPad to real provider contracts (W5.4)
MikeAlhayek Jul 27, 2026
a9fab3a
Prove the call state machine under adversarial delivery (W5.6)
MikeAlhayek Jul 27, 2026
510c968
One call-state vocabulary with real hangup causes (W1.3)
MikeAlhayek Jul 27, 2026
908350e
Close the lost-update class in the telephony interaction store (W1.5)
MikeAlhayek Jul 27, 2026
0bd4dc8
Split the fat telephony provider interface into capability contracts …
MikeAlhayek Jul 27, 2026
e454592
Remove Asterisk-specific vocabulary from provider-neutral contracts (…
MikeAlhayek Jul 27, 2026
2f9e528
Move the provider-neutral voice ingress mechanics into Telephony.Core…
MikeAlhayek Jul 27, 2026
ec11fa3
Register Telephony.Core in the shipped-assembly scan pin
MikeAlhayek Jul 27, 2026
bb159a0
Make one provider call stream feed every projection
MikeAlhayek Jul 27, 2026
de3ee88
Extract ContactCenterWorkState so routing no longer contends with the…
MikeAlhayek Jul 27, 2026
c33127a
Model a live call as a topology instead of scalars (W2.2)
MikeAlhayek Jul 27, 2026
c77fcb2
Give every high-volume Contact Center table a retention policy (W2.3)
MikeAlhayek Jul 28, 2026
45900c8
Put the Contact Center reservation path under a query-plan budget (W2.4)
MikeAlhayek Jul 28, 2026
9444ff4
Converge upgraded and fresh tenant schemas and gate migration safety
MikeAlhayek Jul 28, 2026
859108b
Classify the work-state authority scan's receivers by resolved type
MikeAlhayek Jul 28, 2026
02d15ea
Make provider voice events immutable
MikeAlhayek Jul 28, 2026
2762447
Close the do-not-call bypass with a canonical phone number value obje…
MikeAlhayek Jul 28, 2026
f4ef246
Let Contact Center records decide their own state changes (W10.1)
MikeAlhayek Jul 28, 2026
bfcaf42
Split Contact Center capabilities from their administration screens (…
MikeAlhayek Jul 28, 2026
e013ee3
Degrade reports when the capability that produces their data is absen…
MikeAlhayek Jul 28, 2026
fa6cd51
Make Contact Center and CRM configuration portable between tenants (W…
MikeAlhayek Jul 28, 2026
f97c94f
Bound untrusted webhook request bodies by what actually arrives (W11.6)
MikeAlhayek Jul 28, 2026
510fab9
W11.7: enforce configuration rules on every write path
MikeAlhayek Jul 28, 2026
6c9fb88
Merge branch 'main' into ma/add-contact-center
MikeAlhayek Jul 28, 2026
15bbbe6
regenerate package-lock.json
MikeAlhayek Jul 28, 2026
da3abb0
Record and lock the public surface of every assembly other modules co…
MikeAlhayek Jul 29, 2026
7709b47
Remove the agent-workspace N+1 reads (W11.9)
MikeAlhayek Jul 29, 2026
1917bf6
W15.1: convert stored contact center events to the current schema on …
MikeAlhayek Jul 29, 2026
6c39b08
Merge branch 'main' into ma/add-contact-center
MikeAlhayek Jul 29, 2026
26a9735
W16.4: replace the metric hot row with append-and-rollup
MikeAlhayek Jul 29, 2026
302ca11
Merge remote-tracking branch 'origin/ma/add-contact-center' into ma/a…
MikeAlhayek Jul 29, 2026
6940f3a
Contact Center W16.5: stamp the agent heartbeat in its own unit of wo…
MikeAlhayek Jul 29, 2026
7e891eb
Contact Center W16.6: shorten the reservation critical section and pr…
MikeAlhayek Jul 29, 2026
ff6daf6
W16.1: scope Asterisk call teardown to terminal events and gate it fo…
MikeAlhayek Jul 29, 2026
d7ff3e1
Establish one hub cancellation convention and stop silently deaf agents
MikeAlhayek Jul 29, 2026
655a2d6
Fix the failing CI checks and the Aspire app host startup crash
MikeAlhayek Jul 29, 2026
1d0c205
Rebuild the vendored DOMPurify assets against the pinned version
MikeAlhayek Jul 29, 2026
c7d9863
Fix migration
MikeAlhayek Jul 29, 2026
bbe7a3a
Fix the Windows-only test failures in CI
MikeAlhayek Jul 29, 2026
5e21749
Label every Manage Activities filter and make the filter card collaps…
MikeAlhayek Jul 29, 2026
8d0c01f
Approve the OmnichannelContactsMigrations public surface change
MikeAlhayek Jul 29, 2026
841841f
Hide subject editor buttons and cache omnichannel content types
MikeAlhayek Jul 29, 2026
d13c30b
Split v2 platform improvements into ma/upgrade-omnichannel
MikeAlhayek Jul 29, 2026
aca1121
general cleanup
MikeAlhayek Jul 30, 2026
0b0f606
Apply v2 post-review repairs to ma/upgrade-omnichannel
MikeAlhayek Jul 30, 2026
ea7ff64
Replace ConfigurationCatalog framework with Orchard deployment and re…
MikeAlhayek Jul 30, 2026
e8bba03
Remove per-project README from Reports.OpenXml
MikeAlhayek Jul 30, 2026
d7322d6
Replace bespoke log redactor with Microsoft.Extensions.Compliance.Red…
MikeAlhayek Jul 30, 2026
3d46505
Remove per-project README from Reports.OpenXml
MikeAlhayek Jul 30, 2026
3472210
Merge ma/upgrade-omnichannel into ma/add-contact-center
MikeAlhayek Jul 30, 2026
e72782e
Port ma/upgrade-omnichannel cleanups into Contact Center
MikeAlhayek Jul 30, 2026
700abd1
Make configuration import carry every member, and fix a feature-scope…
MikeAlhayek Jul 30, 2026
70745ba
Patch OS packages in the Asterisk image so the container scan passes
MikeAlhayek Jul 30, 2026
68f3e0e
Show the Automatic inventory-load source in the picker
MikeAlhayek Jul 30, 2026
56ed65d
Add direction (Outbound/Inbound) to omnichannel subject flows
MikeAlhayek Jul 30, 2026
d5bc24c
Honor required-disposition policy in automated SMS conclusions
MikeAlhayek Jul 30, 2026
543a9a9
Move subject flow configuration to OmnichannelSubjectPart content-par…
MikeAlhayek Jul 31, 2026
89abdc1
Improve subject part settings UX with progressive disclosure
MikeAlhayek Jul 31, 2026
a7924aa
Refine subject flow badges and restrict AI config to inbound automated
MikeAlhayek Jul 31, 2026
c756b01
Move Default campaign field above Direction in subject part settings
MikeAlhayek Jul 31, 2026
ed873f6
Fold Automatic batch AI profile into inventory load card; scope chann…
MikeAlhayek Jul 31, 2026
61cefeb
Use empty placeholder for batch AI profile selector without preselect…
MikeAlhayek Jul 31, 2026
1c68647
Order Load Inventory list newest first with pager and bulk selection
MikeAlhayek Jul 31, 2026
dd8f4ca
Show true total item count in admin list headers
MikeAlhayek Jul 31, 2026
23b583f
Fix Load Inventory list newest-first sort via direct ISession query
MikeAlhayek Jul 31, 2026
f95c871
Merge remote-tracking branch 'origin/main' into ma/add-contact-center
MikeAlhayek Jul 31, 2026
919e305
Add consolidated Contact Center production-readiness plan
MikeAlhayek Jul 31, 2026
0e79b59
A1: Remove KnownDevelopmentValues; inline dev-credential rejection
MikeAlhayek Jul 31, 2026
c3f0f99
A2: add functional Contact Center health-check dependency probes
MikeAlhayek Aug 1, 2026
58a848e
A3/A4/A5: remove dead ingress, take-over, and bespoke maintenance; fi…
MikeAlhayek Aug 1, 2026
f1e02f4
B1: prove ARI listener starts only after validation + ownership
MikeAlhayek Aug 1, 2026
8dd522c
Mark B1 complete in production-readiness tracker
MikeAlhayek Aug 1, 2026
5dcb408
Settle telephony recording commands honestly on shutdown (B2)
MikeAlhayek Aug 1, 2026
bc49263
Mark B2 done in production-readiness tracker
MikeAlhayek Aug 1, 2026
3e642ec
B3: prove report-provider state does not leak across requests (no ref…
MikeAlhayek Aug 1, 2026
71746ab
B4: canonical-payload idempotency key for Asterisk ARI events
MikeAlhayek Aug 1, 2026
677e8d6
Mark B4 complete in production-readiness tracker
MikeAlhayek Aug 1, 2026
903611e
B5: close historical transfer-string cleanup as already-correct with …
MikeAlhayek Aug 1, 2026
17cadcf
Mark B5 complete in production-readiness tracker
MikeAlhayek Aug 1, 2026
b4dc0ad
Harden Asterisk ARI ownership: deny blank claims and document single-…
MikeAlhayek Aug 1, 2026
91e3aa9
Mark B6 complete in Contact Center production-readiness tracker
MikeAlhayek Aug 1, 2026
c94ec20
Harden ReservationExpiryBackgroundTask drain and lock-margin safety (B7)
MikeAlhayek Aug 1, 2026
812dc09
Mark B7 complete in production-readiness tracker
MikeAlhayek Aug 1, 2026
6c4aa4d
Parse DialPad provider timestamps as invariant UTC (B8)
MikeAlhayek Aug 1, 2026
ee35788
Mark B8 complete in production-readiness tracker
MikeAlhayek Aug 1, 2026
f3f466f
Add recording/media erasure & lifecycle governance (C1)
MikeAlhayek Aug 1, 2026
711723d
Mark C1 recording erasure complete in release ledger + tracker
MikeAlhayek Aug 1, 2026
3d5865e
Widen CallSession provider-call columns as an N-1-safe rebuild (C2)
MikeAlhayek Aug 1, 2026
44eb262
Record C2 completion in the readiness ledgers
MikeAlhayek Aug 1, 2026
3886f5a
Contact Center D1: bounded real-time event channel with real backpres…
MikeAlhayek Aug 1, 2026
8e28e05
Contact Center D2: prove Asterisk reconciliation reads live ARI
MikeAlhayek Aug 1, 2026
ba8aada
Add Contact Center operational signals and voice handover runbook (D3)
MikeAlhayek Aug 2, 2026
00f7c51
Harden automated omnichannel activities processor (E1 / W13)
MikeAlhayek Aug 2, 2026
b2942ec
Make Contact Center operator docs truthful against shipped code (E2)
MikeAlhayek Aug 2, 2026
2991844
Contact Center G1: prove-or-disable base voice path; ship recording o…
MikeAlhayek Aug 2, 2026
f0573c0
T1: remove Contact Center planning scaffolding for merge-readiness
MikeAlhayek Aug 2, 2026
fe1a788
Decompose VoiceContactCenterCallRouter into focused services (F1)
MikeAlhayek Aug 2, 2026
78afedb
Collapse Contact Center catalog-CRUD controllers onto a generic base …
MikeAlhayek Aug 2, 2026
c5d148c
Refactor(contact-center): F3 decompose two mega-files (report calcula…
MikeAlhayek Aug 2, 2026
5fe05ac
Docs(contact-center): mark G1 complete in the readiness ledger
MikeAlhayek Aug 2, 2026
387471d
Docs(contact-center): mark T3 (docs review) and T4 (Aspire smoke test…
MikeAlhayek Aug 2, 2026
68b9c0d
Refactor(contact-center): T2 deep-dive nit fixes (provider-name width…
MikeAlhayek Aug 2, 2026
0008724
Chore: remove stray .review_files.txt artifact
MikeAlhayek Aug 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
**/wwwroot/**/*.js text eol=lf
**/wwwroot/**/*.css text eol=lf

# Shell scripts must keep LF endings. A CRLF checkout turns a script's shebang into `#!/bin/sh\r`, and a
# container that copies the script then fails to start because no interpreter by that name exists.
*.sh text eol=lf

# Vendored specification cassettes are verified against the SHA-256 of the upstream file recorded in their
# manifest. Line ending normalization would rewrite the bytes and break that check on Windows checkouts.
tests/CrestApps.OrchardCore.Tests/Telephony/Cassettes/** -text

# Ensure binary files are never treated as text.
*.webp binary
*.png binary
Expand Down
207 changes: 207 additions & 0 deletions .github/contact-center/PRODUCTION-READINESS.md

Large diffs are not rendered by default.

498 changes: 498 additions & 0 deletions .github/contact-center/feature-dependency-violations.v1.json

Large diffs are not rendered by default.

207 changes: 207 additions & 0 deletions .github/contact-center/feature-lifecycle-contracts.v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
{
"version": "1.0",
"scope": "inactive-idle-and-r3-active-work",
"activeWorkMilestone": "implemented",
"entries": [
{
"featureId": "CrestApps.OrchardCore.ContactCenter",
"component": "OutboxDispatchBackgroundTask",
"kind": "background-task",
"quiesce": "The pre-disable participant closes base Contact Center admission before Orchard mutates the descriptor; new dispatch passes return without claiming work.",
"drain": "Disable waits up to the configured tenant drain timeout for every admitted dispatch pass to release its lease.",
"reEnable": "The fresh shell reopens admission; durable messages retain their expected handler ids and resume without silent completion.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter",
"component": "ContactCenterRetentionBackgroundTask",
"kind": "background-task",
"quiesce": "Orchard stops scheduling the feature-owned task after the tenant shell reloads.",
"drain": "Idle contract requires no retention pass to be running.",
"reEnable": "The fresh shell resolves exactly one new task registration.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter",
"component": "ContactCenterMetricRollupBackgroundTask",
"kind": "background-task",
"quiesce": "Orchard stops scheduling the feature-owned task after the tenant shell reloads.",
"drain": "Idle contract requires no fold to be running. Contributions left unfolded are not lost: the next fold reads whatever is waiting, and a reader adds unfolded contributions to the stored totals in the meantime.",
"reEnable": "The fresh shell resolves exactly one new task registration.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Availability",
"component": "AgentSessionCleanupBackgroundTask",
"kind": "background-task",
"quiesce": "Orchard stops scheduling the feature-owned task after the tenant shell reloads.",
"drain": "Idle contract requires no cleanup pass to be running.",
"reEnable": "The fresh shell resolves exactly one new task registration.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Availability",
"component": "AgentAvailabilityRecoveryBackgroundTask",
"kind": "background-task",
"quiesce": "Orchard stops scheduling the feature-owned task after the tenant shell reloads.",
"drain": "Idle contract requires no availability-recovery pass to be running.",
"reEnable": "The fresh shell resolves exactly one new task registration.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Routing",
"component": "ReservationExpiryBackgroundTask",
"kind": "background-task",
"quiesce": "The Routing lifecycle participant closes admission before descriptor mutation; new reservation-and-assignment passes return without claiming work.",
"drain": "Disable waits up to the configured tenant drain timeout for the admitted reservation-and-assignment pass.",
"reEnable": "The fresh shell reopens Routing admission and the scheduled pass resumes.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Dialer",
"component": "CallbackDispatchBackgroundTask",
"kind": "background-task",
"quiesce": "The Dialer lifecycle participant closes admission before descriptor mutation; new callback passes return without claiming work.",
"drain": "Disable waits up to the configured tenant drain timeout for admitted callback work.",
"reEnable": "The fresh shell reopens Dialer admission and durable callbacks resume.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Dialer.Automated",
"component": "DialerPacingBackgroundTask",
"kind": "background-task",
"quiesce": "The Automated Dialer lifecycle participant closes admission before descriptor mutation; new pacing cycles return without starting attempts.",
"drain": "Disable waits up to the configured tenant drain timeout for admitted pacing cycles.",
"reEnable": "The fresh shell reopens admission and durable campaign work resumes.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Voice",
"component": "ProviderWebhookInboxBackgroundTask",
"kind": "background-task",
"quiesce": "The Voice lifecycle participant closes admission before descriptor mutation; new inbox passes return without claiming durable deliveries.",
"drain": "Disable waits for admitted inbox work to settle through its existing owner and fence.",
"reEnable": "Admission reopens and the next fresh-scope pass re-evaluates retained durable deliveries without blocking activation.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Voice",
"component": "ProviderCallStateReconciliationBackgroundTask",
"kind": "background-task",
"quiesce": "The Voice lifecycle participant closes admission; new scheduled reconciliation passes return without provider or database work.",
"drain": "Disable waits for an admitted reconciliation pass to finish within the configured timeout.",
"reEnable": "Admission reopens and a normal fresh scope performs provider-truth reconciliation within the next minute.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Voice",
"component": "ProviderCommandRecoveryBackgroundTask",
"kind": "background-task",
"quiesce": "The Voice lifecycle participant closes admission; new recovery and direct dispatch passes leave commands durable without a provider call.",
"drain": "Disable waits for admitted command work to settle; sent or outcome-unknown commands remain fenced for later reconciliation.",
"reEnable": "Admission reopens and the next fresh-scope recovery pass re-evaluates retained commands exactly once through durable ownership.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.Voice",
"component": "ContactCenterVoiceTenantEvents",
"kind": "lifecycle-participant",
"quiesce": "The pre-disable coordinator invokes the Voice participant and atomically rejects new tenant-shell Voice work before the feature descriptor changes.",
"drain": "The participant waits for admitted Voice work up to the validated tenant timeout and fails feature disable closed on timeout.",
"reEnable": "A fresh shell reopens admission and schedules provider-truth reconciliation in a normal scope.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.ContactCenter.RealTime",
"component": "ContactCenterHub",
"kind": "signalr-hub",
"quiesce": "Real-Time admission closes and the tenant-local registry aborts every active Contact Center hub connection before descriptor mutation.",
"drain": "Each connection holds a lease until disconnect cleanup unregisters it; disable waits up to the configured timeout.",
"reEnable": "The fresh shell reopens registration and admission before new hub connections are accepted.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.Telephony",
"component": "TelephonyInteractionReconciliationBackgroundTask",
"kind": "background-task",
"quiesce": "Orchard stops scheduling the feature-owned task after the tenant shell reloads.",
"drain": "Idle contract requires no reconciliation pass to be running.",
"reEnable": "The fresh shell resolves one task and runs tenant activation reconciliation.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.Telephony",
"component": "TelephonyHub",
"kind": "signalr-hub",
"quiesce": "The feature-owned hub route is absent after the tenant pipeline reloads.",
"drain": "Idle contract requires zero connected soft-phone clients.",
"reEnable": "The fresh shell maps one hub route and creates new connection state.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.Omnichannel.Activities",
"component": "AutomatedActivitiesProcessorBackgroundTask",
"kind": "background-task",
"quiesce": "Orchard stops scheduling the feature-owned task after the tenant shell reloads.",
"drain": "Idle contract requires no automated-activity batch to be running.",
"reEnable": "The fresh shell resolves exactly one new task registration.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.Asterisk",
"component": "AsteriskRealtimeVoiceListener",
"kind": "provider-listener",
"quiesce": "Tenant termination cancels the listener and awaits its run task.",
"drain": "Idle listener shutdown completes after cancellation with no provider event in flight.",
"reEnable": "Tenant activation starts one fresh listener guarded against duplicate starts.",
"idleStatus": "verified-idle",
"activeWorkStatus": "deferred-follow-up"
},
{
"featureId": "CrestApps.OrchardCore.Asterisk.ContactCenterVoice",
"component": "AsteriskContactCenterVoiceProvider",
"kind": "provider-adapter",
"quiesce": "The provider feature closes admission before descriptor mutation; every adapter operation rejects new execution after quiesce.",
"drain": "Disable waits for admitted adapter calls to release their provider-feature leases.",
"reEnable": "The fresh shell reopens admission and the resolver creates scoped adapters normally.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.Asterisk.ContactCenterMedia",
"component": "AsteriskContactCenterVoiceMediaProvider",
"kind": "provider-media",
"quiesce": "The media feature closes admission before descriptor mutation; new media-session creation is rejected.",
"drain": "Each open media session retains a media-feature lease through StopAsync or disposal, and disable waits for cleanup.",
"reEnable": "The fresh shell reopens admission and new scoped media providers can create sessions.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
},
{
"featureId": "CrestApps.OrchardCore.DialPad.ContactCenterVoice",
"component": "DialPadContactCenterVoiceProvider",
"kind": "provider-adapter",
"quiesce": "The provider feature closes admission before descriptor mutation; every adapter operation rejects new execution after quiesce.",
"drain": "Disable waits for admitted adapter calls to release their provider-feature leases.",
"reEnable": "The fresh shell reopens admission and the resolver creates scoped adapters normally.",
"idleStatus": "verified-idle",
"activeWorkStatus": "implemented-r3"
}
]
}
150 changes: 150 additions & 0 deletions .github/contact-center/support-matrix.v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"version": "1.0",
"releaseStatus": "blocked-until-r0-r8-pass",
"capacityTier": {
"id": "tier-1",
"maxTenantsPerDeployment": 5,
"maxConcurrentSignedInAgentsPerTenant": 100,
"maxConcurrentVoiceInteractionsPerTenant": 50,
"maxNewInteractionsPerSecondPerTenant": 10,
"maxConcurrentSignedInAgentsPerDeployment": 250,
"maxConcurrentVoiceInteractionsPerDeployment": 100
},
"databases": [
{
"id": "postgresql-16",
"versions": [
"16.x"
],
"production": true
},
{
"id": "sqlite",
"versions": [
"3.x"
],
"production": false
}
],
"topologies": [
{
"id": "single-node-distributed",
"production": true,
"minimumApplicationNodes": 1,
"maximumApplicationNodes": 1,
"redisBackplaneRequired": true,
"redisDistributedLockRequired": true,
"sharedRelationalDatabaseRequired": true
},
{
"id": "single-region-multi-node",
"production": false,
"minimumApplicationNodes": 2,
"maximumApplicationNodes": 4,
"redisBackplaneRequired": true,
"redisDistributedLockRequired": true,
"sharedRelationalDatabaseRequired": true
},
{
"id": "single-node-development",
"production": false,
"minimumApplicationNodes": 1,
"maximumApplicationNodes": 1,
"redisBackplaneRequired": false,
"redisDistributedLockRequired": false,
"sharedRelationalDatabaseRequired": false
}
],
"providerProfiles": [
{
"id": "asterisk-ga-core",
"provider": "asterisk",
"allowedCapabilities": [
"inbound-voice",
"manual-dial",
"preview-dial"
],
"prohibitedCapabilities": [
"automated-dial",
"predictive-dial",
"recording",
"monitor",
"whisper",
"barge",
"bidirectional-media"
]
},
{
"id": "dialpad-ga-core",
"provider": "dialpad",
"allowedCapabilities": [
"inbound-voice",
"manual-dial",
"preview-dial",
"call-transfer"
],
"prohibitedCapabilities": [
"automated-dial",
"predictive-dial",
"recording",
"monitor",
"whisper",
"barge",
"bidirectional-media"
]
}
],
"tenantProfiles": [
{
"id": "ga-core-asterisk",
"providerProfile": "asterisk-ga-core",
"database": "postgresql-16",
"topology": "single-node-distributed",
"features": [
"CrestApps.OrchardCore.ContactCenter",
"CrestApps.OrchardCore.ContactCenter.Availability",
"CrestApps.OrchardCore.ContactCenter.Queues",
"CrestApps.OrchardCore.ContactCenter.Routing",
"CrestApps.OrchardCore.ContactCenter.Voice",
"CrestApps.OrchardCore.ContactCenter.Voice.SoftPhone",
"CrestApps.OrchardCore.ContactCenter.AgentDesktop",
"CrestApps.OrchardCore.ContactCenter.RealTime",
"CrestApps.OrchardCore.ContactCenter.Dialer",
"CrestApps.OrchardCore.Asterisk",
"CrestApps.OrchardCore.Asterisk.ContactCenterVoice"
]
},
{
"id": "ga-core-dialpad",
"providerProfile": "dialpad-ga-core",
"database": "postgresql-16",
"topology": "single-node-distributed",
"features": [
"CrestApps.OrchardCore.ContactCenter",
"CrestApps.OrchardCore.ContactCenter.Availability",
"CrestApps.OrchardCore.ContactCenter.Queues",
"CrestApps.OrchardCore.ContactCenter.Routing",
"CrestApps.OrchardCore.ContactCenter.Voice",
"CrestApps.OrchardCore.ContactCenter.Voice.SoftPhone",
"CrestApps.OrchardCore.ContactCenter.AgentDesktop",
"CrestApps.OrchardCore.ContactCenter.RealTime",
"CrestApps.OrchardCore.ContactCenter.Dialer",
"CrestApps.OrchardCore.DialPad",
"CrestApps.OrchardCore.DialPad.ContactCenterVoice"
]
}
],
"prohibitedCombinations": [
"production with SQLite",
"production with a single application node without Redis distributed locking and a Redis SignalR backplane",
"production with more than one application node",
"multi-node without a Redis SignalR backplane",
"multi-node without OrchardCore.Redis.Lock distributed locking",
"multi-region active-active",
"more than one voice provider profile in one tenant",
"Power, Progressive, or Predictive dialing",
"recording, monitor, whisper, barge, or bidirectional media",
"Elasticsearch in routing, assignment, provider ingest, or another correctness path",
"unlisted feature, provider, database, or topology combinations"
]
}
12 changes: 12 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ CrestApps.OrchardCore is a collection of open-source modules for **Orchard Core
**Target Framework**: .NET 10.0 (net10.0)
**Architecture**: Modular, multi-tenant application framework

## Contact Center module (active, multi-phase project)

The **Contact Center** module set is a large, multi-phase orchestration layer built between the CRM (Omnichannel) and Telephony modules. The planning scaffolding (the multi-phase plan documents and their release-tracking ledgers) has been retired now that the work has landed; the short retained record of what shipped and what remains as an operator step is [`.github/contact-center/PRODUCTION-READINESS.md`](contact-center/PRODUCTION-READINESS.md). Consult it for the shipped scope, the MVP boundary, and any outstanding deployment-acceptance steps before doing Contact Center work (anything under `src/**/CrestApps.OrchardCore.ContactCenter*`).

Key rules for this module set:

- Respect the layer boundary: **CRM (Omnichannel) owns business work data, Contact Center owns orchestration, Telephony owns media execution.** `OmnichannelActivity` remains the universal work item; `Interaction` is communication history for one attempt and never owns workflow or disposition.
- **Never** write competitor product names in code, comments, identifiers, or public docs. Adopt only generic, industry-standard terminology.
- Group related capabilities into separate, feature-gated Orchard modules/features, the way commercial platforms separate licensed capabilities.
- The runtime/architecture-contract ledgers under `.github/contact-center/` (`support-matrix.v1.json`, `feature-dependency-violations.v1.json`, `feature-lifecycle-contracts.v1.json`) are consumed by ordinary tests and must stay in sync with the code they describe.

## Working Effectively

### Prerequisites and Environment Setup
Expand Down Expand Up @@ -136,6 +147,7 @@ dotnet run
#### Documentation

* Keep public docs and comments accurate and aligned with the code.
* In Markdown docs, do not manually hard-wrap prose at a fixed column. Keep each paragraph or list item on a single line and let the editor/viewer wrap it visually.
* Always document:

* Every public method (including constructors) with XML `<summary>` and `<param>` tags.
Expand Down
Loading
Loading