An audit trail for accounts, and a directory that includes non-staff
ACCOUNT_HISTORY records what happens to an account the way LEAD_HISTORY records what happens to a lead — deliberately the same columns, because the internal sit...
Confirm a clock in/out before writing the punch
The nav clock punched straight off the click. Every other control in that bar is idempotent or trivially undoable; a punch is a wage record that afterwards only...
One strip — filter and refresh beside the sub-tabs
The controls sat in a second full-width row under the tab strip holding three short words and an icon, spending a whole band of the pane on what fits in the spa...
Make the option strip yield the room instead of the clusters colliding
The left cluster carried minWidth: 0 while its contents (correctly) refuse to shrink or wrap, so a crowded bar shrank the box below its own content and the cont...
Segmented status filter in place of the select
Pending/Complete/All are three short peers that fit on one line, so a dropdown hid two of them behind a click and spent a label and a 170px well to say nothing....
Skeleton tracks the shared grid helpers; test jsonBody's 204 guard
The loading skeleton in app/hr/overview/page.tsx still hand-wrote the 1800px breakpoint that OverviewPillars and friends extracted into primitives.tsx (WIDE_BRE...
Follow the approval figure into currentPeriod, and stop null reading as zero
SecurityService 7c55054 moved awaitingApproval inside currentPeriod, where the window it describes actually is, and omits it entirely when there is no open peri...
Two-up figure rows so no card label wraps
The figure labels are Operator Labels — uppercase, 11px, 0.12em tracking — which puts "Execution incomplete" at 158px, "Blocking exceptions" at 150px and "Await...
Stop the fixed chrome labels breaking across two lines
A flex item's automatic minimum size is its min-content width, which for wrapping text is its widest word — so a crowded bar squeezed these controls narrow enou...
One snapshot per block, and figures that say what they measure
Both summarize methods are @Transactional(readOnly = true). Each issues six or seven reads whose figures are cross-checked ACROSS query boundaries: countOverdue...
An unreadable close-readiness body is unknown, and the approval count moves into its window
The wrong-path bug is fixed and the response shape is verified, but the CLASS of failure it belonged to was still open: if TimecardService renames `blocking`, d...
Fetch the summary slices' to-one associations and count instead of scanning
The Overview's attention and recent slices read a title per row off a LAZY @ManyToOne, costing up to 16 extra selects per block under open-session-in-view. All ...
One glow on the clock icon, not two around the button
The rule carried BOTH a radial-gradient and a box-shadow. The gradient filled its own box while the box-shadow painted a separate ring outside it — two concentr...
Slide a crowded nav instead of crushing its options
Pinning more options than a nav can show squeezed the tiles out of shape: both strips were raw overflow boxes and the tiles are flex children with no flex-shrin...
Locale-correct structured data, and a robots.txt rule that matched nothing
Every BreadcrumbJsonLd and ItemList URL was hardcoded to /en, so the structured data on /fr/terms told crawlers its breadcrumb parent was the English page — 19 ...
Line the card figures up on a shared baseline
Every figure on the masthead and the four pillar cards was its own stacked box — Operator Label above, value below. Operator Labels are uppercase with 0.12em tr...
Withheld approval state renders as not-tracked, not clear
attendanceState() marked every member 'clear' whenever blockingExceptions was 0 and timecardState wasn't 'SUBMITTED' — true for every member under a caller lack...
A failed close-readiness relay leaves awaitingApproval unknown, not a confident zero
With FINALIZE_PAY_PERIODS held, a 5xx/404/unparseable close-readiness response left awaitingApproval sitting at its initial 0 — the WARN log fired but the HR Ov...
Index the collection detail pages in 19 more languages
The sync finished, so the ~2,400 detail pages that were noindexed for having English body copy now have real translations and can be indexed. Measured across al...
AwaitingApproval is nullable, and null is not zero
SecurityService now withholds the approval half of the summary from a caller without FINALIZE_PAY_PERIODS — resolveRole never admitted MANAGE_TIMECARDS to appro...
Gate the approval half of hr-summary on FINALIZE_PAY_PERIODS
Pointing the composer at close-readiness widened privilege. That relay's own mapping guards with FINALIZE_PAY_PERIODS, and resolveRole does not admit MANAGE_TIM...
Honest compliance figure, per-section failed states, right gating
The masthead percentage mixed units and could only flatter. `complete` summed org-wide ASSIGNMENT counts while `open` counted MEMBER-DOMAINS off memberRows, cap...
Fill the per-member overdue rollup instead of sending zero
Both summary services built members[] with .overdue(0). The Overview's matrix branches on that field, so legal and training could only ever render amber or gree...
The attendance summary called a path that does not exist
summarize() asked TimecardService for **************** That is the name of the SecurityService MAPPING, not of any downstream route. TimecardService has no such...
Per-member overdue rollup for the compliance matrix
The HR Overview's matrix branches on `row.overdue > 0`, but the legal and training rollups shipped with that field hardcoded to 0 — a branch that could never be...
Derive overview pillar deep links from sub-tab id maps; kill dead textSecondary in activity rail
OverviewPillars.tsx hard-coded **************** instead of deriving them from **************** the way AttentionLedger.tsx already does — same name-indexed patt...
Build the Overview tab as a report over the other four
Full-width reporting console: masthead readout, four tab pillars, the needs-attention ledger, the workforce compliance matrix and an activity rail. Read-only — ...
Overview attention ledger, compliance matrix and activity rail
useMemberNames sources /api/security/members/names rather than the brief's guessed .../org-config shape: org-config never returns a member list (confirmed by re...
Strengthen hrOverview id-precision and attendance-state coverage
The precision test used a 15-digit memberId, which round-trips through Number() losslessly and never proved the join key stays a string. Switch to an id past Nu...
Overview data hook and shared visual primitives
useHrOverview fetches attendance + docs summaries with allSettled so one dead service degrades only its own sections; it skips fetches entirely for sections vis...
Bound the Resources block to count/sum/recent queries
**************** was loading the org's entire non-hidden HR_RESOURCE Img collection into memory to filter trashed, sum bytes and take 5 recent rows in Java — un...
Bounded count/sum/recent queries for one org+assoc live set
HrResourceSummaryService was materialising an org's entire non-hidden Img collection into memory to compute a count, a byte sum and a 5-row recent slice. Adds c...
Legal, training and resource summary for the HR Overview
One read per tab domain, each block gated on its own right and omitted rather than refused when out of reach.
Attendance summary for the HR Overview
One MANAGE_TIMECARDS-gated call composing the roster and manager-queue relays with the local exception, employment and pay-period rows.
Stop advertising ta as a translated alternate
Key coverage is not translation. TranslateService returns the source text when no provider supports a direction — ProviderRouter logs "No provider supports en->...
Localize the hub cards and stop bundling the English datasets
The four hub pages rendered client components that imported the collection modules directly and took no props, so every card — industry names, integration tagli...
Summary queries for the HR Overview
Status histograms, overdue slices and per-member rollups for legal and training, plus template/course status counts. No entity change.
Stop leaking an IMAP IDLE connection on every browser reconnect
Interrupting the IDLE thread cannot end an IDLE: it is parked in a blocking socket read that only sees the flag once the read returns on its own, up to Dovecot'...
Glow red when off the clock, green when on, and drop the bullet
Being off the clock while at work is the state that costs someone money, and it was the one state nothing announced: the indicator was simply absent, and an abs...
An Enrollment tab, and hide the member Timecard tab when not enrolled
There was no way to turn timecards on for anyone. Every read surface existed and every one of them correctly showed nothing, because no enrollment could be crea...
Relay enrollment
MANAGE_TIMECARDS to read or change who is on timecards — enrollment decides who gets paid from this system, so it is held to the HR administrator right rather t...
Translate the collection pages instead of hiding them
The 2,400 noindexed detail pages were noindexed because their body copy has no translation: competitors, industries, integrations and glossary keep their prose ...
Stop canonicalizing 21 translated locales into English
Every non-English page carried a hardcoded canonical to its /en twin — `export const metadata` is module-level, so it could not vary by locale and 28 pages ship...
The Approvals and Exceptions tabs actually exist now
Both backends shipped earlier but neither panel was ever written, so /hr/attendance?sub=approvals and ?sub=exceptions rendered "this tab is being built" over wo...
Relay the exception queue
MANAGE_TIMECARDS to read the queue and to waive, because the queue names every member with a problem and waiving changes what the finalize gate reads. The per-m...
The partial indexes that stop a double payment and a code collision
**************** is the teeth behind the export service's refusal to re-issue. A second committed file for one pay period double-pays an entire company, and the...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.