Changelog
All notable changes to Signals, ordered by version.
0.2.0 — People & Places
Added
Members Module
- Members module — universal entity for contacts, organisations, venues, and users
- Members list page with search, type filter chips, column sorting, column filtering, bulk selection, and archive/restore
- Member detail page — CRM-style 3-column layout with left sidebar (avatar, quick actions, key contacts, account details), center content (stat cards with sparklines, AI recommendations, activity timeline), and right sidebar (customer health score, health factors)
- Member create and edit forms — 2-column layout with membership type, status, description, locale, currency, tax class, and conditional org/contact sections
- Contact detail management — addresses, emails, phones, and links with primary flags and type classification
- Member relationships — link contacts to organisations with relationship type labels
- Member archive and restore — replace delete with soft-archive, restore from archived view, archive filter chips (Active/Archived/All)
- Member merge — select two same-type members, side-by-side comparison modal, migrates all polymorphic relations (addresses, emails, phones, links, attachments), relationships, custom fields, and memberships to primary; archives secondary
- Member profile icon in page header — visible on all member pages, white box with border and shadow, initials fallback
- Phone country code —
country_codecolumn on phones table, flag emoji picker with searchable country dropdown and dial code display, international format on information page - Searchable country combobox on address form — replaces plain
<select>withx-signals.comboboxfor 246 countries - what3words geocoding on address form — forward lookup (three words to coordinates), Nominatim geocode from address fields, interactive Leaflet.js map with draggable marker
- Command palette with live member search — triggered by
/orCmd+K, 22 static commands plus live search with type badges and status indicators - Keyboard shortcuts on member pages —
eto edit,nto open New dropdown - Member API endpoints — full CRUD for members, addresses, emails, phones, links, and relationships
- CRMS-compatible member API responses — active flag, membership object, type-specific fields, icon object, child/parent members
- Auto-create User-type member on user creation via InviteUser action
- BackfillUserMembers command for existing users
Custom Fields
- Custom field groups — create, edit, reorder, and delete groups that organise custom fields
- Custom fields admin — 16 field types (Text, TextArea, Integer, Decimal, Boolean, Date, DateTime, Time, Select, MultiSelect, URL, Email, Phone, Colour, Currency, Percentage, RichText) with validation rules, default values, and list-backed dropdowns
- Custom field values on member detail pages, grouped by field group
- Custom field enforcement — default values applied on creation, is_required validated before persistence, is_searchable and is_active enforced in queries
- Custom field multi-value support for multi-select fields
- Auto-number sequences for custom field auto-numbering
- Default
custom_fieldsin member API responses — CRMS-compatible, no explicit?include=customFieldValuesrequired - Custom field API endpoints — CRUD for groups and definitions
Custom Views
- Custom views system — saved list configs with columns, filters, sort order, and visibility levels (personal, shared, role-restricted)
- View builder Livewire component — create and edit custom views with column picker, filter builder, and sort configuration
- Column registry — schema-driven column definitions for DataTable, custom view validation, and API field selection
- DataTable custom views integration — view selector dropdown, filter/sort application from saved views
- Custom views API endpoints — full CRUD
Multi-Currency
- Currencies table (ISO 4217) with CurrencyService for conversion
- Exchange rates with effective dates — create, update, delete via admin and API
- Currency and exchange rate API endpoints
- Currency seeder with ISO 4217 data
File Attachments
- Polymorphic
attachmentstable with S3 signed URLs and virus scanning support - File service — S3/public disk abstraction with signed URL generation, icon upload, and thumbnail creation
- Icon upload Livewire component
- File upload modal on member pages
- Attachment API endpoints
Reference Data & Lists
- Lists (reference data) — create and manage named lists with hierarchical values, system/non-system flags, and active/inactive status
- Built-in system lists seeded on install: AddressType, EmailType, PhoneType, LinkType
- Additional list categories: Lawful Basis Type, Location Type, Rating, Invoice Term, Locale, Currency
- Countries admin page — browse, search, and toggle active status
- List API endpoints — CRUD for list names and list values
- Countries API endpoints — read-only index and show
Tax
- TaxCalculator service — resolves tax rules by organisation + product tax class matrix with fallback to defaults, bcmath precision, currency-aware decimal formatting
- Tax classes — product and organisation tax classifications with default designation
- Tax rate and tax rule API endpoints — full CRUD with Ransack filtering
- Tax rate and tax rule admin pages — create, edit, delete with priority ordering
- Tax class API endpoints — CRUD for product and organisation tax classes
Authorization & Security
- Model policies for 10 domain models — Member, Store, CustomField, CustomFieldGroup, ListName, OrganisationTaxClass, ProductTaxClass, Webhook, ActionLog, EmailTemplate
- RoleLevel enum — hierarchical role ordering for authorization comparisons
- Policy traits —
AuthorizesByPermissionandChecksStoreAccessextracted from 8 policies - Store scoping via
StoreScopeglobal scope andHasStoreScopingtrait — request-scoped via Context facade, Octane-safe - Cost visibility trait —
HasCostVisibilitywith fail-closed design, explicit user parameter for queue contexts - Blade permission directives —
@area,@action,@costsfor template-level authorization
Schema & Query Engine
- Field Registry and Schema Engine —
HasSchemacontract,SchemaBuilder,SchemaRegistryfor unified field metadata across core, computed, and custom fields - Ransack filter enhancements —
matches(regex),start,end,present,blankpredicates; relationship filtering; custom field EAV filtering viacf.prefix; per-token rate limits - Reusable
applyIncludes()in FiltersQueries trait with$defaultIncludesand$allowedIncludesproperties
Admin & Settings
- Admin Integrations settings page — encrypted API key storage for what3words, Google Maps, and future third-party services
- Feature profiles — Full, Lite, Warehouse, Services presets for module configuration
- Setup wizard improvements — infrastructure checks, branding step, module selection, feature profile presets
- Admin seeder management page — run seeders from the admin panel
- Getting started checklist on dashboard — tracks setup completion progress
Infrastructure
- Reusable DataTable Livewire component — configurable columns, sorting, filtering, pagination, row selection with shift-click range, bulk actions, and event-driven refresh
- CustomFieldCopier service — copies custom field values between entities when field name + type match
- Permission registry
validate()method for reusable permission validation - Action log export job — async CSV export with date validation, failure notifications, and retry configuration
- Social promo pages — LinkedIn (1200x627) and Instagram (1080x1080) format
Quality
- PHPStan upgraded from level 5 to level 6 — 168 generic type annotation fixes, zero errors across 618 files
- 7 new migrations: currencies, exchange rates, attachments, custom views, custom view roles, user view preferences, phone country code
- 100+ new tests across actions, services, Livewire components, DTOs, and pre-existing coverage gaps
- Documentation pages for Members, Custom Fields, Lists, Tax Classes, Countries, Currencies, Exchange Rates, Attachments, and Custom Views
Changed
- Member show page redesigned as 3-column CRM-style layout with stat cards, AI recommendations, and activity timeline
- Member form redesigned as 2-column layout with conditional org/contact sections and list-value dropdowns
- Members list bulk action changed from delete to archive with confirmation modal
- Row actions changed from delete to archive/restore based on member state
- Admin sidebar expanded with Data section, Tax section, and Integrations under Preferences
- Demo data seeder updated with sample members, contact details, custom fields, lists, and tax classes
- RansackFilter uses grammar-wrapped column quoting for SQL safety
- CustomFieldSerializer uses batch loading for ListOfValues fields (eliminates N+1 queries)
- ExportActionLog validates date filters and notifies users on failure
- AnonymiseMember uses
refresh()instead offresh()for null safety - PermissionRegistry centralises permission validation (removed duplication from CreateRole/UpdateRole)
- UpdateMemberData membership_type changed from
?stringto?MembershipTypeenum - MergeMember action wraps all operations in DB::transaction with orphan cleanup
- ArchiveMember action wrapped in DB::transaction for atomic state changes
- What3WordsService adds HTTP timeouts (10s) and logging on all failure paths
- MergeModal catches exceptions with user-friendly flash messages instead of raw 500 errors
Fixed
- SQL injection vector in RansackFilter
matchespredicate — column names now safely quoted via query grammar - Relation filter column names validated against
[a-z_][a-z0-9_]*pattern to prevent injection - ILIKE wildcard characters escaped in SearchController to prevent pattern injection
- TaxResult decimal accessors now respect per-currency minor unit exponents (JPY, BHD, KWD, etc.)
- TaxCalculator uses pure bcmath chain — eliminated float intermediate that could cause precision loss
- StoreScope replaced static mutable state with request-scoped Context facade (Octane-safe)
- HasCostVisibility throws LogicException when
$costColumnsproperty is missing (fail-closed instead of fail-open) - BackfillUserMembers wrapped in DB::transaction with per-user error handling
- Gate::authorize('members.view') permission check added to SearchController
- RestoreMember guards against restoring non-deleted members
- Migration logs warnings for unresolvable ListOfValues during type code realignment
0.1.0 — Initial Alpha
Added
- Infrastructure install wizard (
signals:install) with interactive configuration for PostgreSQL, Redis, S3, and Reverb - Web-based setup wizard for company details, stores, feature profiles, branding, and admin account creation
- CLI setup command (
signals:setup) as terminal alternative to web wizard - Status command (
signals:status) for checking infrastructure connection health - Livewire authentication system with login, forgot password, email verification, and profile settings
- Two-factor authentication (TOTP) with recovery codes, manageable from Settings → Profile
- Composite dashboard with branded design system and KPI cards
- Documentation system with markdown rendering, full-text search, and three-column layout
- API documentation auto-generated via Scramble at
/docs/api - Demo data seeding (
signals:seed-demo) for evaluation and testing - Landing page with technical blueprint aesthetic
- Non-interactive mode for CI/CD deployments
- System admin panel with settings management (Company, Stores, Branding, Modules)
- User management with invite, deactivate, reactivate, password reset, and ownership transfer
- User edit page with role assignment and authorization checks
- Role management with system roles (Admin, Manager, Operator, Viewer) and custom role creation
- Role edit page with multi-user assignment
- Permissions reference page showing all registered permissions grouped by domain
- Security settings page for password policies, session timeouts, login lockout, and 2FA enforcement
- Email settings page for SMTP configuration with connection testing
- Database seeders admin page showing seeder status with run controls
- Permission and role seeders integrated into default
DatabaseSeeder - Branding colours (primary and accent) applied across the UI via CSS custom properties
- Invitation system with signed URLs and accept-invitation flow
- REST API (v1) with Sanctum bearer token authentication and scoped abilities (
resource:action) - API token management — create, list, and revoke personal access tokens with granular ability scoping
- Ransack-compatible query filtering engine with 18 predicates (
_eq,_cont,_lt,_in, etc.) and sort support - API endpoints for users, roles, settings, action logs, and system health
- Webhook system — register URLs with event subscriptions, HMAC-SHA256 signed delivery, exponential backoff retry
- Webhook management API — create, update, delete, toggle, and view delivery logs
- Automatic webhook dispatch on user, role, and settings changes
- Auto-disable webhooks after 18 consecutive delivery failures
- ForceJsonResponse middleware ensuring all API responses return JSON
- EnsureActiveUser middleware blocking deactivated users from API access
- Rate limiting on API routes (60 requests/minute per user)
- API documentation pages for authentication, webhooks, and overview
Changed
- Moved
symfony/yamlandlivewire/voltto production dependencies for documentation rendering - Updated documentation URL to
docs.signals.rent - Header navigation bar and mobile sidebar use brand primary colour from settings
- Search input and focus states in header use brand colour tokens instead of hardcoded values
- Auth views updated to use signals component library (
s-*classes) - Component library expanded with 17 new components and
s-prefix convention