A running log of improvements, new features, and fixes. We ship fast so you can work smarter.
Staff can now reply to a
received Lead email from the Lead's activity timeline or message
detail. The composer opens on Email with a single
Re: subject and sends real
In-Reply-To and References headers built
from the received message's stored thread details, so replies thread
correctly in the recipient's mail client. Templates never replace the
reply subject, the original message is not quoted by default, and you
can switch a reply to SMS. Older messages without thread details still
reply, without fabricated headers. The stored thread metadata is
encrypted, excluded from audit snapshots, and never logged.
The manual Lead composer now supports SMS as well as email, each with a saved template or free text. Choose a channel and only that channel's templates appear. A manual SMS uses the Lead's saved mobile number, records one Lead-owned plain-text history entry, and deducts one SMS credit after a successful send. If the credit cannot be recorded, staff see a warning while the sent message and its history are kept. Existing workflow and bulk SMS credit handling is unchanged.
Staff can now send a manual email to an
unconverted Lead using a saved template or free text. The feature is
gated by the Leads toggle. The recipient is always
the Lead's current saved contact, sends record exactly one Lead-owned
sent entry with the pre-tracking body, and converted Leads are
redirected to the Customer. If the provider accepts a message but its
history cannot be saved, staff see an explicit warning instead of a
false failure. SMS and threaded replies ship in the same release
(see the entries above).
Lead-to-Customer conversion now uses
the tenant's saved Lead Conversion Configuration. MVC, API, and
sure-cli lead convert share the same apply path; CLI
conversion accepts an ID or email and sends no mapping JSON. The
historical OpportunityToPlanConversion toggle is no
longer a runtime gate.
AI correspondence replies now support unconverted Leads as well as Customers, including Leads created by unknown-sender processing. Automatic and Manual queue sends record Lead-owned history, and each queued reply has exactly one Customer or Lead owner. Existing Customer behavior and AI controls remain unchanged.
Lead custom-field edits now appear in the main Lead Details form and save with the normal Create Lead or Save Changes action. The separate custom-field tab and save action were removed, with checkbox false values and disabled-toggle protection preserved.
Supplier custom fields and Supplier
workflows are now always enabled. The SupplierCustomFields
and SupplierWorkflows feature toggles have been removed
from the UI and backend, and a migration deletes their catalogue rows —
Supplier definitions always appear in Custom Field administration,
Supplier fields always render on the Supplier form, and Supplier
workflow choices, manual starts, triggers, and Email/SMS stages no
longer check a toggle.
Lead targeting in Bulk Actions no longer
has its own feature toggle. The LeadBulkActions toggle has
been removed from the catalogue, and the general Leads
toggle now gates Lead preview, job creation, and the record-type
option on the Bulk Actions page; ProcessBulkActions
continues to gate background processing.
Bulk Actions now supports non-converted Leads as well as Customers. Lead jobs can change a status, start an active Lead workflow, send Email, or send SMS. Targets come from a saved Lead view or search/Campaign filter and are captured when the job is created. Converted or failed records do not stop the remaining Leads; successful sends create Lead-owned history, and bulk SMS deducts one credit after a successful send. Customer behaviour remains unchanged.
Custom Field administration now supports Supplier definitions alongside Customer and Lead. Active Supplier fields appear on the staff Supplier form in display order and support Text, Number, Date, DateTime, Checkbox, Dropdown, and TextArea values, with tenant-local encrypted storage; they are always enabled. Supplier fields do not add portal, search, reporting, export, API, CLI, workflow, template, or bulk-action behaviour.
Supplier Checkbox values now persist when changing from true to false, and reopening a Customer custom-field definition preserves its Show in Customer Portal setting.
Lead statuses now use one
tenant-local Statuses lookup with separate
Customer and Lead types. The migration seeds eleven legacy
Lead names for compatibility; there is no Docker/baseline
or application catalogue or hard-coded runtime status IDs.
Settings > Statuses offers Customer/Lead tabs, preserves
type on edit, and refuses deletion when a Customer or Lead
record is assigned. Both workflow types store typed status
GUIDs in statusId; Lead stages reject Customer
rows, including historical Customer GUIDs. Lead API/CLI
writes accept names or matching GUIDs, while list, claim,
build-failure, and completion responses retain the stable
wire names New, Processing,
BuildFailed, and ReadyForEmail
without exposing UUIDs. Workflow-only deletion protection
is explicitly out of scope and remains open, not a blocker.
PR #35 review blockers now have
test-first regression coverage: Customer status ownership is
validated on create, update, and conversion, and converted
inbound mail routes from Lead.CustomerId rather
than the mutable status name.
Accepted PR #35 validation recorded build 0 warnings/0 errors, prior full EmailAgent 53/53 plus focused 10/10, Services 50/50, and final Integration 253/253. Disposable cross-product browser QA passed with real Dark Leads and Dark Orchestrator clients; app-created status IDs produced name-only responses with no UUIDs. A later EmailAgent invocation was blocked pre-discovery by sandbox local-socket permission; earlier complete and focused green evidence covers it.
Correspondence mailboxes can now use an optional AI Reply Agent prompt. Blank mailbox prompts retain the tenant-wide prompt, then the built-in default. Support mailboxes and existing manual queue items are unchanged.
Form submission details now show each answer's current configured field label. Renamed labels update existing submissions, and removed or unknown fields retain readable fallbacks.
Administrators now see the pending AI Reply Queue count on the dashboard.
Lead-typed workflow triggers now fire for lead-owned child entities. Events for LeadTag, LeadActivityHistory, LeadCustomFieldValue, LeadTask, Opportunity, and lead-owned NotificationHistory rows (for example inbound email with Direction = Received) were previously dropped because the dispatcher only resolved a customer owner; they now resolve the owning lead and enqueue with LeadId set.
Workflow trigger entities now respect the workflow record type: Lead workflows require Lead, Customer workflows exclude Lead, and stage-condition entity choices remain broad. Mismatched saves are rejected server-side; legacy mismatches require explicit re-selection. Save errors now show the human-readable validation message instead of a raw JSON response.
Removed the single out-of-scope workflow trigger test that had been the prior validation exception. The corrected suite inventory is 289 tests, all 289 passing, with no skips or remaining failures. Legacy mismatched trigger rows already stored in a database can still enqueue for the wrong workflow type; this cleanup removes the signal without changing that underlying gap.
Corrected integration-test database isolation so converted fixtures share one owned schema set per xUnit class and run, while class labels keep concurrent classes isolated. The status-list fixture resets only its test rows to preserve pristine exact-result assertions; stable-seed and KEEP_TEST_DB diagnostics remain available.
Integration test database isolation now uses owned unique names for the converted Lead read, legacy API, and SalesBrief page fixtures. Sixteen focused cases passed in repeated serial runs with no residual test databases; stable failure-reproduction and KEEP_TEST_DB diagnostics remain available.
Lead claim and sample-site build-failure integration fixtures now use owned unique databases. The 20-case and 29-case classes each passed twice in focused serial runs with no residual schemas; stable seed and KEEP_TEST_DB diagnostics remain available.
Sample-site completion and Lead status-list integration fixtures now use owned unique databases. The 29-case and 26-case classes each passed twice in focused serial runs with no residual schemas; stable-seed and KEEP_TEST_DB diagnostics were retained and cleaned exactly.
Reference-backed promotion, opportunity conversion, and Lead workflow integration fixtures now reuse one owned database set per class. Forty-eight runtime cases passed twice in focused serial runs with no residual schemas; stable-seed and KEEP_TEST_DB diagnostics retained and cleaned their exact database names.
Lead workflow email and SMS sends now write one owner-scoped communication row with the original email body captured before tracking. The timeline no longer double-counts sends; failures remain failures, historical sends without stored bodies remain unavailable, and Customer tracking metrics are unchanged.
Lead Activity now combines its complete history with stored notes and received email. Staff can open the actual owner-scoped message; formatted email is sanitized before display, internal viewing does not change tracking state, and send entries without stored content clearly identify that it is unavailable. Internal Note details omit direction and recipient badges because those fields do not describe an internal note. Existing Customer action logs retain safe formatted rendering.
Sample-site completion no longer treats
build order as a customer preference. Both forms preserve an existing
PreferredSite, leave an unset preference unset, and allow
an exact retry after a human choice. CRLF/LF line endings compare as
equivalent without rewriting stored text; a different URL or order
still conflicts. Validator 0efb493c and browser QA
398f4e07 passed; source is complete, not deployed.
Sample-site completion now accepts an optional batch of successful URLs and a minimum-success threshold. It retains partial or empty results, records the final ReadyForEmail or BuildFailed status atomically, and preserves the existing one-URL client contract.
CRM-side validation passed
271/271 tests: 190 integration tests across 17 classes,
40 Email Agent tests, and 41 Services tests, with no
failures, skips, missing or extra tests. The build
reported 0 errors and 0 warnings. No schema or dependency
change is included, and the existing one-URL contract
remains supported. Full Feature Review
94c21c7f approved all three exact source
heads with 0 blockers. Dave owns CRM deployment, which
must precede the Orchestrator batch consumer; this is
source preparation only.
Lead workflow Set Status stages now offer Lead statuses and preserve the selected status when reopened and run. Customer workflows retain GUID-based statuses. Historical Lead stages containing a Customer status require an explicit staff correction; they are not guessed, migrated, run, or resent automatically. Source is complete but not deployed, and no production workflow is repaired.
Independent validation reconciled all
279 retained test names: all 279 passed, with no skips, missing, extra,
or duplicate tests.
Workflow tests passed 15/15, including all three new editor journeys;
Completion passed 29/29 and Services passed 41/41. Implementation review
45520eed0 found no blockers, and browser QA
0d0e6da2 passed the Lead, Customer, historical correction,
Wait, and mobile journeys.
Customer workflow instances now retain their original customer ownership when a Set Status stage updates the customer, so completed instances remain visible in the customer's Workflows tab. Source is complete but not deployed; existing detached instances are not repaired, and Dave owns production CRM deployment.
Ownership validation at the exact tested source head is corrected to 272 retained tests, all passing. No test was skipped; legacy mismatched trigger-row enqueue behavior remains outside that slice's scope.
One-command integration-test database
isolation is complete for shared-host fixtures: class-scoped owned
names converge in repeated serial runs at about 7.5 minutes, and
exact cleanup leaves no residual test databases. Each final run
reported 218 passed, 1 upstream workflow-contract failure, 0 skipped,
and 219 total; the suite is not green and the failure is accepted for
this PR only. The unchanged MySQL 5.7 disposable-container path
remains supported, including its task-owned --rm containers
and fixed internal names.
HTML email templates now support
[Lead.SampleSiteUrlsHtml], which renders non-blank
sample-site URL lines as an ordered, HTML-encoded list while
preserving the existing plain-text token and CRM storage.
Supplier workflows now provide a third
persisted workflow type, Company, shown as
Supplier to staff. The tenant-local
SupplierWorkflows toggle is disabled by default. When
enabled, administrators can create and manually start Supplier
workflows, or enroll Suppliers on Company Added/Modified triggers.
Supplier stages support Email, SMS, Set Status, Wait, Start Workflow,
and REST actions, with Company conditions and safe skips for unsupported
actions. Supplier Email/SMS do not create communication history.
Supplier workflow source closure records Slice 1 at 30/30, the post-main-merge focused checkpoint at 48/48, Slice 2 at 69/69, and Slice 3 at 85/85. Privacy fixes keep echoed REST response content and Supplier template IDs out of persisted feedback and audit logs. Browser QA and the full release suite remain next gates; source is complete but not deployed.
The email agent now posts every
inbound email it can associate with a known record to that
record's notification history — on both correspondence and
support mailboxes, and to both a customer and
a lead when they share the sender's email address. A converted
lead is skipped so its communication continues on the customer
record only, and recording an existing lead no longer depends
on the UnknownSenderProcessing toggle. Email
matching is now case-insensitive throughout the inbound
pipeline.
The Unknown Sender Action now only creates a customer or lead when no customer or lead exists with the sender's email address; previously the lead check ran inside the toggle-gated unknown-sender path, so an existing lead could be missed when the toggle was disabled.
Workflows are now multi-entity: every workflow declares a primary Record Type of Customer (default, existing behaviour preserved) or Lead, chosen in the builder and locked once the workflow has stages or is active. Database triggers can be defined on the Lead entity (lead created/modified) for full automatic lead enrollment, and manual start is type-aware — the customer page lists Customer workflows and the lead page's Workflows tab lists Lead workflows. Lead workflows support Email, SMS, Update Status, Wait, and Start Workflow (child) actions, evaluate stage conditions against lead fields (status, attempt count, business name, contact details, campaign, and more), and skip customer-only actions with a clear message on the stage instance. The workflow list shows a Record Type column, and instance details link lead-driven instances back to the lead.
Opportunities gained a Revenue Frequency field (OneTime, Weekly, Monthly, or Yearly), editable on the opportunity form. It records how often a deal's revenue recurs and drives billing when a plan is created from the opportunity at lead conversion.
Added
toggle-gated opportunity-to-plan conversion
behind the disabled-by-default
OpportunityToPlanConversion
feature toggle. When enabled, converting a
lead to a customer links all of the lead's
opportunities to the new customer and creates
a Customer Plan from each
closed/won opportunity — named after the
opportunity, priced at its value, and billed
at its revenue frequency (a one-time plan
with a positive price also raises the
customer's initial balance) — all in a single
transaction, with activity-history and
application-log entries. When disabled,
conversion behaves exactly as before.
Support ticket
due dates are no longer behind a
feature toggle: the due date picker on the create
form, the due date column and overdue filter on the
support list, the due date actions on the ticket
page, and the dueDate field in the
support ticket API are always available.
Feature toggles are
now grouped by functional area on the Feature
Toggles page instead of all sitting under
Master Features. Group headers
include AI, Balance,
BackgroundEngine, Campaigns,
Email, Leads,
Opportunities, and Security
— for example LeadImport sits under
Leads and
OpportunityToPlanConversion sits under
Opportunities.
Custom fields
now have an Applies To type of
Customer or Lead.
Lead fields render on the lead form's Custom
Fields tab (under the
LeadTagsAndCustomFields toggle) and
are stored separately from customer fields, so a
field designed for customers no longer appears on
leads and vice versa. The Custom Fields admin
page shows the type per field and matches the
modern application styling.
AI customer
summaries are now cached for 24 hours
in a per-customer database table, so repeat
summary requests are served from the cache
instead of re-calling the AI provider, saving
API credits. Caching is on by default and
controlled by the
AiCustomerSummaryCache toggle (under
the AI group) — disable it to call
the provider on every request, for example while
testing prompt changes. Cache rows expire after
24 hours, are rewritten on the next request, and
are removed when the customer is deleted.
Repaired the September 4 EF migration path so all intended migrations are discovered, the supported baseline keeps its existing Bulk Action index, and a logged migration failure stops startup. The obsolete manual SQL upgrade script was removed: deploy the application so EF migrations remain the only supported schema-upgrade path.
Added a guarded EF
migration for the missing
OpportunityKanban feature toggle. The
seed is disabled under Opportunities,
preserves any existing same-name row, and does not
alter other feature settings.
Reconciled the 20
feature toggles present in the supported Docker
baseline but missing from EF-created tenants. Each
missing row is inserted disabled, existing rows are
preserved, and ProcessInboundEmail uses
its current BackgroundEngine grouping.
The AI Settings page
now offers two additional providers:
OpenRouter (preset endpoint
https://openrouter.ai/api/v1/chat/completions,
use its vendor/model model names) and
OpenAI-compatible endpoint for any
self-hosted or third-party OpenAI-compatible
server (vLLM, LM Studio, proxies) — the Base URL
is required for that option and is validated as an
absolute http(s) URL on save. Both reuse the
existing OpenAI chat-completions request shape, so
Test Connection, auto-reply, template generation,
and customer summaries work unchanged.
Added the AI Email
Assistant, gated by the disabled-by-default
AI feature toggle. A per-tenant AI
Settings admin page configures the provider
(OpenAI, Anthropic, or Kimi), model, encrypted API
key (blank keeps the stored key), optional Base URL
override, reply agent prompt, and max tokens, with
a Test Connection button. Inbound correspondence
email can be answered automatically via tenant SMTP
or drafted into an AI Reply Queue where admins
review, edit, send, or discard each reply, and a
Generate with AI button on the Email and SMS
template pages drafts subject and body for review
before saving.
Added rule-based
unknown-sender email processing, gated separately
by the disabled-by-default
UnknownSenderProcessing toggle. When
enabled, the Unknown Sender Action setting
(Email Agent admin page) lets the email
agent create a customer or a lead from inbound
correspondence whose sender matches no existing
customer; existing leads always receive the mail
body in their shared communication history, and
new leads are bucketed into the tenant's first
campaign.
Added on-demand AI
customer summaries on the customer overview page,
gated by the AI master toggle plus the
new disabled-by-default AiCustomerSummary
child toggle (summaries consume provider tokens, so
nothing generates automatically). A Generate
Summary button produces a short factual summary of
the customer's current position — balance and
status, recent payments, recent communications,
open support issues — with the tone controlled by
the new Summary agent prompt on the AI Settings
page.
AI provider API keys are stored encrypted per tenant, are never written to logs, and are redacted from logged provider error messages; AI failure logs contain no customer or lead PII.
Closed the SalesBrief
write/read boundary on the legacy API-key Lead
routes (POST/PUT/GET api/lead and
GET api/lead/byEmail): they no longer
accept, replace, erase, or serialize
salesBrief, regardless of the
feature toggle. The brief remains writable only
through the authorised Lead form and the external
promotion handoff, and readable only through the
dedicated opaque-reference read API.
Extended the SalesBrief
feature: the external promotion payload accepts an
optional salesBrief (max 8,000
characters, trimmed, blank values stored as null)
stored on the Lead at creation and never compared
or overwritten on replay; added a feature-gated
Lead read API
(GET /Api/external/leads/{externalReference})
returning exactly the external reference, business
name, brief, and optional contact email and phone;
and added an optional
hasSalesBrief=true filter to the Lead
status list API that restricts results to Leads
with a brief while omitted/false behaviour is
unchanged.
Added a nullable
SalesBrief field to the Lead (MySQL
TEXT, max 8,000 characters) with a
feature-gated textarea on the authorised Lead
create/edit form. The textarea shows a live
character count when the disabled-by-default
SalesBrief toggle is enabled and is
hidden otherwise; direct form submissions cannot
store or replace a brief while the toggle is off.
Briefs are trimmed, blank values are stored as
null, and the stored text is always rendered as
untrusted text, never raw HTML.
Added an atomic Lead claim API
(POST /Api/leads/claim) for automated
sample-site claiming. Transitions one Lead from
New to Processing by opaque
external reference with optimistic concurrency;
concurrent claimers yield one success and
409 for the rest. Gated by the
disabled-by-default
AutomatedSampleSiteClaim toggle.
Added a feature-gated Lead status list API
(GET /Api/leads/byStatus) for automated sample-site claiming.
Returns opaque external references only, with keyset pagination (max page size 20),
and is disabled by default via the AutomatedSampleSiteClaim toggle.
Added atomic, feature-gated external Lead and initial Opportunity promotion with safe retries, conflicts, and tenant-scoped references.
External handoffs now use opaque references rather than CRM UUIDs; existing Lead and Opportunity APIs remain compatible for their current clients.
Added feature-gated, tenant-scoped external references and campaign selection APIs with idempotent campaign creation.
Added an Opportunities pipeline with stage-based board view, value tracking, probability, and expected close dates linked to leads.
Added Lead Tasks for assignable to-do items with due dates, priority, and status tracking.
Added Opportunities and Lead Tasks tabs to the lead detail page, with activities recorded in the lead timeline.
Added REST API endpoints and CLI commands for managing opportunities and lead tasks.
Added "Opportunities" and "LeadTasks" feature toggles under Master Features.
Updated API and CLI documentation with the new opportunities and lead tasks reference material.
Fixed TenantDatabaseMigrator to correctly migrate fresh databases and surface migration errors instead of swallowing exceptions.
Made lead names clickable in opportunity, task, and task-list views so users can jump straight to the lead detail page.
Added a feature that lets administrators design custom forms for customer data collection.
Added secure form fill links for customers to complete assigned forms.
Updated customer portal to show completed and pending forms.
Added notification groups to administrator console.
Updated workflow engine to allow processing of communications to customer/notification group.
Added sendTo option in the workflow builder to support customer/notification group.
Recreated the administrator console - manage user screen.
Fixed a bug where customer ids associated with a failed bulk action job was not clickable.
Added support to track bank transfer payments to an individual bank account.
Updated the Admin setting navigation to use modern styling.
Payment module updated to add support for different transaction types such as Adjustment, Payment and Refunds.
Tenant selector updated to supporting customers with multiple domains.
Added a toggle to custom fields to determine if they should display fields on the customer portal.
Added a new Feature Toggle section in the administration view to easily toggle on/off features.
Various bugs fixed.
Dashboard component refresh with faster data loading and new KPI cards for active workflows and aging balances.
Resolved an edge case where portal payment callbacks could duplicate balance records under high concurrency.
UI alignment fixes on the customer detail screen for mobile viewports.
Payments via customer portal — customers can now pay outstanding balances directly through the self-service portal with Stripe and PayPal support.
Portal payment receipts now include PDF generation and automatic email dispatch.
Completely redesigned workflow builder with drag-and-drop stage reordering, modern card-based UI, and real-time validation.
Create Record workflow action — automatically create new entities (payments, plans, disputes) from within a workflow stage.
Start Workflow action — chain workflows together to build complex automation pipelines.
Custom field support inside workflows — read and write custom field values dynamically during workflow execution.
Entity field references in workflow actions now support aggregation (First, Last, Max, Min, Sum, Average, Count).
Removed legacy appointment support to simplify the data model. Appointments will return in a future dedicated module.
Two-factor authentication (2FA) support added for all admin and agent accounts using TOTP authenticator apps.
Support requests and customer portal access — customers can now raise tickets and track progress without agent intervention.
Bulk action engine — select multiple customers and apply tags, status changes, or start workflows in one operation.
Backend filtering for customer grids now supports multi-column searches with debounced input.
Calendar view for customer data — visualize appointments, important dates, and plan renewals in a month/week/day layout.
One-time payment support — record ad-hoc payments without needing a recurring plan attached.
Calendar navigation bug where switching months would reset the selected custom field filter.
Recursive workflow start — workflows can now safely trigger other workflows with infinite-loop prevention built in.
Set custom field workflow action — update custom field values dynamically using static values, calculated expressions, or entity references.
Time support added to calendar events and custom date-time fields.
Custom fields system — define unlimited custom fields per tenant with text, number, date, date-time, and boolean types.
Dynamic values — use calculated expressions and entity field references inside workflow actions and data field updates.
API controller with token-based authentication for third-party integrations.
Customer detail screen redesigned with tabbed navigation and custom field sections.
Twilio dialer embedded in the CRM — make and receive calls without leaving the app.
Call controls (mute, hold, transfer) and agent status dashboard for queue management.
Search indexing issue that caused customer lookups to return stale results after bulk imports.
Dialer button on customer cards for one-click outbound calling.
Encryption field configuration now pulls from tenant database settings rather than static config.
Tenant DTO serialization bug that caused multi-tenant context switches to fail intermittently.
Mass action support — apply actions to filtered customer lists directly from grid views.
Option to disable field-level encryption per tenant for performance-critical deployments.
Custom views — build and save filtered customer views with custom columns, sorting, and date ranges.
Quick views sidebar for one-click access to commonly used filters (Overdue, New This Week, etc.).
Customer plan refactoring — individual plan fields (service name, price, billing frequency, due days) replace rigid plan types.
Workflow improvements including stage condition evaluation and better error logging on failure.
Set data field workflow action — programmatically update customer fields like Age, Important Date, or Referral Source.
Workflow quick link for jumping directly to a customer's active workflow instance from the grid.
Optional auditing feature toggle — enable per-tenant audit trails for compliance requirements.
Workflow ordering bug where stages could execute out of sequence after a database rollback.
Customer aging background task no longer runs on a constant loop when no tenants are configured.
Start workflow action — trigger a workflow manually from within another workflow or via the API.
Workflow engine processing reliability with retry logic and better failure state handling.
Workflow builder — visually design multi-stage workflows with delays, conditions, and actions.
Workflow engine background service — processes scheduled workflow stages automatically.
Owner assignment — assign customers to specific agents with filtered views.
Background service stability fixes preventing the hosted processor from stalling on tenant switches.
Referral tracking — capture and report on how customers found your business.
Database query performance optimizations for large customer lists (>50k records).
Slow query timeout on the customer dashboard for tenants with heavy plan data.
Feature toggle system — enable or disable modules per tenant without redeploying.
Status change bug where updating a customer's status would not cascade to related plan eligibility checks.
Tag service and background processing — auto-apply tags based on rules and process tag-based reports.
Tag helper performance and view rendering speed for customer grids with many tags.
Reporting engine with parameterized reports — create reusable reports with date ranges, status filters, and tag inclusion.
Transaction history and balance reporting with drill-down to individual payments.
Customer UI overhaul with better search, filtering, and inline editing capabilities.
Action manager, SMS service, and credit manager for pay-as-you-go message billing.
Notification action service with queue-based dispatch for emails and SMS.
Report parameter bug where empty optional parameters would crash the report viewer.
Dashboard with key metrics, recent activity feed, and quick-action shortcuts.
Global settings panel for SMTP, branding, and default page size configuration.
Audit log UI — view every change made to customers, plans, and payments with before/after snapshots.
Call audit trail for tracking agent activity and call outcomes.
Various UI bugs on mobile viewports and form validation edge cases.
Multi-tenancy support — run multiple CRM instances from a single deployment with isolated data and branding.
Account lockout protection after repeated failed login attempts.
SMS credit calculation bug that under-reported remaining credits in the admin panel.
Data encryption at rest for sensitive customer fields using AES-256 + RSA hybrid encryption.
Decryption performance optimized with parallel processing and property caching.
Query filter middleware bug that caused data leakage between concurrent requests.
Customer management with full CRUD, advanced search, tagging, and status tracking.
Customer plans and recurring billing with automated balance generation.
Payment recording with dispute tracking and resolution workflows.
Document storage with file upload and customer association.
Email and SMS templates with token replacement for personalized messaging.
User management with role-based access control (Admin, Agent, ReadOnly).
Automated action designer for event-driven emails, SMS, status changes, and tag updates.
Scheduled action processor for time-delayed automation.