Skip to content

Releases: Payroll-Engine/PayrollEngine

PayrollEngine v1.0.0

21 Apr 09:33

Choose a tag to compare

Payroll Engine — Release Notes

v1.0.0 - Apr 2026

Highlights

  • Wage type cachesWageTypeCycleCache and WageTypeConsolidatedCycleCache bulk-load cycle and consolidated wage-type results once per employee when wage types are tagged via the corresponding payroll cluster sets, reducing database round-trips during payrun scripts
  • PasswordAvailable — user API and client models expose whether a password is set without transferring the hash
  • Exchange import — payrun jobs that end with Abort/Cancel and CompletedJobStatus=Abort are treated as an expected test outcome during import, not as a hard import 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. The nine Payroll columns ClusterSetCase, ClusterSetCaseField, ClusterSetCollector, ClusterSetCollectorRetro, ClusterSetWageType, ClusterSetWageTypeRetro, ClusterSetCaseValue, ClusterSetWageTypePeriod, and ClusterSetWageTypeLookup are replaced by a single ClusterSet JSON column; existing data is migrated in the scripts. The persistence layer enforces minimum schema version 1.0.0 — the backend will not start against a pre-1.0.0 database.

New Features

  • WageTypeCycleCache — for wage types tagged via Payroll.ClusterSet.ClusterSetWageTypeCycle, GetWageTypeResults data for the cycle/YTD path is loaded in bulk once per employee at payrun employee start; the cache is reset and reloaded before retro re-evaluation
  • WageTypeConsolidatedCycleCache — for wage types tagged for the consolidated cache, GetConsolidatedWageTypeResults is bulk-loaded once per employee; calls with noRetro=true bypass the cache by design
  • PasswordAvailable in the user API response — derived from the stored hash in memory; the password hash remains [JsonIgnore] on the model

Bug Fixes

  • ClusterSet persistence — pre-serialize ClusterSet as PascalCase JSON before write to avoid sql_variant conversion issues; register JsonObjectTypeHandler<PayrollClusterSets> for correct Dapper deserialization on read
  • Payrun jobsCompletedJobStatus=Abort is no longer applied to successfully completed jobs; abort remains reserved for processor failures and expected-abort test scenarios
  • PayrunProcessorSettings — XML documentation for MaxParallelPersist default corrected (validated by load tests)

Breaking Change

  • Database schema 1.0.0Payroll cluster-set columns consolidated into one ClusterSet JSON column; breaking change (see Database Update above)

Libraries

  • Client.CoreIPayroll / Payroll: individual ClusterSet* string properties replaced by a single ClusterSet property of type PayrollClusterSets breaking change; PasswordAvailable on IUser / User; ExchangeImport honors intentional abort status for test expectations; project references use $(Version) for PE dependencies; release workflow no longer patches versions with sed
  • Client.Scripting — fixed double-encoding of strings in PayrunFunction; GitHub Actions pages.yml patches PE dependency versions before build

Breaking Change

  • JSON schema (PayrollEngine.Exchange.schema.json) — the former top-level Payroll properties clusterSetCase, clusterSetCaseField, clusterSetCollector, clusterSetCollectorRetro, clusterSetWageType, clusterSetWageTypeRetro, clusterSetCaseValue, and clusterSetWageTypePeriod are removed; the same references must appear under clusterSet (PayrollClusterSets). Existing payroll JSON files used for import/export must be migrated — breaking change

📦 NuGet Packages (v1.0.0)

Package GitHub Packages NuGet.org
PayrollEngine.Core 1.0.0 1.0.0
PayrollEngine.Serilog 1.0.0 1.0.0
PayrollEngine.Document 1.0.0 1.0.0
PayrollEngine.Client.Core 1.0.0 1.0.0
PayrollEngine.Client.Scripting 1.0.0 1.0.0
PayrollEngine.Client.Test 1.0.0 1.0.0
PayrollEngine.Client.Services 1.0.0 1.0.0
PayrollEngine.Mcp.Core 1.0.0 1.0.0
PayrollEngine.Mcp.Tools 1.0.0 1.0.0

🐳 Docker Images (Linux)

App Version Pull Command
PayrollEngine.Backend 1.0.0 docker pull ghcr.io/payroll-engine/payrollengine.backend:1.0.0
PayrollEngine.PayrollConsole 1.0.0 docker pull ghcr.io/payroll-engine/payrollengine.payrollconsole:1.0.0
PayrollEngine.WebApp 1.0.0 docker pull ghcr.io/payroll-engine/payrollengine.webapp:1.0.0
PayrollEngine.Mcp.Server 1.0.0 docker pull ghcr.io/payroll-engine/payrollengine.mcp.server:1.0.0

PayrollEngine v0.10.0-beta.4

01 Apr 11:30

Choose a tag to compare

Pre-release

Bug Fixes

Features

  • Backend

    • Payrun.RetroTimeType (enum) replaced by Payrun.RetroBackCycles (int): -1 = unlimited (default), 0 = current cycle only, n = n previous cycles breaking change
    • PayrollResult denormalized with business-key string fields: PayrunName, PayrunJobName, EmployeeIdentifier, PayrollName, DivisionName — enables archive restore idempotency and self-describing results (consistent with existing CycleName/PeriodName pattern)
    • New POST /payruns/jobs/import endpoint — imports PayrunJobSet[] (payrun job + result sets) into a tenant; Phase 1a resolves all references (Payrun, Division, User, Employee) by business-key names (422 on failure); Phase 1b checks for duplicate payrun job names (409 on conflict); Phase 2 inserts in a TransactionScope — payrun job first, then result sets with new job ID; full rollback on failure (use cases: archive restore, tenant migration, system migration, staging seeding)
    • OData any() lambda operator — filters on JSON collection columns (List<string>, List<int>, etc.) using correlated EXISTS sub-queries; supports scalar arrays and key/value object arrays
    • OData in operator — value-set filter (field in (v1, v2, ...)) mapped to SQL WHERE col IN (...)
    • Both operators are backend-aware: SQL Server uses OPENJSON, MySQL uses JSON_TABLE
    • MySQL support: IDbContext.BuildCollectionFromRaw abstracts the OPENJSON / JSON_TABLE difference
    • TenantIsolationLevel server-wide policy — new TenantIsolationFilter enforces cross-tenant HTTP access control on every request: None (transparent), Consolidation (report scripts only), Read (GET + ReadSemantic POST cross-tenant), Write (full cross-tenant, Auth-Tenant header forbidden). Configured in appsettings.json. See Security
    • RegulationShare.IsolationLevel — new field controlling access granted to the consumer tenant: Consolidation (cross-tenant result access for report scripts, regulation not added as payroll layer) or Write (full payroll layer, default)
    • Report.ReportIsolation — new field on Report; exposed via GetDerivedReports to allow per-report access control aligned with TenantIsolationLevel
    • 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.
  • MCP Server

    • Division isolation: list_employees now pushes the division filter to the backend via divisions/any(d: d eq 'DivisionName') — eliminates client-side post-filtering
  • Mcp.Core (new)

    • Core infrastructure for building Payroll Engine MCP servers: isolation model (MultiTenant, Tenant, Division, Employee), role-based permission system (HR, Payroll, Report, System), ToolBase abstract base class with typed service factories, isolation-aware query helpers and resolver methods, ToolRegistrar for startup-time tool filtering by role and isolation level compatibility
  • Mcp.Tools (new)

    • Complete set of read-only MCP tools built on Mcp.Core: 27 tools across HR, Payroll, Report and System roles; all tools are read-only by design (get_employee_pay_preview and execute_payroll_report execute calculations without persisting results)
  • Core

    • RetroTimeType enum removed — replaced by Payrun.RetroBackCycles (int) breaking change
  • Client.Scripting

    • WageType and Collector temporal selectors in action syntax — new scope properties on ^$WageType and ^$Collector tokens: .PrevPeriod, .NextPeriod, .Cycle, .PrevCycle, .NextCycle; additionally .RetroSum for WageTypes (sum of retro corrections within the current cycle)
    • New Calculation action group — 15 standard payroll calculation actions on PayrunFunction: AnnualProjection, CycleToPeriod, PeriodToCycle, RoundToFraction, CappedContribution, RateContribution, LookupRateContribution, PhaseOut, LinearPhaseOut, PhaseIn, ProRateByDays, InsuranceWage, D2Delta, MinMaxContribution, ContributionIfObligated
    • New GetConsolidatedWageTypeValue and GetConsolidatedCollectorValue actions — period-offset based consolidation (e.g. -11 for a 12-period rolling window)
  • Console

    • New PayrunEmployeePreviewTest command — executes an employee payrun preview (no persistence) and tests the results
    • New InstallRegulationPackage command — installs a regulation NuGet package (.nupkg) directly into a PE backend tenant. Supports local file paths, wildcards, and HTTP(S) URLs (e.g. GitHub Release assets). Features: version check, cross-tenant dependency check, ordered manifest-driven import, dry-run mode, and automatic temp cleanup.
    • HttpGet: optional second parameter writes response body to a file
    • HttpPost / HttpPut: Content-Type set to application/json (was text/plain → HTTP 415)
    • URL placeholder resolution in HTTP commands: {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 for POST /payruns/jobs/import

📦 NuGet Packages (v0.10.0-beta.4)

Package GitHub Packages NuGet.org
PayrollEngine.Core 0.10.0-beta.4 pending sync
PayrollEngine.Serilog 0.10.0-beta.4 pending sync
PayrollEngine.Document 0.10.0-beta.4 pending sync
PayrollEngine.Client.Core 0.10.0-beta.4 pending sync
PayrollEngine.Client.Scripting 0.10.0-beta.4 pending sync
PayrollEngine.Client.Test 0.10.0-beta.4 pending sync
PayrollEngine.Client.Services 0.10.0-beta.4 pending sync
PayrollEngine.Mcp.Core 0.10.0-beta.4 pending sync
PayrollEngine.Mcp.Tools 0.10.0-beta.4 pending sync

🐳 Docker Images (Linux)

App Version Pull Command
PayrollEngine.Backend 0.10.0-beta.4 (pre-release) docker pull ghcr.io/payroll-engine/payrollengine.backend:0.10.0-beta.4
PayrollEngine.PayrollConsole 0.10.0-beta.4 (pre-release) docker pull ghcr.io/payroll-engine/payrollengine.payrollconsole:0.10.0-beta.4
PayrollEngine.WebApp 0.10.0-beta.4 (pre-release) docker pull ghcr.io/payroll-engine/payrollengine.webapp:0.10.0-beta.4
PayrollEngine.Mcp.Server 0.10.0-beta.4 (pre-release) docker pull ghcr.io/payroll-engine/payrollengine.mcp.server:0.10.0-beta.4

PayrollEngine v0.10.0-beta.3

19 Mar 13:13

Choose a tag to compare

Pre-release

Bug Fixes

  • Client.Scripting

    • CasePayrollValue: fixed FindMatchingPeriodValue — added left-contains-right containment branch for retro payruns where a Period field (open-ended, End=MaxValue) appears on the left side of a binary operator and a CalendarPeriod field (trimmed end) on the right; previously the match returned null silently, causing all operators (+, -, *, /, %) to return Empty and the payrun to fail with Missing results
  • Backend

    • Fixed concurrent assembly load collision in AssemblyCache — replaced lock-free double-entry with a proper lock to prevent race conditions during parallel payrun execution
    • Fixed CaseValueRepositoryBase.GetPeriodCaseValuesAsync period filter: changed < to <= for Start boundary, ensuring period-edge case values are included correctly
  • Web App

    • Fixed report template encoding: changed ASCII to UTF-8 for XSL, XSD and FRX streams
    • Fixed payrun job workflow: Draft panel now displayed correctly after job start and on page reload
  • Client.Services

    • WeekPayrollCycle: migrated from removed IPayrollCalendar to CultureInfo/Calendar — aligns with WeekPayrollPeriod, MonthPayrollPeriod, and YearPayrollCycle
  • Examples

    • CumulativeJournal: fixed monthly result columns typed as decimal

Features

  • Backend

    • MySQL 8.4 LTS support via new Persistence.MySql provider (preview) — activate with PayrollServerConfiguration__DbProvider=MySql
    • MaxParallelEmployees default changed from sequential to auto (ProcessorCount) breaking change — use off or -1 to restore sequential behavior
      • values: 0/empty = auto, off/-1 = sequential, half = ProcessorCount/2, max = ProcessorCount, 1N = explicit
    • GET /api/admin/information — new endpoint returning backend server diagnostics
      • Assembly: version, build date
      • API: version, name
      • Authentication: mode (None / ApiKey / OAuth); OAuth authority and audience (no secrets exposed)
      • Database: type, catalog name, server version, edition
      • Runtime: MaxParallelEmployees (resolved integer), MaxRetroPayrunPeriods, command/transaction/cache/webhook timeouts, ScriptSafetyAnalysis, audit trail flags, CORS origins, rate limiting policies
    • IDbContext extended with GetDatabaseInformationAsync() returning DatabaseInformation (type, name, catalog, version, edition)
    • ReportIsolation — new domain model and audit: report execution can be scoped to None, Global, Company, Division, or Employee
  • 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
    • 29 tools in 4 roles:
      • System — tenant and user queries (list_tenants, get_tenant, get_tenant_attribute, list_users, get_user, get_user_attribute)
      • HR — employee master data, case values, and audit trail (list_divisions, get_division, get_division_attribute, list_employees, get_employee, get_employee_attribute, list_employee_case_values, list_company_case_values, list_employee_case_changes, list_company_case_changes)
      • Regulation — regulation definitions (list_regulations, get_regulation, list_wage_types, list_lookups, list_lookup_values)
      • Payroll — payroll execution and results (list_payrolls, get_payroll, list_payruns, list_payrun_jobs, list_payroll_wage_types, list_payroll_result_values, get_consolidated_payroll_result, get_case_time_values)
    • Enrichment: employee context (identifier, firstName, lastName) injected into all employee-scoped results; division name lookup in list_payrun_jobs; list_payroll_result_values fully denormalized
    • get_case_time_values supports three temporal perspectives: Historical, Current knowledge, Forecast
    • Access control: role-based permissions (McpRole / McpPermission) and isolation levels (MultiTenant, Tenant) configurable per deployment via appsettings.json or environment variables
    • Docker image available; claude_desktop_config.json example included
  • Core

    • New PayrunPreviewRetroException, replaced SHA1 with SHA256, regex timeout for ReDoS prevention, stream and DataTable fixes
    • IDocumentService with GenerateAsync, MergeAsync and ExcelMergeAsync
    • Apply property added to Query; ApplyOperation added to QuerySpecification
    • New ReportIsolation enum (None, Global, Company, Division, Employee)
  • Client.Core

    • AdminService — new service (IAdminService) with GetBackendInformationAsync() calling GET /api/admin/information
    • BackendInformation model hierarchy: BackendAuthInformation, BackendDatabaseInformation (incl. Edition), BackendRuntimeInformation, BackendAuditTrailInformation, BackendCorsInformation, BackendRateLimitingInformation
    • ApiEndpoints.AdminInformationUrl() — new endpoint constant
    • IAttributeService added to IDivisionService, ITaskService, IRegulationService, IReportService — consistent attribute URL endpoints and service implementations across all object types
    • ReportIsolation added to IReport interface and Report model — synchronized with API model
  • Document

    • IDocumentService.GenerateAsync — generates a schema document (.frx skeleton) from a DataSet or rebuilds the Dictionary section of an existing template (CI mode), preserving all design elements
  • Client.Test

    • New PayrunEmployeePreviewTestRunner for preview-based payrun testing without persisting results
    • PayrunTestRunner refactored: ImportAsync and TestAsync are now separate phases, enabling independent re-test without re-import
  • Console

    • ReportBuild — executes a report and generates a schema document for template design; format-agnostic, output extension derived from TemplateFile
      • without TemplateFile: generates new skeleton from DataSet
      • with TemplateFile (CI mode): updates schema section, preserving layout
    • PayrunLoadTest: optional Excel report alongside CSV
      • /ExcelReport — write .xlsx with derived filename
      • /ExcelFile=<path> — explicit Excel output path
      • /ParallelSetting=<v> — documents backend MaxParallelEmployees in the Excel setup sheet
      • Excel contains three sheets: Setup (machine, OS, ProcessorCount, MaxParallelEmployees), Results (formatted CSV), Avg ms/Employee (pivot with outlier highlighting)
    • PayrunLoadTest: optional Markdown report alongside CSV
      • /MarkdownReport — write .md with derived filename
      • /MarkdownFile=<path> — explicit Markdown output path
      • Report sections: Test Summary (median timing, per-run breakdown table, ms/Employee and Employees/h columns) and Test Infrastructure
        • Computer: machine name, OS, framework, CPU model (Windows Registry), CPU cores, RAM total + available (Windows: GlobalMemoryStatusEx), disk total + free
        • Console: version, build date
        • Backend: version, build date, API version, auth mode, max parallel employees, timeouts, script safety analysis, database (type/name/version/edition), audit trail flags, CORS origins, rate limiting policies — sourced from GET /api/admin/information
  • Tests

    • ConsolidatedEdge.Test (new)NoRetro flag isolation in GetConsolidatedWageTypeResults: NoRetro=false returns the retro-corrected prior value; NoRetro=true returns the original main-run value
    • PayrunTag.Test (new)GetWageTypeResults tag-filter isolation: Alpha-tagged retro sub-run result queryable by tag; non-existent tag returns zero
    • MultiDivision.Test (new) — division-scoped case value isolation (valueScope: Division): same employee across two divisions, each payroll resolves its own salary independently
  • Examples

    • TemporalPayroll — new example demonstrating the two independent time axes of case value resolution
      • periodStart (valueDate): which value was active on a given date
      • evaluationDate: which entries were known on a given date
      • 7 payrun jobs cover a 2×2 retro matrix (past/today × past/today) and 3 forecast scenarios including a forecast entry with validity window expiry
      • minimal regulation (one case field, one wage type, one No-Code action) — all complexity lives in the payrun invocations
    • ReportPayroll — new Payslip report: single-employee payslip with current-month value, retro column, and YTD accumulation
      • parameters: PayslipYear, PayslipMonth (zero-padded, e.g. 03), EmployeeIdentifier (optional employee filter)
      • ReportEndFunction accumulates months 1..N via GetConsolidatedWageTypeResults; builds Value, YtdValue, RetroValue columns
      • columns: Name (WageTypeName - WageTypeNumber) · Amount · Retro · YTD
      • A4 portrait template with full-width employee card header; negative values in red, retro ad...
Read more

PayrollEngine v0.10.0-beta.1

09 Mar 18:13

Choose a tag to compare

Pre-release

Features

  • General

    • Internal tooling and infrastructure improvements
    • Updated exchange schema (PayrollEngine.Exchange.schema.json)
  • Website

    • New documentation website at payrollengine.org, replacing the GitHub Wiki
    • Role-based structure: Provider (REST API), Regulator (No-Code/Low-Code), Automator (Client Services)
    • White Paper content integrated into the documentation; standalone PDF removed
  • Examples

    • New self-contained payroll examples — each includes regulation, case data, payrun jobs, and a test file
    • Tutorial: StartPayroll — incremental three-layer regulation build (JSON + YAML variants)
    • Business Scenarios
      • GlobalPayroll — age supplement, one-time bonus, progressive tax
      • MultiCountryPayroll — DE/FR/NL with shared base regulation and split employee
      • MinWagePayroll — automatic top-up via year-versioned lookup, fully No-Code
      • PartTimePayroll — overtime guard and retroactive level correction, fully No-Code
      • ForecastPayroll — parallel what-if scenarios without regulation change, fully No-Code
      • MarchClausePayroll — German Märzklausel Q1 bonus routing via Low-Code extension methods
    • Retro Corrections: RetroPayroll — positive deltas, late Moment entry, cascading correction
    • Data Import: TaxTablePayroll — ~7 100 records bulk import with range-based withholding tax
  • Tests

    • New PayrunEmployeePreview.Test — payrun job preview without persisting results
    • New WageTracingPayroll.Test — wage calculation traceability via clusterSetWageTypePeriod
    • New RetroPayMode.TestretroPayMode None vs. ValueChange: verifies that None suppresses retro sub-runs even when prior-period mutations are detected, while ValueChange triggers them
    • New Collector.Test — collector features: multi-source accumulation, maxResult cap (3 jobs), minResult floor, negated sign inversion
    • New PayrunEdge.Test — payrun date boundary and temporal edge cases: period boundaries, retro trigger via created/evaluationDate alignment, Period touching, CalendarPeriod overlap, mid-period split, evalDate==PeriodStart/PeriodEnd/CycleEnd, forecast
  • CI/CD Pipeline

    • New orchestrated release pipeline with wave-based build ordering
    • Single-click release for all libraries and applications via GitHub Actions
    • Version guard prevents accidental overwrites of existing releases, packages, and tags
    • Directory.Build.props is auto-updated, committed, and tagged by the workflow
    • Dry-run mode for pipeline testing without side effects
    • RELEASE_NOTES.md as single source for release text (umbrella release + wiki)
    • New ci.yml workflow for build and test on pull requests and pushes to main
    • New devops/scripts with release preparation tooling:
      • Update-BreakingChanges.ps1 — automated breaking change detection across REST API, Backend, Scripting, and Client Services surfaces
      • Release-Changelog.ps1 — cross-repo changelog collection with conventional commit parsing
      • Update-CommitMessage.ps1 — pre-fills Git commit message from RELEASE_NOTES.md for Visual Studio
    • New devops/scripts with database schema tooling:
      • Export-DbScript.ps1 — exports the live SQL Server schema to a .sql file (Create or Delete mode) via PayrollDatabaseConnection
      • Format-DbScript.ps1 — normalises GO delimiters and topologically sorts DDL objects to eliminate forward-reference warnings
      • Compare-DbScript.ps1 — diffs two formatted .sql files and generates an incremental update script (Added / Removed / Modified)
      • Generate-DbUpdate.ps1 — orchestrates Format + Compare in one step to generate an update script from any two SQL files
      • Compose-DbScript.ps1 — injects version-check and version-set blocks into Create and Update scripts from a JSON config
  • NuGet Packages

    • GitHub Packages as primary NuGet source for all PayrollEngine.* packages
    • New nuget.config with package source mapping (PayrollEngine.* → GitHub Packages, * → NuGet.org)
    • Dedicated sync workflow for selective NuGet.org publishing
  • Docker

    • Automated Linux container builds for Backend, PayrollConsole, and WebApp
    • Images published to ghcr.io/payroll-engine/*
    • Pre-release images skip the :latest tag
  • Backend

    • Payrun job preview endpoint (POST .../payruns/jobs/preview)
      • synchronous single-employee payrun calculation without persisting results
      • returns PayrollResultSet with wage type, collector, and payrun results
      • preview accepts any RetroPayMode to match production behavior; returns HTTP 422 if retro is triggered
      • new PayrunPreviewRetroException with employee identifier and retro date context
      • runs in-memory only — no payrun job or result records written to the database
    • Refactored PayrunJobInvocation from id-based to name/identifier-based references breaking change
      • removed PayrunId and UserId properties from API and domain models
      • PayrunName and UserIdentifier are now the required fields
      • payrun and user resolution by name/identifier in PayrunProcessor and controller
      • retro job invocations use Payrun.Name and User.Identifier instead of ids
    • Asynchronous payrun job processing with background queue
      • PayrunJobQueue with bounded channel for backpressure (capacity: 100)
      • PayrunJobWorkerService as BackgroundService for job dequeuing and processing
      • job pre-created and persisted before enqueue, returns HTTP 202 with location header
      • infrastructure abort on unhandled exceptions or service shutdown
      • webhook notification on job completion or abort
    • Configurable parallel employee processing (MaxParallelEmployees)
      • values: 0/off (sequential, default), half, max, -1 (automatic), 1N (explicit)
      • per-employee PayrunEmployeeScope for mutable state isolation in parallel mode
      • thread-safe progress reporting with batched DB persistence (every 10 employees)
      • payroll calculator cache with Lazy<T> and composite key (calendar+culture) for thread-safe reuse
    • Employee processing timing logs (LogEmployeeTiming)
      • per-employee duration and summary (mode, total, average) logged at Information level
    • Bulk employee creation endpoint (POST .../employees/bulk)
      • accepts Employee[], uses SqlBulkCopy for high-throughput insert (5'000 item chunks)
      • generic CreateBulkAsync in RepositoryChildObjectController for reuse across entity types
      • returns created item count (no individual IDs); duplicate identifiers caught by DB unique constraint
    • Retro payrun period limit (MaxRetroPayrunPeriods, default: 0/unlimited)
      • safety guard to prevent runaway retro calculations with RetroTimeType.Anytime
    • CORS configuration (Cors)
      • configurable AllowedOrigins, AllowedMethods, AllowedHeaders, AllowCredentials, PreflightMaxAgeSeconds
      • inactive by default (no cross-origin requests allowed)
    • Rate limiting (RateLimiting)
      • global policy for all endpoints and dedicated policy for payrun job start endpoint
      • configurable PermitLimit and WindowSeconds per policy
    • Configurable authentication (Authentication)
      • supports three modes: None, ApiKey, OAuth
      • OAuth with Authority, Audience, RequireHttpsMetadata, ClientSecret
      • startup validation for OAuth authority and audience to prevent token confusion
      • environment variable fallback for API key
    • Explicit Swagger toggle (EnableSwagger, default: false)
    • Per-category audit trail configuration (AuditTrail)
      • replaced single AuditTrailDisabled bool with granular flags: Script, Lookup, Input, Payrun, Report
    • Script safety analysis (ScriptSafetyAnalysis, default: false)
      • static analysis of user scripts for banned API usage (System.IO, System.Net, System.Diagnostics, System.Reflection)
      • opt-in via appsettings due to compilation overhead
    • Configurable database collation check (DbCollation, default: SQL_Latin1_General_CP1_CS_AS)
      • verified on startup in TestVersionAsync before the schema version check
      • prevents silent data integrity issues from mismatched collation
    • Added ConsolidatedPayrunResultQuery for consolidated payrun result queries
    • Updated database scripts (ModelCreate, ModelDrop, ModelUpdate) for schema version 0.9.6
    • Added database script history — previous schema versions archived under Database/History/v{version}
    • Added production UseExceptionHandler middleware for structured JSON error responses
  • Console

    • New PayrunEmployeePreviewTest command for testing payrun job preview results
    • New PayrollMerge command — merges multiple payroll files (JSON or YAML) into a single file
      • supports file masks (e.g. *.yaml, *.json)
      • toggle /top (default) or /recursive for directory scope
    • Built-in load test commands for payrun performance testing
      • LoadTestGenerate generates scaled exchange files from any regulation template
      • LoadTestSetup bulk-imports employees via CreateEmployeesBulkAsync
      • LoadTestSetupCases bulk-imports case changes via AddCasesBulkAsync (replaces slow PayrollImport for load test setup)
      • PayrunLoadTest executes payrun with warmup, measured repetitions, and CSV report (client + server timing)
    • New .pecmd file 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)
  • Web App

    • Updated MudBlazor to v9.1.0
    • Fixed SSL certificate validation bypass with config-controlled AllowInsecureSsl setting
    • Fixed HttpClient singl...
Read more

v0.9.0-beta.17

18 Feb 17:47

Choose a tag to compare

v0.9.0-beta.17 Pre-release
Pre-release
  • Backend

    • Added OAuth support, configurable in appsettings.json.
    • Assembly cache: added tenant isolation
  • Console

    • All import, export, and test commands now support for YAML.
    • New command PayrollConvert.
      • Converts payroll files between JSON and YAML.
      • Support for file masks and recursive conversions.
    • Wiki: updated examples to YAML.
  • Client Services

    • New YamlReader and YamlWriter to read and write YAML files.
    • Support for JSON schema embedding in YAML files.

v0.9.0-beta.16

11 Feb 15:30

Choose a tag to compare

v0.9.0-beta.16 Pre-release
Pre-release
  • Lookup Range Brackets

    • New objects lookup range result containing a list of lookup range brackets.
    • Each bracket is defined by a numeric range from RangeStart to RangeEnd including the lookup key and value.
    • The RangeValue field 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.
  • Backend

    • 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-beta.15

05 Feb 12:59

Choose a tag to compare

v0.9.0-beta.15 Pre-release
Pre-release
  • 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.
  • Backend

    • Improved bulk data import performance for lookups.
  • Web App

    • Regulation page action grid: use italic font style for comments.

v0.9.0-beta.14

14 Jan 07:59

Choose a tag to compare

v0.9.0-beta.14 Pre-release
Pre-release
  • 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/jobs now returns HTTP 202 Accepted instead of HTTP 201 Created.
      - Response includes Location header for status polling.
      - Clients must poll status endpoint to determine job completion.
    • Test library: added support for async payrun jobs.
    • Web App payrun jobs page: added support for async payrun jobs.

v0.9.0-beta.13

07 Jan 21:20

Choose a tag to compare

v0.9.0-beta.13 Pre-release
Pre-release
  • General

    • Updated to .NET 10 and C-Sharp 14
    • Updated third-party NuGets
  • No-Code Actions

  • Scripting API

    • Function: new method to get calendar day count
    • Payroll function: added support for the regulation namespace
    • Payrun function
      • Added get/set payrun result
      • Added get wage type name/number by number/name
  • Backend

    • Updated to OpenApi version 3.1
    • Collector and wage type: added actions
    • Case field: removed actions
    • Regulation: added namespace
    • Tenant controller: added an endpoint to retrieve system action properties
    • New application setting for HTTPS redirection
    • New db stored procedure to delete a lookup
    • Updated database to version 0.9.5
      • New installation script Database\ModelCreate.sql
      • Update from version 0.9.4 script Database\ModelUpdate.sql
  • Console

    • New command lookup text import
    • Payroll import command: refactored file mask handling
    • Payrun employee test: added result count to the statistics
  • Web App

    • Regulation item editor: added undo support and save confirmation
    • Regulation page: added action support for collector and wage type
    • Payrun job page: added virtualization for list selections
    • Regulation obejct: added namespace
    • Refactored action editor

v0.9.0-beta.12

05 Nov 07:07

Choose a tag to compare

v0.9.0-beta.12 Pre-release
Pre-release
  • Common
    • Lookup: calculation of wage data (e.g. tax rates) using various methods.
      • Threshold - scaling a value based on a threshold lookup range value.
      • Progressive - value distribution based on lookup value ranges.
  • Scripting API
    • PayrollFunction: new method ApplyRangeValue to calculate lookup range values.
  • Backend
    • C# compiler: enhanced error message with source file info (first comment).
    • Updated database version to 0.9.4.
  • Console
    • Payroll import: added support for source file mask.