Operational and technical updates to the HR Cluster platform.
Types of changes
AddedNew functionality or modules.
UpdatedImprovements or changes to existing functionality.
CoreMajor architectural, platform-wide, or operational changes.
DeprecatedFeatures scheduled for removal.
RemovedFeatures or functionality removed.
FixedBug fixes and issue resolution.
SecuritySecurity improvements or vulnerability fixes.
2026
UpdatedUI
Smaller polish
Documents review modal preview is capped so body, thumbs, metadata, and class list wrap into a single scroll region; the doc column drops the redundant "Verified: date (name)" line; delete-proof placement tightened; per-file × removal added on bundle thumbs in the public competence form.
UpdatedGroupsMessaging
Groups • recipient language resolved from contact for emails and PDFs
When a group has a designated contact, outbound emails and the PDFs they carry now render in that contact's preferred language instead of the manager's session language.
UpdatedLocations
Locations • crew list actions inline on the table
Crew list actions are now exposed directly on the locations table, with sub-row buttons aligned on a single line so narrow viewports don't drop them onto a second row.
UpdatedClockworkUI
Clockwork • faster clock-in flow with progress feedback and pre-warmed GPS
GPS is now pre-warmed when the form opens and times out faster, narrowing the gap between submit and server response. A loading-progress toast bridges the submit-to-modal handoff so the screen never looks frozen, and the verify→handout continuation persists across reload via sessionStorage. Post-action URL cleanup is now consistent across every clock-in/out entry point, and the "Clocking out…" toast clears immediately when there is no follow-up return flow.
AddedInfrastructureUI
Analytics • consent-gated GA4 with sanitised paths
Google Analytics now loads only after the visitor accepts cookie consent, and tracked URLs are stripped of tokens, signing keys, and workspace slugs before being sent. A new hrcTrack() helper standardises custom events across modules so feature usage can be measured consistently.
Public form uploads • mobile camera multi-shot fix
Adding a second photo from a phone camera no longer wipes the first. The file queue now accumulates across change events and submits via fetch + FormData whenever items are pending, so multi-attachment uploads complete in a single round-trip and survive iOS Safari's per-tap input reset.
FixedMessagingLocalization
Outbound emails and PDFs render in the recipient's language end-to-end
Every outbound email and the PDFs they carry now resolve language per recipient. Coverage includes group-contact emails, food-allergies summaries, and shift emails sent from the Clockwork QR pipeline. Saving a user profile no longer writes the actor's session language into users.preferred_language, closing a long-running source of mis-localised mail. The email template loader now lives inside the with_lang() boundary so async sends pick up the resolved language even when no admin is in session.
Competence • multi-file proof bundles with per-class verification
Competence proof can now be uploaded as a bundle of multiple files, so a renewal upload doesn't replace the previous evidence. Each class on a multi-class certificate verifies, rejects, and resets independently in the review modal. Actions stay scoped to the class you clicked, not the whole bundle. Verifying the last outstanding class auto-approves the linked pending bundle, and the review modal's preview, body, thumbs, metadata, and class list now scroll as one capped region instead of stacking off-screen.
AddedInfrastructure
Deploy • DB migration gate on app nodes
App-node post-receive hooks now refuse to rsync if ops/required_migration.txt names a migration that hasn't been applied to the database. Worker nodes are exempt by hostname so non-DB-touching deploys still flow. Structurally enforces DB-first deploy ordering, so app code can no longer reach the apps before the schema it depends on.
performance.mark() is now placed across the full clock-in/out timeline (form open, submit, modal visible, handout/return visible) so timing regressions can be caught from real-user metrics rather than hand-timing the flow.
Technical focus: performance.mark() • cw-* timing marks
Shift CSV imports get a helper card that shows the expected format, with column headers now matching the form labels exactly so renaming a field in the form doesn't silently break the import. Upload validation enforces is_uploaded_file() on the temp path before any further processing.
Billing • workspace plans split from operational add-ons
The billing page separates the workspace plan tiers (Core / Pro / Enterprise) from operational add-ons such as Ops and module-level entitlements, so it's clear at a glance which line items are subscription tiers versus per-feature opt-ins.
AddedLocations
Locations • crew list actions surfaced from the modal
Each location modal now exposes the crew list actions directly, so you can pull a roster or message attached crew without leaving the page.
Sending out request emails no longer blocks the page response. Requests are queued and dispatched asynchronously through the worker. The email copy now spells out that the worker should review and confirm even when they have no allergies to declare.
AddedFormsWorkforce
Food & allergies • related and overlapping crew in summary PDF
The summary PDF now includes a person-centric section listing related and overlapping crew with shared allergens or diet markers. Names of unrelated workers are never paired with their dietary data; the section is anonymised for GDPR. The detailed PDF's group filter now correctly includes subgroup members, and the section reads group membership from current account_users, not affiliation history.
AddedClockworkWorkforce
Items • bulk return, bulk transfer, and clock-out return capture
Issued items can now be returned or transferred in bulk from the Open page, and Clockwork's clock-out flow captures returns alongside the session itself. Pool items configured with require_identifier_on_issue are supported in handout, and max_quantity is enforced for concurrent issuance across multiple workers. Closes a race that could let a finite pool go over its cap.
UpdatedInfrastructure
Public changelog API now exposes module taxonomy and technical-focus metadata
GET /api/public/changelog now returns a `modules` array (locked taxonomy of 20 keys) and `technical_focus` (string or null) on every entry. Existing fields unchanged — purely additive. ETag bumped from v2 to v3 so cached clients revalidate cleanly.
Public changelog redesigned as an operational technical surface
Outcome-first titles, type and module pills, optional technical-focus footer line on infrastructure and security entries. Module taxonomy spans 20 keys (Workforce, Clockwork, Infrastructure, Security…). The page is now English across all locales for terminology stability; surrounding workspace UI stays localized.
UpdatedUI
Smaller polish across users, imports, and platform switcher
Employee preselected as default worker type on user import; phone and rate formatted in import preview; alert bullets indented; age shown inline beside DOB on user detail; phone country-code stripping unified across forms; platform switcher hidden when an account has only one platform enabled.
FixedContracts
Contract upload form prefills validity dates from project
Selecting a project on the contract upload form now prefills valid_from and valid_to, mirroring the existing behaviour of the new-contract form.
FixedForms
Submission deduplication unified across signup, public form, and admin paths
Double-submit dedup is now applied consistently to every submission entry point. The food-allergies group column reads current group state, and invoice reference is now properly optional rather than silently flagging a submission as incomplete.
FixedMessagingLocalization
Transactional emails resolve language per recipient
All outbound mail — not just contracts — now picks language from the recipient's preference plus the account default, instead of the sending actor's session language. Closes a long-standing class of mis-localised notifications.
Technical focus: resolve_recipient_lang() • Per-recipient language resolution
UpdatedUI
Form interaction model unified across the workspace
Native browser confirm and alert dialogs replaced with in-app modals (Escape closes, focus returns to the trigger). Every form shows a submit loading state, and submitter values are preserved when validation fails.
SecuritySecurity
Security hardening pass across POST handlers, PIN entry, and signing tokens
Enforced CSRF on every POST endpoint, added per-user PIN throttling, and started logging IP plus user-agent on contract-signing and password-reset tokens. Mail attachments now fail closed when the file is missing, and elevated access is cleared automatically when a user is demoted.
Form submissions grouped by workflow state, reviewed in a dedicated modal
Submissions are bucketed by workflow stage (needs review, approved, rejected) instead of raw lifecycle states. Each opens in its own review modal, keeping context off the main list.