← HR Cluster

Changelog

Operational and technical updates to the HR Cluster platform.

Types of changes
Added New functionality or modules.
Updated Improvements or changes to existing functionality.
Core Major architectural, platform-wide, or operational changes.
Deprecated Features scheduled for removal.
Removed Features or functionality removed.
Fixed Bug fixes and issue resolution.
Security Security improvements or vulnerability fixes.
2026

Schedule • clearer staffing colours

Shift staffing colours now follow a where-do-I-still-need-people model. Fully staffed shifts render green and recede, almost-complete shifts render neutral grey, and unfilled gaps stand out. Red is reserved for overstaffed shifts.

Locations • streamlined linked-users picker

The picker for linking users to a location now reuses the same participant selector as risk assessments, showing clean name-only pills rather than employee number, email, and phone. This makes assigning people to a location quicker and less cluttered.

Competence • upload fixes for proof and duplicate types

Re-adding a competence type a worker already holds no longer creates a duplicate record; the uploaded proof now attaches to the existing competence instead of a blank copy. A self-service proof upload added at the same time as the competence is no longer silently dropped, and the ten-file, ten-megabyte upload rule is enforced consistently across the upload paths.

Clockwork • clearer self-service terminal access controls

The control that grants a worker access to the public self-service clock-in terminal is now labelled Self-service terminal access on both the user forms and CSV import, and defaults to denied for new forms. Eligibility for the public terminal is decided by active membership plus this explicit opt-in. New signups and imported workers are issued a PIN consistently across every intake path, so a worker granted self-service access can clock in without a separate step.

Incidents • admin soft delete and clearer list defaults

Administrators can now soft delete open and in-progress incidents; a closed incident is the sealed record and is never deletable. The capability is admin-only by default and resolves through the permission system, so a manager can be granted it individually. The incident list now defaults to All, with All shown first in the filter navigation.

Vehicles • overrides honoured everywhere and a manager grant flow

Per-vehicle access and parking overrides are now resolved consistently on both the desk and the plate scanner, so the two surfaces always agree, and a vehicle that is valid right now shows a clear green chip. The add page gains a manager grant flow: an inline access and parking editor sits alongside the vehicle details, and Create and grant access writes the windows, then submits and approves them with the manager as the decider so the vehicle is immediately valid on the desk and scanner. Ownership and contact wording is unified across add, edit, detail, and desk, matching the public intake terminology.

Vehicles • gate-check desk with clickable status and scan history

The vehicles desk now has a gate-check modal for working a checkpoint without leaving the page. Pressing Enter in the search box runs a true server-side plate lookup, independent of the current filter or time window, and each row has a Gate button that opens the same decision view. Access and parking status now show as clickable pills that open a per-track detail modal, and the row subline shows the full validity span rather than just the first window. The vehicle History view adds plate-scan events as a distinct third source alongside the access lifecycle and desk movements, so the gate scanner trail is finally visible.

Settings • account default language preserved on save

Saving account settings no longer resets the account default language. The configured default is now preserved across saves, so outbound emails and new-user defaults keep using the language the account actually chose.

Settings • configure who can access Accreditation and Vehicles

The Accreditation and Vehicles modules now have a Configure button on the modules settings page that opens the shared per-user access list, the same pattern already used by Items and Suppliers. Operators can grant the relevant permissions to individual users per module from one place.

Risk assessments • automatic confirmation invites and soft delete

Participant confirmation invites are now sent automatically when an assessment goes live and when participants are added or changed on a live assessment, instead of only on a manual click. Risk assessments also gain an admin soft delete for non-sealed records, which revokes any outstanding sign-off tokens so a deleted assessment can no longer be confirmed.

Risk assessments • participant sign-off

Participants can now confirm in writing that they were briefed on a risk assessment. A tokenized public page lets a participant confirm without logging in, and the workspace adds Request sign-off, Resend, and Request from all actions. If the assessment changes after an invite is sent, the pending sign-off is blocked against the stale version so a confirmation always refers to the content the participant actually saw.

Incidents • public reporting on the meldavvik domains

Public incident reporting can now be served on the meldavvik.no and meldavvik.com domains. An account-scoped link opens that account public incident form and stays on the meldavvik domain, which is convenient for print and QR codes, while manager review links continue to point back to the workspace. This gives a clean, dedicated address for collecting incident reports from the field.

Vehicles • registry lookup tells an outage apart from a real miss

A temporary failure from the Statens vegvesen vehicle registry, such as a timeout or a rate limit, is no longer reported as plate not found. When the registry is briefly unavailable the lookup now shows a try again shortly message instead of telling the operator or an external supplier to type every detail in by hand. A genuine miss still prompts manual entry as before.

Suppliers • action link active by default and clearer invites

Every supplier now gets an active action link automatically, so the entry point a supplier opens to reach the modules an operator has configured no longer needs to be created and activated by hand. The invite language picker defaults to the account language rather than the operator interface language, since the recipient is a cold contact for that account, and the invite button consistently reads Send invite. The redundant last-invite-sent line was removed from the intake links list because the same detail already appears in the send modal.

Suppliers • approval email sent on activation

When an administrator approves a supplier and it becomes active, the supplier now receives an approval email with a link to its action page. The email is sent only on a genuine transition into the active state, so re-saving an already-active supplier never resends it.

Accreditation • affiliation field on the record form

The accreditation record form now has an optional Company or organisation field on the identity card, so operators can capture who a manual guest or public-link registrant represents when there is no linked supplier. Supplier-sourced records still use the linked supplier as the affiliation. New accreditation types now default to one-time issue, which matches the most common guest and wristband case, and the records search field spans the full row.

Accreditation • issuance now works independently of presence

Issuing accreditation phases no longer depends on whether the holder is signed in. Previously, once a phase was issued the holder flipped to inside, the Issue button disappeared, and a partially issued record could not be finished without signing the person out and back in. Issuing and presence sign in and out are now separate actions for every accreditation type, so a part-issued record can always be completed. The issued and total count, for example Partially issued (1 of 2), now shows consistently on the desk card, the records column, and the details view.

Clockwork • bank-detail requirement follows worker type

The verify-user step no longer flags a missing account number for workers who are not paid to a personal bank account. The bank field is now required only for employees; volunteer, invoice, and hourly-dugnad workers are no longer marked incomplete for a detail that does not apply to them.

Subscription • full plan summary with total price

The account subscription view now shows the full plan summary, including the included entitlements and the total price, rather than just the plan name. Capacity counts use European number formatting so large figures are easier to read.

Accreditation • desk shows affiliation, phase names, and a validity line

The accreditation desk card and its detail and issue-confirmation views now show the linked supplier as a dedicated affiliation row beneath the type chips. Whole-project records list the actual project phase names instead of a generic label, and every card carries a consistent validity line so access windows read the same way across the desk and the record history.

Vehicles • per-vehicle access and parking overrides

A manager can now override the access and parking permissions of a single vehicle on top of its approved request windows. The override is an additive layer: it never changes the underlying approval, and removing it instantly reverts the vehicle to its default permissions. The effective result is honoured everywhere the vehicle is read, including the detail page, the desk, the plate scanner, the request summary, and the access gate, so the screen and the enforcement always agree. Every override that is created, edited, or removed is recorded in the vehicle timeline alongside the approval history, so the reason a vehicle differs from its originally approved scope stays visible months later. Action labels now distinguish an override (a temporary exception) from modifying the underlying approval.

Workspace • user picker prefills the selected user on edit

Opening an edit form that carries a chosen person now prefills the user picker with that person, so the current selection is shown instead of an empty field.

Suppliers • simpler per-supplier vehicle access panel

The per-supplier vehicle access configuration panel is simplified, with optional toggles for collecting a driver name and phone number. When parking is offered, a contact is required so there is always a way to reach the holder. The panel continues to mirror the standalone vehicle link controls from a single shared form.

Vehicles • parking selections persist on public submissions

Parking choices made through a public vehicle link are now saved correctly on both the link configuration and the resulting public submission, so a parking grant requested at intake is no longer lost before review.

Vehicles • compressed access windows on the detail view

Long lists of access dates now compress by contiguity on the vehicle detail view and in the edit modal, so a run of consecutive days or a whole-phase grant reads as a single range instead of a stack of individual dates. This keeps entitlements readable for vehicles cleared across a full event.

Workspace • cleaner timestamp formatting

Date and time values shown together no longer carry a middle dot between them, giving a cleaner, more consistent timestamp across the workspace.

Platform • power ingest health monitoring and alerting

The power ingest pipeline now has a health check that confirms data is actually flowing, not just that the worker process is running. It tracks per-source freshness and raises an alert when ingest goes stale or the worker stops, with a recovery notice when it returns to normal. An on-call runbook documents the alerts and the response steps.

Groups • bulk emails run in the background

Bulk actions that send to many people now run through the job queue instead of blocking the page. Form-request invitations and contract reminders are queued and delivered in the background, and the registration link in queued form invitations now uses the correct account host.

Public forms • clearer vehicle and accreditation request layout

The public vehicle and accreditation request forms now share one hierarchy. The request type is the only heading, the footer is a single row with the back-to-hub link on the left and submit on the right, and the people helper text uses the same body font as the intro. A lone person card no longer shows a Remove control, editable track chips start unchecked so nothing is selected by accident, and supplier-scoped forms name the supplier in the intro. The accreditation desk also shows the concrete validity windows alongside the phase names.

Vehicles • desk shows approved vehicles with make and model

The vehicles access desk now lists only fully-approved vehicles, so operators working a checkpoint see exactly what is cleared to pass. Each row shows the make and model with the colour in the active language, and the approve or deny modal returns to the requests list after a decision so the queue stays in view.

Vehicles • automatic fill from the Norwegian vehicle registry

Entering a valid Norwegian plate now looks the vehicle up in the official Statens vegvesen registry and fills in the make, model, colour, and category automatically. The colour and category are shown in the active language, and a suggested HR Cluster vehicle type is derived from the registry category. Registry-sourced fields lock so the authoritative values are kept, and the same auto-fill works on the workspace add and edit forms as well as every public intake form (standalone, supplier, and accreditation-linked). Lookups are cached so repeated checks on the same plate are instant.

Groups • subgroup roll-up and export refinements

A top-level group now rolls up the members of its subgroups in the Users tab, so the parent view reflects everyone underneath it. The group users export shows the member title instead of the backend role, and the CSV and PDF export actions moved up to the page header row for quicker access.

Schedule • statistics PDF refinements

The schedule statistics PDF moves to A4 portrait with tables resized to fit the page, fixed time-column widths so dates no longer overflow, empty-state cards where a section has no data, and cleaner page-break rules. The on-screen chart gains vertical midnight gridlines with day labels centred between them, and the crew list table now matches the shared workspace table styling.

Suppliers • send and resend intake invitation emails

Operators can now send and resend a supplier intake invitation email per intake token directly from the workspace. This gives a supplier a clean link to complete or update their own details without the operator having to relay it manually.

Suppliers • clearer accreditation decisions, desk, and emails

The supplier accreditation decision email now renders the actual per-person decisions in a cleaner layout, and the submitted-notification email links straight to the review surface with an absolute URL. On the desk, accreditation types render as chips with validity shown as muted supporting text, the record edit opens in a standard modal with a unified action row, and contiguous access windows on the supplier cards compress into range chips so long date lists stay readable. Notify supplier moved into the person card actions, and the dashboard accreditation card links directly to the Ops requests queue.

Suppliers • combined export with PDF report and CSV spreadsheet

Supplier export is now a single Export action that produces either a formatted PDF report or a CSV spreadsheet from the same selection. Personnel and vehicles are split into their own sections, the former Drivers section is renamed Vehicles, and a catering summary rolls up food and allergy requirements for the event. Both formats use single-select scoping so an export covers exactly one section at a time.

Accreditation & Vehicles • a project phase is now required

Accreditation and vehicle access now require the selected project to have at least one phase defined. Phase-bound access windows clip to the phase boundary, so a request can no longer be granted against a project with no timeline to anchor it. This keeps validity windows meaningful across the desk, the records list, and the public intake.

Vehicles • camera plate scanner on the access desk

The vehicles access desk now has a camera-based plate scanner for operators working a checkpoint. It reads the plate continuously and locks onto a stable candidate, recognises Norwegian and other European formats including two-line motorcycle and trailer plates, and corrects the common character confusions before it commits a result. Recognised plates are matched against the plate universe for the selected project so a near miss still resolves to the right vehicle, and the scan resolves the checkpoint action without leaving the page. The terminal is built for phone use in the field with a tall scanning area, a checkpoint picker, and a compact result layout.

CSV exports • Norwegian characters render correctly in Excel

CSV exports now use a consistent UTF-8 BOM-only format across people, contacts, channels, groups, sessions, projects, and suppliers. This prevents Excel from misreading Norwegian characters while preserving semicolon-delimited output for Scandinavian locale settings.

Incidents • Company involved field searches suppliers

The Company involved field on the incident form now searches the account suppliers as you type, with a free-text fallback when the company is not a registered supplier. The autocomplete only appears when the Suppliers module is enabled, and the suggestions show company identity without exposing contact details.

Platform • email delivery logging, suppression, and follow-up

Outbound email now records delivery status, classifies the result, and suppresses addresses that hard-bounce so the system stops sending to dead inboxes. A follow-up path surfaces delivery problems for action, and the inbound delivery webhook can be turned off with a single kill switch when needed.

Contracts • correct a recipient email and resend

When a contract has gone to the wrong address, the recipient email can now be corrected and the contract resent in one flow, available while a single recipient is still unsigned. Signed-copy delivery emails also carry the account context and summary metadata so the recipient sees which event the contract belongs to.

Suppliers • self-contained vehicle access configuration

Each supplier now carries its own vehicle access configuration, with the same per-track access and parking controls used by standalone vehicle public links. The supplier vehicles tab mirrors the accreditation tab layout and reuses the shared link-share card, and enabling the config requires a responsible person to be set so submissions always have a return channel.

Accreditation & Vehicles • redesigned operational desks

The Accreditation and Vehicles desks now share one operational toolbar with search-as-you-type, the native search clear control, and a uniform focus state. The request queues default to pending so the list shows only what needs action, and the time-window filter is phase-relative so operators can scope to the current or next phase rather than picking dates by hand. Per-desk option menus, clearer status and validity hierarchy, and consistent empty states make both desks readable at a glance during access work.

Suppliers • accreditation guided start and date boundary handling

The suppliers accreditation flow now opens with a guided start and the default project preselected, removing the most common dead end on first use. Accreditation date windows render open boundaries and narrowed phase-edge visibility consistently across record forms, the public intake, and the dates-mode picker. The date row generator honours project phase flags so phase-bound entries align with the project timeline. A multi-type configuration also lets a single accreditation type cover several profiles where the access pattern is shared.

Power • phase balance and risk separation, CT multiplier across read paths

Power Live now separates Phase balance and Phase risk into two distinct axes. Balance stays informational while Risk drives the alarm-bearing classification based on imbalance, utilisation, and fuse pressure. A meter context badge is shown across Live, Analytics, public links, and Source so the displayed multiplier and meter type are explicit at every read site. The CT multiplier (meter type plus primary and secondary ratio) is honoured on both Live and the public read path, and an admin debug view exposes raw versus normalised values for verification.

Power • public Analytics dashboard with PDF download

Public power links now have an opt-in Analytics tab alongside the Live dashboard. The Analytics surface uses the workspace layout and includes a PDF download that mirrors the on-screen analysis for sharing with stakeholders outside HR Cluster. The topbar is unified across Live and Analytics with the same chrome, language pill, and legal footer. Open Graph and Twitter card metadata are set on both surfaces so shared links preview cleanly in chat tools, and a public favicon ships at the document root.

Accreditation • optional vehicle request on public intake

The accreditation public intake form now offers an optional vehicle request per person. When the submitter toggles vehicle access on, the form captures plate and parking details and creates a linked vehicle request on save. Phone is required when a vehicle is requested so the desk has a return channel, and the dates picker accepts cross-midnight end times so overnight access can be requested in one row. This removes the separate accreditation-then-vehicle round trip during pre-event registration.

Vehicles • requests approval workflow with row actions and edit page

Vehicle access requests now have a full approval workflow on the Requests page. Each row carries Details, Approve, Deny, and Edit actions; granted requests open a dedicated edit page so operators can adjust validity windows and parking without rejecting the request. The Records page gains the same Details action and modal, so the request summary is reachable from the operational list rather than only from the rule counters. Approve, Deny, and Edit run inline and update the row in place, removing navigation steps during access desk work.

Suppliers • accreditation request flow with phase-based scoping

Suppliers can now go through a structured accreditation request flow scoped to project phases. The supplier action page becomes an action hub surfacing Incidents and SJA cards alongside the new accreditation request. Accreditation requests follow project phase availability and support crew preferences such as food and allergy information. Accreditation availability can be limited to selected project phases.

Power • live energy monitoring with public TV dashboards

A new module brings live power monitoring into HR Cluster. Connect supported energy sources (initial integration: Tibber) and monitor live telemetry through a multi-source dashboard with capacity indicators and selectable trend intervals. Public links generate password-gated TV-viewport dashboards with auto-rotation across sources, sized for control rooms and production offices. An opt-in data-logging rule system stores historical telemetry, surfaced through a historical read view and an Analytics sub-tab with computed statistics.

Schedule statistics • Accuracy, Variance, Drift, Arrival, and Hotspots cards

The Schedule statistics page gains five new analytics cards. Shift Accuracy, Variance, and Drift compare planned versus delivered shifts; Arrival Performance reports on-time, late, and very-late arrivals with percentile breakdowns; Pressure Hotspots highlights staffing shortages and overcapacity across analysed intervals. A help modal explains the percentile metrics. CSV and landscape PDF exports are available for every card.

Settings • account timezone surfaced in General settings

The account timezone is now visible and editable directly from General settings. This removes an extra navigation step during account setup and regional configuration.

Groups • contract reminder breakdown and signature visibility

The bulk contract reminder action now shows a breakdown of skip reasons (for example: already signed, no email on file, contract not assigned), so operators can immediately see why some users were not contacted. The contract coverage by project view gains a Signatures column for at-a-glance signed totals per project.

Schedule • mobile optimisation and high-volume staffing improvements

Schedule surfaces received mobile refinements together with layout tuning for larger staffing operations. Dense festival views reduce visual noise while preserving shift visibility across wider ranges.

Shifts import • upload overrides, status control, and role backfill

The shifts importer collects per-batch overrides for project, location, and group at the upload step instead of inside the CSV columns. Draft or Published status is selectable at the same step and defaults to Published. Imported rows backfill the shift role from the role label or title when no explicit role id is provided, matching case-insensitively against existing shift roles. Status keys are now translated into Swedish and Danish.

Projects • optional phases and timeline boundaries

Projects can be split into phases, opt-in per project. Phase dates are optional and a phase can be flagged as a start or end boundary; live validation keeps the timeline consistent as you edit. Projects also move into the shared platform sidebar block and are pinned to the top, since they cross workforce and ops surfaces.

Suppliers • categories, intake routing, and confirmation status

Each supplier now carries an operational category that drives intake-link routing, paired with type on the edit form. Public intake links can seed an internal-responsible user, and intake submissions notify the assigned responsible automatically. A new Confirmed status overlay propagates across the supplier list, parent picker, and sub-suppliers tab so operators can spot validated entries at a glance.

Locations • physical hierarchy, work areas, and inline venue context

Locations now distinguish physical locations from work areas through a dedicated location type model. Physical locations support deeper nesting while zones and gates render inline beneath their host location for clearer venue navigation. Overview rows use a lighter metadata treatment to reduce visual noise.

Privacy • user erasure action for GDPR right to be forgotten

Admins can now trigger a structured GDPR erasure on a user record. The action anonymises personal data while preserving operational history required for audit and compliance. Use the dedicated action on the user detail page; the operation is logged in the audit trail.

Accreditation • project-scoped access management with profiles and phases

A new module for managing access credentials per project. Define access-profile types with linked locations, zones, and gates; group records into packages; track movement phases. The type editor renders the parent chain in location, zone, and gate pickers so operators see the full venue context while building profiles. Status and access summary are consolidated into a single footer card on the type detail view.

Schedule • role default items and shift items picker

Shift roles can now carry a default set of required items. Creating a shift and picking a role auto-loads its defaults until the first operator action, after which they become additive via an explicit Apply role defaults action. Roles admin and the shift create / edit forms share one search picker that spans items and kits with inline kit expansion and per-row return-required toggles. The shift import applies role defaults by case-insensitive role-name match, and the shift detail page is now a clean read view with all mutation routed through the Edit shift CTA.

Risk • SJA form and detail polish

The SJA workspace edit form gains a multi-pill participants picker with progressive disclosure for participant rows, replacing the previous single-select control. The mobile readiness stepper was redrawn with cleaner circles and a calmer connector line, and the readiness checkbox primitive plus the operational-selection primitive are now unified across every SJA surface so behaviour and visual weight match end to end. Buttons inside the tinted state card now sit on a solid white background for legibility, and a missing CSS variable that affected the detail view's green tint is restored.

Risk • report an incident directly from an active SJA

Operators can now report an incident straight from an active risk assessment. The SJA stays intact as the operational document; the incident is recorded as a separate event that links back, and one SJA can spawn many incidents over time. The RA detail page gains an Escalation tier in Quick Actions and a Related Incidents sidebar, and the incident detail strip carries a bidirectional Linked risk assessment line.

Risk • public risk-assessment-create tokens converge to lowercase URLs

Public risk-assessment-create links now use a lowercase prefix (racr-). Existing uppercase RACR- links are 301-redirected to the canonical lowercase form, so any previously shared or printed URLs keep working without manual reissue.

Reporting forms • flat operational-path location picker

Every reporting form that asks for a location (public Incident, public SJA, workspace SJA edit) now uses the same flat operational-path picker. Rows are compact single-line entries with the parent prefix muted and the leaf-location name strongly weighted, and search results are sorted parent-first so the venue path reads naturally. The flat picker replaces three separate nested controls and gives reporters one consistent mental model wherever they pick a location.

Incidents • public form converged with SJA style and two-step review

The public Incidents form was rebuilt to match the public SJA visual language end to end. The freetext location input was replaced with the unified location picker (saved location plus a "use custom" fallback), and a two-step review pattern was added so reporters can verify their submission before sending. The redesigned form lands operators in the same visual hierarchy whether they are reporting a hazard or filing an incident, removing the previous style mismatch between the two.

Locations • zones and gates with cascading pickers across SJA and Incidents

Locations now carry two new child entities: zones (operational areas like Backstage, Front of House, Stage Left) and gates (controlled access points like Main Gate, Crew Gate). Both attach to any location, parent or leaf, and a gate can optionally link to a zone within the same location. The workspace and public SJA forms plus the public Incidents form all gained cascading zone and gate pickers below the location picker; selections appear on detail views as a chained Location • Zone • Gate label. The Locations index gets a pill-nav for filtering between Locations, Zones, and Gates, plus a structured detail page where all three children share the same card pattern.

Schedule • single-keystroke shift assignment and unified modal ESC handling

Assigning a worker to a shift now submits on Enter inside the inline picker. Type a name, hit Enter, the shift is assigned without a second click on the Assign button. Modal ESC handling was also consolidated through a single registry so every overlay (shift detail, document viewer, competence review, generic modals) closes consistently and no longer fires during CJK IME composition.

Groups • parent picker in the edit modal with leaf-only safeguards

The group edit modal now exposes a parent-group picker, so a top-level group can be turned into a subgroup, and a subgroup can be moved between parents or promoted back to top level. The picker disables with a hint when the group has its own subgroups (which would push the structure past the two-level cap), and the save handler rejects any move that would either create a third level or relocate users out of a leaf group, matching the same leaf-only rule the create path already enforces.

Users • request national ID number through the missing-info banner

The amber missing-info banner on a user profile now requests the national ID number when it's empty, and the public missing-info request form prompts for it under the Personal section in every supported language. The submitted value is encrypted at rest like every other sensitive ID column.

Sessions • parent-group rollup and local-day attribution

Parent-group session views previously showed zero sessions because the filter required an exact group-id match. Parent groups now roll up their own sessions plus all direct subgroup sessions; leaf groups remain unchanged. The default day filter on group and project session pages also flips from today to All, matching the projects-sessions behaviour. Separately, session day attribution for regular / overtime splits now consistently uses the account-local day instead of the UTC day, so totals match the displayed timestamps on accounts whose local time straddles midnight UTC.

Sessions • clearer Worked-hours summary and unified mobile card grid

Sessions summary cards now show Worked hours as a single top-line total with Regular and Overtime indented underneath, so the breakdown reads as a classification of the same worked total rather than two figures stacked on top of each other. The mobile session list adopts a compact two-row card grid across user, group, and project sessions (name and status pill on row one, date and duration on row two), so the same card pattern is in use everywhere sessions are listed.

Schedule Statistics • time breakdown card and unified ratio tables

The Statistics page gains a Time breakdown card that buckets the planned / filled / clocked triplet by time (2-hour buckets up to 30 hours, daily beyond that), making coverage gaps surface against the actual hour of day. Both stats tables now share two ratio columns: Coverage (filled / planned) and Clocked (clocked / filled), with a consistent 50 / 80 / 100 severity ladder. Manual datetime edits in the toolbar now wait 1500ms before submitting and correctly de-activate the preset pill, fixing a long-standing edit-on-every-keystroke bug.

Schedule • day-board layout with global-modal shift detail and location filter

Schedule's three timed views (1-Day, 3-Days, Week) now share a single lane-based board layout with vertical guide rails per day, anchored to a shared visual bottom so the board reads as a coherent grid regardless of shift count. Shift detail moves from an inline-expanding panel to a global modal with structured header, Assigned and Staffing sections, and Open-details / Edit-shift actions; the same surface renders on every viewport. The toolbar gains a location filter (when the locations module is on), the "Today" label is renamed to "1 Day", and mobile reflows the date picker and Add shift onto a single row above the filter grid.

Crew List • email a PDF of the day's crew and shifts

Operators can email the day's crew roster as a PDF directly from the Crew List view. The recipient field uses the standard user typeahead, and delivery routes through the shared email template system so wording and language follow each recipient's resolved preference rather than the sender's session language. Export, email, and print actions now share one equal-width mobile action row.

Scheduling • unified toolbar system across Schedule, Crew List, and Statistics

Schedule, Crew List, and Statistics now share the same toolbar layout. Date controls, filter pills, and period navigation land on one row at typical desktop widths and stack predictably on phones. Role-based filter pills replace the search field on the main Schedule view, and the "Add shift" CTA only appears where it makes sense (the main Schedule view, not Crew List or Statistics).

User import • admin language no longer leaks to imported accounts

Importing users while signed in as an admin no longer writes the admin's session language onto the new user records. Imported users now inherit the account default and resolve their own preferred language on first interaction, matching the recipient-language rule the rest of the platform already follows.

Users • food allergy confirmation modal redesigned

The food allergy confirm modal now uses a clear title plus body layout, and the request action moves up to the card header so the most common operation is reachable without expanding the card.

Risk • workspace polish for live operations

Risk assessment detail pages now use a card-grid hazard layout with severity-driven tints and a clearer event hierarchy. Live SJAs expose an expanded controls section so operators can act on safety measures during the work itself, not only after the fact. The public risk form hides the submitter block for signed-in visitors so backend users do not re-enter their own details.

Dashboard • project and location scope filtering

Dashboard widgets now scope to a chosen project and location. Filters are resolved server-side and cached per scope key, so switching scope reloads the matching widget set without a full page reset. The scope controls only render when more than one project or location is enabled, keeping single-scope accounts uncluttered.

Staffing chart • clocked-in series now the primary operational signal

The staffing chart now prioritizes live attendance as the primary operational signal, with scheduled coverage rendered behind it for comparison. Chart readability was improved across dense overlap scenarios, and NOW indicators now hide automatically outside the active time window. Mobile and desktop rendering were tuned for clearer visual separation between planned and live staffing levels.

Schedule • date-range staffing statistics with per-location breakdown

A new Statistics page under Schedule charts staffing across a configurable date range, with stats split by location and presets (today, week, month, custom). The chart adapts x-axis labels to the range, renders localized headers, and exports cleanly to PDF (embedded SVG) and CSV. Preset chips stay lit across prev/next period navigation, and the mobile layout flattens the location list into one card-per-row hierarchy that extends up to tablet widths.

Comms • live-linked supplier contacts and pre-flight import counts

Suppliers can be added to contact lists as live-linked entries. Renaming a supplier or editing its contact details propagates to every list that includes it. The import modal now previews how many entries are new, already present, or missing required contact info before the operator confirms.

Workspace • incidents and risk assessments aligned

Both modules now share a stable reference scheme (IR-YYYY-NNN for incidents, equivalent for risk assessments), the same list column layout, identical filter chips, and matching detail-page hierarchy. The reference column is first and stays visible on mobile. Filtering by status, group, or owner now behaves the same in both modules.

Incidents • convert directly to a linked risk assessment

Any incident can now be converted to a risk assessment in one action. The incident's basics, location, and reporter prefill the SJA edit form so the operator lands straight in editing. The original incident keeps a permanent link to the resulting SJA so the audit trail stays intact across both modules.

Risk • public SJA workflow with phased form and v2 taxonomies

A public risk-assessment form is now available per account. The form steps through five phases (basics, hazards, controls, participants, readiness) with mandatory-field gating between phases. Hazard and control taxonomies group under six operational domains so every SJA pulls from the same vocabulary. Submitting from the readiness step lands the assessment in logged status without an extra approval click.

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.

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.

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.

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.

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.

Technical focus: GA4 • Consent gate • Path sanitisation

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.

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.

Technical focus: resolve_recipient_lang() • with_lang() boundary • preferred_language default empty

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.

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.

Technical focus: ops/required_migration.txt • Pre-deploy schema check

Clockwork • observational performance instrumentation

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

Imports • shift CSV helper, column alignment, upload validation

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.

Technical focus: is_uploaded_file • Header validation

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.

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.

Food & allergies • async request emails, clearer copy

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.

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.

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.

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.

Technical focus: ETag v2 → v3 • Locked module taxonomy • CORS allowlist

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.

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.

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.

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.

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

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.

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.

Technical focus: CSRF • PIN throttling • Per-token IP/UA audit

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.

Per-module access management lives on the module itself

Every module settings page now lists who has access and exposes a typeahead to grant or revoke without leaving the module. Removes the round-trip through global user settings.

Self-service area for workers • hours, profile, competence, contracts

Workers get a personal area at /me with their hours dashboard, an editable profile, a competence wallet for adding qualifications and proof, and a contract archive. Reduces day-to-day questions reaching account managers.

Signup list filters out shifts the worker is already assigned to

Shifts already assigned to a crew member are filtered out of the public signup list, preventing double-assignment from a single signup session.

Enabling Ops grants access to managers, not just admins

Activating the Ops platform on an account now correctly extends Ops access to managers — closing a permission gap that required a manual second step.

Module settings page surfaces platform attribution per module

The modules settings page shows which platform — Workforce or Ops — each module belongs to, making the scope of any toggle change immediately visible.

Session cards align time and task lines via mobile subgrid

Session cards on narrow viewports now use a two-column subgrid so time and task fields stay aligned across all rows.

Radio channels gain mode and signal-type metadata; lists exportable

Radio channels now carry mode (analogue, digital, DMR, TETRA) and signal type (simplex, duplex). Public contact and channel lists are downloadable as CSV or PDF on a per-list basis.

Voiding fully-signed contracts notifies the recipient

Fully-signed contracts can now be voided. The recipient receives a notification email when their contract is voided, regardless of opt-out settings — voiding is not optional communication.

GPS captured consistently across every clock-in/out flow

Location now logs whether the worker clocks via QR code or a manager clocks them in from the backend. GPS capture timeout is also more reliable on slow connections.

Food and allergies • dietary data collection module

Collect dietary preferences and allergy information from crew. Send request emails individually or in bulk via Groups, track responses, and export a summary. Access grants are per-user so visibility stays controlled.

Users • preferred language no longer corrupted on save

Editing a user could in rare cases write the literal string "Array" into their preferred language field. The user form now validates the active language before saving.

Groups • contract coverage table tidy-up

The contract coverage table on the group detail page no longer shows a redundant Details button; the row itself is the link.

Users • import lives in Settings

The Import button on the Users page now goes to the canonical Settings → Import wizard, with the old standalone import URL redirecting there. The button is also hidden on mobile, since the wizard is desktop-first.

Projects • clearer hierarchy, no empty container rows

Project lists now show "Parent / Child" for projects nested inside a container, and container projects with no children are no longer shown as empty rows.

Comms • phone numbers display as +47 12345678

Phone numbers on the Contacts tab and in the printable contact-list PDF now render in spaced international format for readability.

Items moved into Ops

Items has been recategorised in the sidebar from Workforce into Ops, alongside Inventory and Locations.

Contracts • emails go out in the recipient's language

Contract emails (sent, viewed, signed, declined, reminders) now resolve language per recipient using their preferred language and the account default as fallback, instead of using the sender's language. Cron-triggered reminders translate correctly for each individual recipient even when no admin is logged in.

Contracts • automated signing reminders

Recipients with unsigned contracts are now reminded automatically by email. A standard reminder fires 5 days after sending and again 3 days before the recipient's first scheduled shift. An urgent reminder fires when a shift is due within 24 hours and the contract is still unsigned. Each stage only triggers once per recipient, so the same person never gets the same nudge twice.

Comms • Contacts and Radio Channels

A new Comms section in the sidebar groups two modules. Contacts (per-account contact lists for emergency, suppliers, crew leads) has moved here from its previous location. Radio Channels is brand new — track which crew or department is on which frequency / channel during the event, with per-channel notes and a printable overview.

Messaging • group with subgroups no longer drops recipients

Composing a message to a group now correctly resolves recipients via the leaf-only group assignment. Users in subgroups under the selected group are no longer missed when the message is sent.

Contacts • translated default list and tighter public layout

The default Contacts list seeded when the module is first enabled is now created in the account's default language. The public contact-list page also renders denser cards on small screens.

User requests • token validity extended to 72 hours

Tokens for personal info verification and registration links now stay valid for 72 hours instead of 24, giving people more time to act on the email before the link expires.

Contacts • CSV import no longer 500s

Importing contacts from a CSV used to throw a server error when groups were involved. The import handler has been corrected to match the leaf-only group schema and now imports cleanly.

Modals • Escape closes, page locks, no accidental dismiss

A shared modal system now powers most dialogs across Users, Items, Contacts, and the verify flow. Pressing Escape closes the open modal, the page underneath stops scrolling while a modal is open, and clicking outside the dialog no longer dismisses it — only the X, Cancel, or Escape close a modal. Behaviour is now consistent across the workspace.

Admin modal polish

Spacing, padding, and footer layout are now consistent across notice modals in the admin area, so add and edit dialogs frame their content the same way as the rest of the workspace.

Payroll • Users only export mode

The payroll export wizard now offers a Users only mode that exports the worker list without sessions — useful for syncing rosters into accounting without bringing time data along.

Users • Norwegian postal codes normalised to four digits

Norwegian postal codes are now padded to four digits everywhere (so a leading zero is no longer dropped on import or save), with a one-time backfill across existing user records.

Groups • mobile subgroups and contact picker

Subgroup rows lay out properly on mobile with a dimmed hierarchy arrow and stack as cards on narrow screens. The group contact picker is now a searchable typeahead instead of a long static dropdown.

Contracts • Upload signed contract no longer errors

Uploading a pre-signed contract PDF could fail with a 500 error on save. The upload now completes cleanly and the contract appears in the list as expected.

Contracts • auto-search list and cleaner uploaded actions

The contracts list filters as you type instead of waiting for a submit, large lists paginate at 50 per page, and uploaded signed contracts only show the actions that actually apply to them.

Documents • show all linked competence classes

When a document is linked to multiple competence classes, the documents list now shows all of them instead of only the first. Easier to spot at a glance which credentials are covered by which file.

Competence • multi-class certificates and verification

A major polish pass to the competence workflow: certificates can carry multiple classes per card, each class can be verified or rejected individually in the document viewer, valid-until dates and certificate numbers are required only when the certificate type calls for them, and category and class labels read more cleanly. Mobile rows and the review modal have been tightened so they fit phones properly.

Forms • organisation details for invoice workers

Registration forms now collect organisation details for invoice and organisation-paid workers under a clearer Organisasjonsdetaljer section, with smarter title handling that follows the account's default language.

Worker types • Dugnad / organisation worker

A fourth worker type has been added for volunteer and organisation-paid crew. Dugnad workers support an hourly rate without requiring personal bank account details, and flow through the import, schedule, and payroll surfaces like the other types.

Contracts • translated event log and preselected project

Event log entry types in the contract history are now translated, and creating a new contract preselects the account's standard project when the recipient has no default of their own.

Schedule • per-assignee shift export rows

Shift exports — list view, CSV, PDF, and the daily emails — now produce one row per (shift × assignee) and include the assigned worker's name, so a shift with three assignees is no longer collapsed into a single ambiguous row.

Incidents • mobile case layout

On mobile, the Quick actions band now sits on top of the Details panel, the meta block has tighter spacing, and Last updated has moved into the meta block where the rest of the case metadata lives.

Incidents • owner notifications and audit log

Owners are now notified by email when an incident is assigned, reassigned, cleared, has its status changed, or is closed. Every dispatch attempt is recorded in the case audit log so you can see exactly what was sent and when.

Incidents • PDF report download

Each incident case now has a Download PDF report action in the More menu, producing a printable case summary with the full event log.

Missing info • birth date check

The missing-info detector on the user profile now flags users without a date of birth, so gaps in worker records are easier to chase down.

Users • admin role limited to admins

Only account admins can grant or revoke the admin role. Managers can still manage their own group's users but can no longer escalate or demote admin-level access.

Users • separate title field

Workers now have a dedicated title field on their profile, separate from worker type. Imports, the user edit form, and registration forms all flow into it.

Phone numbers • international format on import and edit

Phone numbers are now normalised to international (+CC) format both on CSV import and when saving from the user edit form, with safeguards so a real local number that happens to start with country-code digits is no longer mangled.

User import • redesigned CSV flow

CSV user import has been rebuilt around a fuller template, a bulk default values panel, override-all + clear-value toggles, and a richer preview that surfaces birthday, address, and emergency contact fields. Header validation now suggests the closest match when a column is misspelled, the template covers every importable field via its config aliases, and rates of 0 are treated as empty cells. When a row has no project, the account default project is used.

Payroll export • pill nav inside Settings

The payroll export wizard moved into the Settings pill nav and dropped the per-step H1s, giving the wizard the same compact framing as the rest of Settings.

Outbound emails • correct language every time

Some transactional emails were rendering in the sender's UI language instead of the recipient's preferred language. Emails now always swap the translation table when a language is set explicitly, so workers receive their messages in their own language regardless of who triggered the send.

Design system uplift • Contracts and Incidents

Contracts and Incidents now follow the same layout, table, modal, and action-button patterns as the rest of the workspace. Mobile action rows wrap cleanly, the user access card stacks correctly, and modal footers no longer overflow on narrow screens.

Shared pill navigation across the workspace

Tabs, sub-filters, and section navs across Users, Incidents, Items, Contracts, Schedule, Settings, and Payroll now use one shared pill component. On mobile, narrow tab strips get a chevron scroll button, the active tab scrolls itself into view, and a fade indicates more options off-screen.

Schedule list view • instant assign and group changes

Assigning, unassigning, and changing the group on a shift in the schedule list view now updates in place via AJAX. No more full-page reloads after each tweak — the row updates and you keep your scroll position and any open filters.

Incidents • case workspace, owner, and priority

The incident detail page has been rebuilt as a single case workspace with one owner control, a priority field, and an anonymous-reporter fallback when no submitter is recorded. Closing an incident now goes through a confirm modal instead of a native browser dialog, and the Involved company row is always visible on the case so it's never hidden behind a toggle.

User shifts • cancelled assignments hidden

Cancelled shift assignments and cancelled sessions are now skipped on the per-user Shifts tab, so the list reflects what the worker actually has on their plate.

Schedule • stale shift link cleared on session edits

Editing a session's work status now clears any stale shift_id on linked sessions, so a session that's been re-categorised no longer claims an old scheduled shift.

reCAPTCHA • per-account toggles across all public surfaces

reCAPTCHA Enterprise can now be toggled per account on the public signup, registration forms, incident submission, password reset, and PIN reset surfaces. The /login page enables an adaptive challenge after repeated failed attempts. The server is the single decision point — clients fail open so a CAPTCHA outage never locks legitimate users out.

Settings • customer-editable billing address

Billing address is now editable directly from Settings → Billing. Changes update the next invoice automatically; no support request needed.

Bank accounts • country-aware Nordic + international handling

The payment details edit modal now has a country picker. Norwegian accounts auto-format as 4-2-rest, and Sweden, Denmark, and Finland get their own validation. Anything else is accepted as a free-text international account number. The Bank Review tab in Users surfaces accounts that are unset or set to OTHER for follow-up.

Contracts • company info pulled from account details

Contract templates now have shared global merge fields for the issuing company's legal name, organisation number, postal address, and bank account. They populate automatically from the account's details, so every contract carries consistent company info without per-template edits.

Contracts • 14-day default deadline and sender e-signature

New contracts default to a 14-day signing deadline, and the sender's electronic signature is now applied automatically on send (default on, can be disabled). Signed PDFs reflect the actual signer count in their wording.

Contracts • account-specific vs global templates

The template library now separates the account's own templates from the shared global templates, with search and an active/archived toggle on each list. Creating a new version can start from a global template instead of a blank document.

Items • per-user access grant on the access card

Managers can grant Items access to individual users from the access card on the user profile, without giving them broader admin or manager rights.

Items • concurrent-issuance cap per item

Each item can now define a max_quantity — the maximum number of concurrent issuances allowed. Once reached, the Issue modal blocks new issuances until something is returned. Useful for radios, harnesses, key sets, and any pool with a finite count.

Items • receipt-style emails and per-issuance identifiers

Issuance and return emails now render as a receipt with the item name as the hero, the per-issuance identifier and description, a localised timestamp, and one row per item. Single-item batches still show what was issued instead of collapsing into a generic message.

Items • statistics dashboard

A new Statistics tab on the Items module shows issued, returned, and outstanding counts by item, category, or month. Equal-height KPI cards highlight return-rate and active alerts; row highlights flag items with overdue or outstanding issuances; filters submit automatically as you adjust them.

Payroll export wizard with frozen-snapshot audit log

A new step-by-step payroll export builds a CSV per period with a frozen snapshot of every session, rate, and adjustment at export time. Past exports are kept in an audit log so you can always re-download exactly what was sent to the accountant — even if a session is later edited or cancelled.

Clockwork verify modal • richer prompt with snooze

The verify-document prompt at clock-in is now always-on (no per-account gate), supports a 24-hour snooze that lasts until the next clock-in, exposes an audit-logged SSN reveal, and chains directly into Items handout after verification.

Modals • explicit close, mobile-safe

Every modal in the workspace now closes only via the X / Cancel button or Escape — backdrop click no longer dismisses, so you don't lose data by tapping outside on mobile. Modal heights respect the dynamic viewport and safe-area insets so iOS and Android Chrome no longer clip content behind the URL bar.

Document review modal • unified preview and verification

The user document and competence review modals merged into one surface. Image preview supports zoom (single-click toggles, with cursor states for pan), rotation persists per attachment, and a drop zone replaces the old upload control. Actions adapt to the document's current state so you only see what applies.

Modules split • Items (Workforce) and Inventory (Ops)

Items belongs to the Workforce platform — operational issuance to crew. Inventory becomes the Ops platform — asset, stock, and equipment-pool management. The Inventory stub now self-labels as "coming soon (Ops)" and points to Items for crew handout. The sidebar has a segmented Workforce/Ops switcher to move between the two platforms.

Items module • catalog, issue, return, transfer

A new Items module tracks anything that gets issued to crew: radios, keys, vests, tablets, harnesses, cash floats. Catalog with categories and kits, multi-item issue modal, return + transfer flows on the Open page, full audit log per item, and per-user history. Wired into the Clockwork terminal so handout and return can happen at clock-in or clock-out.

Public shift signup • 5-minute reservation hold

When a worker selects a shift on a public signup link, the slot is held for 5 minutes while they finish the registration. Prevents the race where two people pick the same last seat at the same time.

Users • parent group shown when scoped to a subgroup

When a user belongs to a subgroup, their profile and lists now show the parent group name alongside the subgroup, so you can see their full org context at a glance.

Sessions • unified project resolver across all entry points

Manual session creation, terminal clock-in, and the new session_open() pipeline all use the same project resolution logic. The user's default project is applied consistently whether the session is started from a terminal, the manager's session create form, or the API.

Sidebar • Workforce and Ops platform switcher

The platform dropdown in the sidebar is now a segmented Workforce / Ops pill. One tap to swap between the two platforms; the visible module list updates to match.

Public marketing API • /api/public/pricing and /api/public/changelog

Pricing tiers (now Core, Pro, Enterprise — Basic was renamed to Core) and the published changelog are available as JSON at /api/public/pricing and /api/public/changelog. Both respond with proper ETag and 304 Not Modified handling, are stateless (no session, no cookies), and can be consumed by the marketing site or external integrators.

Platform status page • status.hrcluster.app

A public status page at status.hrcluster.app shows current uptime and recent incidents for the platform.

CSRF verification on public token pages

The public contract-signing page and the public missing-info request page now require a CSRF token tied to the page's one-time URL token. These pages are accessed via tokenised links without a login session, so they needed their own CSRF mechanism — matching the protection the rest of the app has had.

Reactivating a removed user preserves their worker type

When you re-add a user who had previously been removed, their prior worker type is restored automatically instead of defaulting back to Time only. Employees come back as employees, invoice workers come back as invoice workers.

CSV user import supports worker types

The user import CSV now accepts an optional worker_type column. Values: employee, invoice_worker, time_only. Common aliases are normalised — invoice / invoiced / contractor map to invoice_worker; sessions_only / volunteer / unpaid map to time_only. Blank values preserve the existing worker type on update, so bulk re-imports never downgrade users who were already categorised.

Missing-info card prompts for invoice details

When an invoice worker is missing their company name, org/VAT number, or invoice reference, the Missing profile information card on the user page now flags those fields alongside the usual contact/address/ICE items. The worker-facing request email uses the same secure link as before — no login required to fill in what's missing.

Invoice workers • supplier details on the user profile

Invoice workers now have a dedicated Invoice details section on the user profile: company name, org/VAT number, and invoice reference. These fields only appear for invoice workers — payroll employees keep their Payment details card, and time-only users see neither. Switching a worker from one type to another no longer wipes the previous type's data; bank account stays for employees, invoice details stay for invoice workers, in case you switch back.

Worker types • Employee, Invoice worker, Time only

Users can now be categorised as one of three worker types instead of the old Employee yes/no. Employees are payroll staff (rate + bank account apply). Invoice workers are paid by invoice (rate optional, no bank account collected). Time only covers volunteers and attendance-only crew. The existing Employee flag is kept in sync automatically, so existing reports and filters continue to work. Registration forms can also create users as any of the three types.

Missing-info dashboard flags workers without payment details

Employees without a payment_account are now surfaced on the missing-info view so they can be chased before payroll export. A one-off backfill ran to catch existing gaps.

Projects • session filter covers all days and all months

The sessions-per-project view now defaults to all days rather than just today, and adds an "All months" option so a project's full history is one click away. Also fixed a filter binding bug that could error on month selection.

Forms • default project, auto-group, ICE contact relation, approval fix

Registration forms can carry a default project onto new users. New signups are auto-added to the form's linked group. The in-case-of-emergency section has a relation field. Fixed the approval dropdown and payment write path.

Signup flow • approval emails, reliability, clearer copy

Approval confirmation emails now send after the admin approves a signup. The approve flow runs in its own transaction so a flaky email cannot leave the registration half-saved. Copy tightened, and the logged-in assign handler now respects the form's require-approval setting.

Schedule overview • inline assign picker

The assign action on the schedule overview now opens an inline picker directly, rather than a button that opens a picker. Quick-assign rows also align with the assignees indent for a cleaner layout.

Managers can now approve sessions

Session approval — previously admin-only — is now available to managers by default.

Tighter access control for Contracts and Incidents

Access to the Contracts and Incidents modules now requires an explicit permission. Admins — or managers who already hold the module access themselves — can grant it to other managers from the user detail page. Nav links, dashboard cards, user-detail tabs, and attachment downloads for these modules are hidden and blocked for users without access.

Approvals list • mobile checkbox layout

Checkboxes no longer overlap names on the Approvals list on small screens, and the first column's padding now matches the rest of the workspace card-table system.

Schedule • managers can intentionally overbook

Managers can now manually assign workers to a shift that's already at capacity, with a soft warning and an overcap badge on the shift. Useful when you want a backup or a swap without splitting the shift.

Public shift signup • race condition resolved

Two workers grabbing the last seat at the same instant could both succeed, putting the shift over capacity. The signup flow now uses a transactional lock, with regression harnesses to keep it that way. Past shifts no longer appear in the signup picker.

Privacy, terms, and cookie policy refresh

Our legal pages have been updated with clearer transparency for B2B customers: named primary hosting (Hetzner, Helsinki, Finland), a named subprocessor list (including our email and analytics providers), honest international transfer wording with Standard Contractual Clauses where applicable, GDPR legal basis per processing purpose, a stronger security section, and a concrete table of the cookies we actually set. Available in English, Norwegian, Swedish, and Danish.

HR Cluster AS organisation number on all legal pages

The HR Cluster AS Norwegian org. number (937 565 690) is now printed on the Terms, Privacy, and Cookies pages in every supported language, replacing the earlier placeholder.

Safer migration tooling for admins

The migration runner is now CLI-only — no one can trigger a schema change by hitting a URL. Platform admins get a read-only schema status view under Admin → System, plus a pending-migration banner so deploys never miss a step.

Clockwork QR codes reuse a live token per shift

The QR page now returns the existing valid token for a given account, user, and shift instead of minting a new one on every page load. Scanning an older printout keeps working until the token actually expires or is revoked.

Schedule assignee rows • cleaner, mobile-first layout

Expanded shift rows and the assigned-users card on the shift detail page now share one grid pattern: name anchored left, time and group aligned consistently, and actions grouped on the right. Mobile layouts stack cleanly without horizontal scroll.

Schedule assign modal • tighter layout and small bug fix

The assignee row in the shift schedule is a little denser on wide screens, and a stray undefined-variable warning that could appear in the assign modal during approvals has been cleaned up.

Group shift CSV/PDF export 500 error

Exporting group shifts to CSV or PDF no longer errors out. The group-scoping query was missing a join that the export paths needed.

Norwegian: Sessions section renamed to Økter

The Sessions section in the Norwegian UI is now labelled Økter, matching how users actually refer to it in the field.

Duration labels translated into all supported languages

Hour and minute abbreviations in shift and session durations now localise: t and min for Norwegian and Danish, h and min for Swedish, matching the UI language instead of forcing English h/m.

Unified email template for crewlist and group-shift exports

Crewlist and group-shift emails now flow through the same layout as the rest of the transactional email system, and the Norwegian locale is respected so recipient-language delivery works end to end.

Group-scoped visibility • no cross-group leaks

Managers scoped to a specific group now see only assignments that belong to that group: either an explicit per-assignment group, or the shift's default group when no override exists. An explicit override to another group no longer shows up under the shift's default group. Applied across the Shifts tab, per-group staffing counts, group-shift email, and CSV/PDF exports.

Multi-crew staffing • assign one shift across several groups

A single shift can now be staffed from different groups. The shift still has a default group, but each assignment carries its own group, so one shift can pull people from Bar, Drift, and Rigg without duplicating the shift. The per-assignment group is visible on the schedule, shift detail, and per-worker shift lists, and editable from an inline picker in the shared assign modal.

Manage button locks once a session is recorded

The Manage button on a shift now disables once a session is linked, preventing accidental edits to a shift that already has clocked time against it.

Consistent page title separator

Section hierarchy in page headings and browser titles now uses a single bullet (•) separator throughout the workspace.

Upcoming shifts on Me page

Date and time merged into one column, with a Group column added when the Groups module is enabled.

Cleaner shift and session list navigation

Shifts, Sessions, and Me lists now use a month-year picker and dotted date format. Multi-day spans show a (+N) day-offset suffix instead of repeating the date.

Email a group contact directly from Shifts and Sessions

Send an email straight to the group contact from the Shifts and Sessions tabs — no copy-pasting addresses.

Group Shifts tab with CSV and PDF export

Every group page now has a Shifts tab listing all shifts assigned to that group, with one-click export to CSV or PDF for crew briefings and printouts.

Dashboard Missing Contracts KPI aligned

The Missing Contracts KPI on the dashboard now uses the same definition as the Users + Groups views for a consistent count everywhere.

Missing Information promoted on user pages

The Missing Information card now sits above Personal on the user detail page, with softer amber styling for less visual noise.

User requests sent in the recipient's language

Update and information request emails now go out in the recipient's preferred language, not the language of the manager's UI.

Missing profile request form

Phone field now uses a country-code dropdown and the in-case-of-emergency contact name is split into first and last name.

Settings import • empty CSV templates per type

Download an empty CSV template for each import type, with the column delimiter matching your account preference.

Settings and Modules information architecture

Settings and Modules pages reorganised for clearer grouping and quicker access to common toggles.

Schedule overview rebuilt

Faster async loading, redesigned expanded row, a shared assign modal with Approvals, and a conflict guard that warns before double-booking.

Per-user contract requirement policy

Override the account-wide contract requirement on individual users — useful for volunteers, externals, or other exceptions.

Assign approvals to open shifts from a modal

Approve a clock-in and assign it to an open shift in the same step — no more navigating away from the Approvals queue.

User Shifts tab

Each user page now has a Shifts tab listing their upcoming shifts, with one-click reassign or unassign through a modal.

Day-before shift reminder

Optional automated email sent the evening before a worker's next shift. Toggle it on per account in Settings → Modules.

Unified transactional email system

All system emails (verifications, requests, reminders, approvals) now flow through a single sender with consistent templates, recipient-language delivery, and full delivery logging.

Account user created on form submission approval

Approving a public registration submission now properly creates the account_user record so the person can be scheduled and emailed immediately.

Public request form styling

Inputs on the no-login request pages render with proper spacing, stacked labels, and consistent card layout.

Hide empty competence categories

Categories with no registered competence and no types enabled for the account are no longer shown on user pages — less noise, clearer lists.

Cleaner user-request UX

Request update and Request information buttons now live in their natural headers and are replaced by a compact status line (Sent · Expires · Resend) after sending.

Upload evidence via self-service link

Workers who open a competence update link can now attach PDFs or images directly from the form, not just edit metadata.

User Documents tab

Every user now has a Documents tab listing all uploaded evidence — type, status, expiry, and a download link in one place.

Documents & credentials layer

Competence files now live in a canonical user_documents table with a many-to-many link to competencies. Each document carries a verification status and can be reused across multiple competence claims.

Dashboard and Clockwork auto-refresh

Dashboard KPIs and the Clockwork view now refresh automatically so you see current state without reloading.

No-login request links

Admins can send workers a secure tokenised link to fill in missing information or update competence — no login required. Links expire and are one-time.

Fixed 500 errors on shift creation and signup link creation

Resolved a bind_param type/count mismatch that was returning 500s on both shift creation and signup link creation paths.

Password reset works for users without a user_auth row

Users provisioned before the user_auth table existed can now request a password reset — the flow auto-creates the auth record on first reset.

Removed reCAPTCHA from public registration forms

Public registration no longer routes through reCAPTCHA. Submit handlers were hardened against silent failures as part of the cleanup so a missing third-party dependency cannot strand a submission.

Incident types and categories translated across all four languages

Incident type labels and category names are now available in Norwegian, Swedish, and Danish in addition to English.

Resend appears on contracts where one party has already signed

The Resend action is now available on partially-signed contracts, making it easier to nudge the remaining signer without opening a fresh agreement.

Contract template editor self-hosts Quill 1.3.7

Quill is now bundled rather than CDN-loaded — resolves a loading failure that could leave the template editor blank or non-editable.

Sender counter-signature, signed PDFs, and per-signer audit trail

Sender counter-signature is fully wired up. Signed PDFs include the per-signer audit trail and signature certificate, are attached to the fully-signed notification email, and contract emails carry the sending account's name.

Identity numbers encrypted end-to-end across the platform

Social-security numbers are now encrypted at rest with a per-user salt and account-scoped pepper. Revealing an ID number in the clockwork verify modal goes through a dedicated audit-logged endpoint — every reveal is attributable.

Technical focus: AES-256-GCM • Audit-logged reveal endpoint

Registration forms ship with separate workspace and terminal access toggles

Registration forms now have independent toggles for workspace access and terminal clock-in access. Terminal access is blocked by default on new forms — the more conservative posture.

Public signup provisions a full worker account in one submission

Public registration submissions create the account, send a welcome email containing the PIN and a set-password link, and enforce shift selection on shift-scoped signup links. Removes the manager round-trip for day-of-event onboarding.

Schedule module gains tab navigation, dedicated approvals, group-aware CSV import

Tab navigation surfaces a dedicated Approvals page; shifts now optionally carry a group; CSV import covers group_id and the full current schema. Brings the schedule module up to parity with the rest of the platform.

Live attendance and coverage on the workspace dashboard

Filled slots vs active slots is reported in real time on the workspace dashboard. Replaces the previous "log in to find out" model with operational visibility on landing.

Single background worker for email, automation, and maintenance jobs

Replaces feature-specific cron jobs with a unified worker that polls a shared queue. Stuck-job detection and per-run duration metrics make background work observable end-to-end through one operational surface.

Technical focus: Job queue • Worker coordination • Stuck-job detection

Daily 06:00 crew list and shift overview email per location

Each leaf location can be configured to send a 06:00 crew list and shift overview to its linked users every morning, in the recipient's preferred language.

Per-location crew lists with on-demand PDF, browser, or email export

Workers are linked to one or more leaf locations. Per-location crew lists are produced on demand as PDF, in-browser view, or email — in English, Norwegian, Swedish, or Danish.

PHP error logging enabled in production for faster diagnosis

PHP errors are now logged on production for operator debugging without ever surfacing them to end users.

Login page indexable; the rest of the app stays out of search

Login page is now indexable with a proper canonical URL and meta description. All other pages remain noindex by deliberate policy.

Admin logout now ends the session under the correct cookie path

Admin logout was leaving the session intact due to a cookie path mismatch. Resolved.

Fixed server error on password-reset submission

Hardened HTTP security headers across both web tiers

Permissions-Policy, stricter CSP, and the standard security header set are now enforced consistently at both Apache and Nginx. Eliminates a class of header drift between deployment topologies.

Technical focus: CSP • Permissions-Policy • Apache + Nginx

Dashboard layout polish • flush table edges, accurate shift counts

Cleaned up double borders, fixed shift-time display on the dashboard, and excluded admin-assigned shifts from the approval count.

Clockwork terminal • mobile tab bar, mandatory User ID, layout polish

Mobile tab bar redesigned, User ID is now mandatory on workspace clock-in/out, and form layout improved across screen sizes.

QR scanner returns rich error context and voids tokens after shift end

The scanner now shows worker and shift information on every result (success or error), exposes a Scan-next action, and voids QR codes after the shift completes.

QR shift emails redesigned with card layout and per-recipient language

QR shift emails now use a card layout with inline QR image and the worker's ID prominently shown — sent in each recipient's preferred language.

Compact short-URL QR codes for faster scanning

QR codes now use compact short URLs (/q/{token}) instead of fully-qualified links. Faster scans on cheap cameras; cleaner emails.

Schedule module rewritten • UI, filtering, assignment workflow

Full rewrite of the schedule module covering shift management, filtering, and the assignment flow.

Workspace settings split into dedicated pages

Settings now live on dedicated pages — general, clockwork, notifications, workforce — instead of one long form.

Failed login attempts are tracked and rate-limited

Failed logins are now logged and progressively rate-limited per identifier and per IP — a credible mitigation for credential stuffing.

Technical focus: Per-identifier and per-IP throttling

Tiered billing plans with per-plan feature gating

Starter, Pro, and Enterprise plans with explicit per-plan feature gating and account-subscription management.

Self-service password reset via tokenised email

Workers can reset their own password via a one-time tokenised email link — removes the manager round-trip for the most common credential issue.

Swedish and Danish translations across the platform

Full Swedish and Danish translations are in place across all modules, including competence type labels.

Competence module • certifications, licences, expiry tracking

Track worker certifications, licences, and qualifications with explicit expiry tracking and a verification workflow.

Signup links can route through multiple registration forms

Each form keeps independent field configuration and worker-type defaults — letting one signup link cover heterogeneous crew categories without separate landing pages.

Per-account currency for hourly rates and payroll export

QR-code clock-in for scheduled shifts

Scheduled shifts can generate and email QR codes. Workers scan to clock in or out — no PIN entry required.

HR Cluster v3 enters public beta

A complete platform rebuild — multi-tenant identity model, unified clockwork engine, mobile-first workspace. Feature parity with v2 plus the architectural runway for the operational tooling rolling out across this release.

Messaging module

Send messages to individual users, groups, or subgroups from the workspace.

Shift signup links

Create public links that allow crew to register and select available shifts.

Inventory module

Track equipment and manage checkout and return of items to crew members.

Locations module

Manage venues, areas, and physical locations within an account.

Cookie consent

GDPR-compliant cookie banner with category-based consent for essential, analytics, and marketing cookies.

Legal pages

Public terms of service, privacy policy, and cookie policy pages with support for four languages.

Account settings

General, workforce, and module settings are now separated into dedicated pages with a unified navigation.

Subscription and billing

View subscription details and request plan changes or cancellation from the workspace.

Module management

Enable or disable optional modules per account from the workspace settings.

Schedule module

Full shift scheduling with role support, user assignments, and no-show tracking.

Groups module

Groups rewritten with affiliation history tracking and support for parent-child group structures.

Registration forms

Create public registration forms with configurable fields and automatic group assignment.

Contracts module

Contracts can now be assigned to projects and groups, and pre-signed documents can be uploaded directly.

Incidents module

Incidents now capture geolocation on submission, company involved, and support categorised incident types.

User verification

Email verification is now required before a user can access the workspace, configurable per account.

Session isolation

Resolved session isolation issues between accounts/projects to prevent unintended logout and cross-project access conflicts.

Affiliation contact person

Support for contact person and contact information in the affiliation module.

Session validation

Sessions are now validated on every clock-in and clock-out outside the planned schedule. Both existing and newly created sessions are cross-checked against scheduled sessions, and scheduled sessions are revalidated against active sessions.

Scheduled sessions

Support for scheduled sessions in the clockwork module.

Parameter consistency

Improved internal consistency in parameter handling to reduce side effects in routing and export functionality.

Hashing stability

Stabilized hashing by enforcing valid cost values and preventing runtime failures.

Input handling hardening

Hardened input handling by deferring sanitization to output context and avoiding unsafe implicit casting.

PHP 8.1 compatibility

Updated Clockwork components to ensure full compatibility with PHP 8.1 and later versions.

2025

PHP 8.3

Platform upgraded to PHP 8.3.

2024
2023
2022
2021
2020
2019
2018