Releases
Versioning
The Payroll Engine uses Semantic Versioning. v1.0.0 is the first stable public release. Incompatible changes to the REST API, database schema, or JSON exchange are called out as breaking changes in the release notes and normally ship in a new major version. Minor and patch releases aim to stay backward compatible—always read the notes for your upgrade.
During the earlier 0.y.z development series, breaking changes could occur in any release (SemVer initial-development semantics for major version zero). That phase is complete.
Release Artifacts
A release contains the following artifacts:
Docker Images (GitHub Container Registry)
ghcr.io/payroll-engine/payrollengine.backend— Backend API serverghcr.io/payroll-engine/payrollengine.payrollconsole— Payroll Consoleghcr.io/payroll-engine/payrollengine.webapp— Web Applicationghcr.io/payroll-engine/payrollengine.mcp.server— MCP Server
See the Container Setup page for installation instructions.
Release Assets (download from Assets section below)
| ➡️ Continue to GitHub Releases |
|---|
v1.0.0 - Apr 2026
First stable release. Highlights:
- Wage type caches —
WageTypeCycleCacheandWageTypeConsolidatedCycleCachereduce database round-trips during payrun scripts when wage types are tagged via the corresponding payroll cluster sets PasswordAvailable— user API and client models indicate whether a password is set without exposing the hash- Exchange import — payrun jobs that end with intentional
Abort/Cancelare treated as an expected test outcome during import, not a hard failure
Backend
Database update required — run the Update-Model scripts (SQL Server and MySQL) from schema 0.9.7 → 1.0.0 before starting the backend. Nine legacy Payroll ClusterSet* columns are replaced by a single ClusterSet JSON column; existing rows are migrated in the scripts. The persistence layer enforces minimum schema version 1.0.0.
Breaking changes
- Database schema 1.0.0 — cluster-set columns consolidated (see above)
- Exchange JSON — former top-level
clusterSet*properties onPayrollmove underclusterSet(PayrollClusterSets); migrate existing import/export files
Libraries
- Client.Core —
IPayroll/Payrolluse a singleClusterSetproperty;PasswordAvailableonIUser/User; exchange import honors intentional abort status where applicable
See the full changelog in RELEASE_NOTES.md on the main repo.
v0.10.0-beta.4 - Apr 2026
Highlights
- Payrun Job Import — new
POST /payruns/jobs/importendpoint for archive restore, tenant migration, and staging seeding; transactional, duplicate-safe, with full reference validation - Tenant Isolation — server-wide
TenantIsolationLevelpolicy withTenantIsolationFilter;RegulationShare.IsolationLevelfor per-share access control; cross-tenant consolidation report scripting viaExecuteConsolidatedQuery - MCP Libraries — new
Mcp.Core(infrastructure: isolation model, permission system,ToolBase) andMcp.Tools(27 read-only tools) as standalone NuGet packages - OData Extensions —
any()lambda operator andinoperator for JSON collection column filtering; SQL Server and MySQL backend-aware - Install Regulation Package — new
InstallRegulationPackageconsole command installs regulation NuGet packages directly into a PE backend tenant
Backend
Database Update required — run ModelUpdate.sql (SQL Server, schema 0.9.6 → 0.9.7) or apply the equivalent changes manually (MySQL) before starting the backend.
New Features
- New endpoint
POST /api/tenants/{tenantId}/payruns/jobs/import— importsPayrunJobSet[](payrun job + result sets) from an archive or external system - Phase 1a: resolves all references (Payrun, Division, User, Employee) by stable business-key names; returns
422on failure - Phase 1b: duplicate check by payrun job name; returns
409on conflict - Phase 2: transactional insert with full rollback on failure
PayrollResultdenormalized name fields:PayrollName,PayrunName,PayrunJobName,EmployeeIdentifier,DivisionNameTenantIsolationLevelserver-wide policy —TenantIsolationFilteron every request:None(transparent),Consolidation(report scripts only),Read(GET + ReadSemantic POST cross-tenant),Write(full cross-tenant). See SecurityRegulationShare.IsolationLevel—Consolidation(cross-tenant result access for report scripts, regulation not added as payroll layer) orWrite(full payroll layer, default)Report.ReportIsolation— per-report access control aligned withTenantIsolationLevel- OData
any()lambda operator — filters on JSON collection columns using correlatedEXISTSsub-queries - OData
inoperator — value-set filter mapped to SQLWHERE col IN (...) - MySQL:
IDbContext.BuildCollectionFromRawabstractsOPENJSON/JSON_TABLEdifference
Breaking Change
Payrun.RetroTimeType(enum) replaced byPayrun.RetroBackCycles(int):-1= unlimited (default),0= current cycle only,n= n previous cycles; DB migration required (Update-Model.sql)
MCP Server
- Division isolation:
list_employeespushes division filter to the backend — eliminates client-side post-filtering
Libraries
- Mcp.Core (new) — Core infrastructure for Payroll Engine MCP servers: isolation model, role-based permission system,
ToolBasewith typed service factories and isolation-aware query helpers,ToolRegistrarfor startup-time tool filtering - Mcp.Tools (new) — 27 read-only MCP tools across HR, Payroll, Report and System roles built on
Mcp.Core - Core —
RetroTimeTypeenum removed breaking change - Client.Scripting — WageType and Collector temporal selectors (
.PrevPeriod,.NextPeriod,.Cycle,.PrevCycle,.NextCycle,.RetroSum); newCalculationaction group with 15 standard payroll calculation actions (AnnualProjection,CycleToPeriod,PeriodToCycle,CappedContribution,InsuranceWage,D2Deltaand more); period-offset consolidation actionsGetConsolidatedWageTypeValueandGetConsolidatedCollectorValue
Console
- New
InstallRegulationPackagecommand — installs a regulation NuGet package (.nupkg) into a PE backend tenant; supports local paths, wildcards, and HTTP(S) URLs; features version check, dependency check, dry-run mode - New
PayrunEmployeePreviewTestcommand — tests payrun job preview results without persistence HttpGet: optional second parameter writes response body to a fileHttpPost/HttpPut:Content-Typeset toapplication/json(wastext/plain→ HTTP 415)- URL placeholder resolution:
{tenant:X},{user:X},{division:X},{employee:X},{regulation:X},{payroll:X},{payrun:X},{payrunJob:X}resolved to numeric IDs at runtime
Tests
- New
PayrunJobImport.Test— full export → delete → import → verify cycle forPOST /payruns/jobs/import
v0.10.0-beta.3 - Mar 2026
Highlights
- MCP Server — new
PayrollEngine.McpServerrepo: 29 read-only tools across 4 roles (System, HR, Regulation, Payroll) via stdio transport; compatible with Claude Desktop, GitHub Copilot, and other MCP clients - Backend Diagnostics —
GET /api/admin/informationexposes assembly, API, auth, database (incl. edition), and runtime configuration - MySQL Support — new
Persistence.MySqlprovider (preview) alongside existing SQL Server - Report Isolation —
ReportIsolationscoping across domain, API, and client models - Report Schema Builder — new
ReportBuildconsole command generates or updates.frxskeleton documents;IDocumentService.GenerateAsyncin Document library - Load Test Markdown Report —
PayrunLoadTestnow produces a Markdown report with full infrastructure section (CPU model, RAM, database edition, backend diagnostics) - Test Phase Separation —
PayrunTestRunnerimport and test phases are now independent
Backend
New Features
GET /api/admin/information— new endpoint returning backend diagnostics: assembly version/build date, API version/name, authentication mode (with OAuth authority/audience), database type/catalog/version/edition, and runtime configuration (MaxParallelEmployees, timeouts,ScriptSafetyAnalysis, audit trail, CORS, rate limiting)- MySQL 8.4 LTS support via new
Persistence.MySqlprovider (preview) — activate withPayrollServerConfiguration__DbProvider=MySql IDbContextextended withGetDatabaseInformationAsync()returningDatabaseInformationincluding editionReportIsolation— new domain model and audit trail: report execution scoped toNone,Global,Company,Division, orEmployee
Breaking Change
MaxParallelEmployeesdefault changed from sequential (off) to auto (ProcessorCount) — useoffor-1to restore sequential behavior
Bug Fixes
- Fixed concurrent assembly load collision in
AssemblyCache— proper lock to prevent race conditions during parallel payrun execution - Fixed
CaseValueRepositoryBase.GetPeriodCaseValuesAsyncperiod filter:<corrected to<=forStartboundary
MCP Server (new, preview)
- AI agent interface for payroll data queries — read-only by design, no mutation operations
- stdio transport via Model Context Protocol; compatible with Claude Desktop, GitHub Copilot, Cursor, and other MCP clients
- 28 tools in 4 roles:
System(tenant/user),HR(employee, case values, audit trail),Regulation(wage types, lookups),Payroll(payrun jobs and results) - Employee context enrichment injected into all employee-scoped results;
list_payroll_result_valuesfully denormalized get_case_time_values: Historical, Current, and Forecast temporal perspectives- Role-based permissions (
McpRole/McpPermission) and isolation levels (MultiTenant,Tenant,Division,Employee) configurable viaappsettings.jsonor environment variables - Docker image available;
claude_desktop_config.jsonexample included
Console
- New
ReportBuildcommand — executes a report and generates or updates the schema document (.frxskeleton) for template design PayrunLoadTestMarkdown report: ms/Employee and Employees/h columns in Test Summary; CPU model (Windows Registry), RAM available (GlobalMemoryStatusEx), and database edition in Test Infrastructure section- Fixed report template encoding: ASCII → UTF-8 for FRX, XSL and XSD streams
Web App
- Fixed report template encoding: ASCII → UTF-8 for XSL, XSD and FRX streams
- Fixed payrun job workflow: Draft panel displayed correctly after job start and on page reload
Libraries
- Core —
IDocumentServicewithGenerateAsync,MergeAsyncandExcelMergeAsync;Applyproperty onQuery,ApplyOperationonQuerySpecification; newReportIsolationenum - Client.Core —
AdminService/IAdminServicewithGetBackendInformationAsync();BackendInformationmodel hierarchy incl.Edition;IAttributeServiceadded toIDivisionService,ITaskService,IRegulationService,IReportService;ReportIsolationonIReport/Report - Document —
IDocumentService.GenerateAsync: generates.frxskeleton from DataSet or rebuilds Dictionary section of existing template in CI mode - Client.Test —
PayrunTestRunnerrefactored into separateImportAsync/TestAsyncphases - Client.Scripting — fixed
CasePayrollValue.FindMatchingPeriodValue: left-contains-right branch for retro payruns (Periodopen-ended vs.CalendarPeriodtrimmed end) - Client.Services —
WeekPayrollCycle: migrated from removedIPayrollCalendartoCultureInfo/Calendar
Tests
ConsolidatedEdge.Test(new) —NoRetroflag isolation inGetConsolidatedWageTypeResults:NoRetro=falsereturns the retro-corrected prior value;NoRetro=truereturns the original main-run valuePayrunTag.Test(new) —GetWageTypeResultstag-filter isolation: Alpha-tagged retro sub-run result queryable by tag; non-existent tag returns zeroMultiDivision.Test(new) — division-scoped case value isolation (valueScope: Division): same employee across two divisions, each payroll resolves its own salary independently
Examples
TemporalPayroll(new) — demonstrates the two independent time axes of case value resolution:periodStart(valueDate) andevaluationDate; 7 payrun jobs cover a 2×2 retro matrix and 3 forecast scenariosReportPayroll—CumulativeJournal: fixed monthly result columns typed as decimal
v0.10.0-beta.1 - Mar 2026
Highlights
- Payrun Job Preview — synchronous single-employee calculation without persisting results
- Async Payrun Job Queue — background processing with bounded channel and webhook notification
- Parallel Employee Processing — configurable parallelism with thread-safe state isolation
- Persist Parallelism — configurable concurrent DB writes (
MaxParallelPersist), load-tested default of2delivers 30% throughput gain - Bulk Employee Creation — high-throughput import via
SqlBulkCopy - Excel Regulation Import — full regulation import from Excel workbooks
- Load Testing Framework — generate, setup, execute, and benchmark payrun performance
- CI/CD Release Pipeline — single-click wave-based release with version guard and dry-run
- Docker & GitHub Packages — automated container builds and NuGet publishing
- Authentication & Security — configurable auth modes, CORS, rate limiting, script safety analysis
CI/CD & Infrastructure
- New orchestrated release pipeline with wave-based build ordering and single-click release via GitHub Actions
- Version guard prevents accidental overwrites of existing releases, packages, and tags
Directory.Build.propsauto-updated, committed, and tagged by the workflow- Dry-run mode for pipeline testing without side effects
- GitHub Packages as primary NuGet source for all
PayrollEngine.*packages - New
nuget.configwith package source mapping (PayrollEngine.*→ GitHub Packages,*→ NuGet.org) - Dedicated sync workflow for selective NuGet.org publishing
- Automated Linux container builds for Backend, PayrollConsole, and WebApp published to
ghcr.io/payroll-engine/* swagger.jsonauto-generated from Backend via Swashbuckle CLI and attached to releases- New
ci.ymlworkflow for build and test on pull requests and pushes tomain - Updated exchange schema (
PayrollEngine.Exchange.schema.json)
Backend
New Features
- Payrun job preview endpoint (
POST .../payruns/jobs/preview) - Synchronous single-employee payrun calculation without persisting results
- Returns
PayrollResultSetwith wage type, collector, and payrun results - Supports any
RetroPayMode; returns HTTP 422 if retro is triggered - Asynchronous payrun job processing with background queue
PayrunJobQueuewith bounded channel for backpressure (capacity: 100)PayrunJobWorkerServiceasBackgroundServicefor job dequeuing and processing- Job pre-created and persisted before enqueue, returns HTTP 202 with location header
- Webhook notification on job completion or abort
- Configurable parallel employee processing (
MaxParallelEmployees) - Values:
0/off(sequential, default),half,max,-1(automatic),1–N(explicit) - Per-employee
PayrunEmployeeScopefor mutable state isolation - Thread-safe progress reporting with batched DB persistence (every 10 employees)
- Configurable persist parallelism (
MaxParallelPersist, default:2) - Controls concurrent DB writes per payrun job (SemaphoreSlim count)
- Load-tested:
2is the optimal value;4+shows no measurable gain - Failed persists retried up to 3× with backoff; no data loss possible
- Employee processing timing logs (
LogEmployeeTiming) - Bulk employee creation endpoint (
POST .../employees/bulk) usingSqlBulkCopy - Retro payrun period limit (
MaxRetroPayrunPeriods, default: 0/unlimited) - CORS configuration (
Cors) with AllowedOrigins, AllowedMethods, AllowedHeaders, AllowCredentials, PreflightMaxAgeSeconds - Rate limiting (
RateLimiting) with global policy and dedicated payrun job start policy - Configurable authentication (
Authentication) with modes:None,ApiKey,OAuth - OAuth with Authority, Audience, RequireHttpsMetadata, ClientSecret
- Startup validation for OAuth authority and audience
- Explicit Swagger toggle (
EnableSwagger, default: false) - Per-category audit trail configuration (
AuditTrail) replacing singleAuditTrailDisabledbool - Script safety analysis (
ScriptSafetyAnalysis, default: false) for banned API usage detection - Configurable database collation check (
DbCollation, default: SQL_Latin1_General_CP1_CS_AS) - New
PayrollServerConfigurationfor centralized server settings ConsolidatedPayrunResultQueryfor consolidated payrun result queries- Updated database scripts for schema version 0.9.6
Breaking Change
- Refactored
PayrunJobInvocationfrom id-based to name/identifier-based references - Removed
PayrunIdandUserIdproperties from API and domain models PayrunNameandUserIdentifierare now the required fields
Bug Fixes
- Fixed inverted slot filter logic in
GetCaseValuesAsync - Fixed
NullReferenceExceptionin timeless case value path - Fixed sort lookup values by
RangeValueinBuildRangeBrackets - Fixed calculator cache key to include culture
- Fixed deterministic culture fallback in
CalculateEmployeeAsynctoen-US - Fixed
CodeFactory.CodeFilesrace condition withConcurrentDictionary - Fixed thread-safe timer initialization in
AssemblyCache - Fixed sync-over-async bridge in scripting layer
- Added production
UseExceptionHandlermiddleware for structured JSON error responses
Console
- New
PayrunEmployeePreviewTestcommand for testing payrun job preview results - New
PayrollMergecommand — merges multiple payroll files (JSON or YAML) into a single file - New load test commands:
LoadTestGenerate,LoadTestSetup,LoadTestSetupCases,PayrunLoadTest - New
.pecmdfile type registration scripts included in the release package Register-PecmdExtension.ps1— Windows (user-level, no admin required)register-pecmd.sh— Linux (MIME + desktop integration) and macOS (shell wrapper)- Fixed case relation validate script publisher comparing build expression instead of validate expression
- Fixed collector custom result culture validation
Web App
- Fixed SSL certificate validation bypass with config-controlled
AllowInsecureSslsetting - Fixed
HttpClientsingleton disposal inBackendServiceBase - Fixed
NullReferenceExceptioninSetupUserTasks - Fixed
TaskServiceinjection inUserSessionfrom[Inject]attribute to constructor injection - Enabled
UseHstsin production pipeline
Libraries
- Client Services — fixed inverted condition in
ReportParameterParser, fixedGetContinuePeriodsloop termination, fixedWeekPayrollCycle.GetPayrollPeriodweek offset - Client Test — new
PayrunEmployeePreviewTestRunner, fixed null reference and collector custom result issues - Client Scripting — fixed
JsonElementnull handling, deep copy inCaseValue,Date.Tomorrow/Yesterdayas computed properties, off-by-one fixes, updatedIPayrunRuntime; addedRetroSumwage type accessor (^$WageType.RetroSum) andGetRetroWageTypeValueSum(number/name)scripting API - Client Core — new
NamespaceUpdateTool,AddCasesBulkAsync, async payrun job support, fixed inverted validation and duplicate detection,HttpClientownership pattern - Core — new
PayrunPreviewRetroException, replaced SHA1 with SHA256, regex timeout for ReDoS prevention, stream and DataTable fixes
v0.9.0-beta17 - Feb 18, 2026
- Backend
- Added OAuth support, configurable in
appsettings.json. -
Assembly cache: added tenant isolation
- All import, export, and test commands now support for
YAML. - New command
PayrollConvert.- Converts payroll files between
JSONandYAML. - Support for file masks and recursive conversions.
- Converts payroll files between
-
Wiki: updated examples to
YAML. -
Client Services
- New
YamlReaderandYamlWriterto read and writeYAMLfiles. - Support for JSON schema embedding in YAML files.
v0.9.0-beta16 - Feb 11, 2026
- Lookup Range Brackets
- New objects lookup range result containing a list of lookup range brackets.
- Each bracket is defined by a numeric range from
RangeStarttoRangeEndincluding the lookup key and value. - The
RangeValuefield in each bracket contains the distributed value for progressive lookups, as well as the amount used from the matching bracket. -
For an example check the Lookup test.
-
Scripting API
- Payroll function: added acces to the lookup range bracktes.
- Payroll function: added access the threshold lookup bracket using a range value.
-
Payroll function: added access to progressive lookup bracktes using a range value.
- Payroll controller: new endpoint to get the payroll lookup ranges.
- Action parser: alternative text added for the logical operators
&&(AND) and operator||(OR). - Regulation audit trail Breaking Change
- The regulation audit trail is now disabled by default.
- Enable the audit trail configuration in
appsettings.json: Script: enable or disbable auditing of scripts.Lookup: enable or disbable auditing of lookups and lookup values.Input: enable or disbable auditing of cases, case fields and case relations.Payrun: enable or disbable auditing of collectors and wage types.Report: enable or disbable auditing of reports, report templates and report parameters.
v0.9.0-beta15 - Feb 5, 2026
- No-Code Actions
- Actions
Min,Max,Range,Contains: support for time range. - New action
Within: test if a value is within a range. - New action
GetTimeSpan: duration between two dates. - New action
YearDiff: calculate years between two dates. - New action
Age: calculate age. - New actions
SameYear,SameMonth,SameDay: test for equal dates. - Action value: added timespan/year/month/day properties.
-
Action value: added methods to add and subtract year/month/day/timespan.
-
Scripting API
-
Payroll function: added properties year/month/day for cycle/period start and end date.
-
Improved bulk data import performance for lookups.
- Regulation page action grid: use italic font style for comments.
v0.9.0-beta14 - Jan 14, 2026
- New feature Async payrun job processing Payroll-Engine/PayrollEngine.Backend#6
- Implement asynchronous payrun job processing using Channel
and BackgroundService. - Return HTTP 202 Accepted immediately with Location header for status polling.
- Prevent HTTP 524 timeout errors when processing large payrolls (500+ employees).
- Backend Breaking Changes:
- POST
/api/tenants/{id}/payruns/jobsnow returns HTTP202 Acceptedinstead of HTTP201 Created. - Response includes Location header for status polling.
- Clients must poll status endpoint to determine job completion.
- Implement asynchronous payrun job processing using Channel
- Test library: added support for async payrun jobs.
- Web App payrun jobs page: added support for async payrun jobs.
See Release Archive for earlier releases.