Carry whether a ticket is one of the items the support badge counts
The navtop badge and the ticket list were answering different questions and nobody could tell. The badge counts items awaiting attention — overwhelmingly ticket...
The payroll-provider domain behind the timecard engine
Adds the persistence spine for connecting an organization's timecards to a third-party payroll system: the connection and its encrypted per-org config, the OAut...
Count unseen messages for a viewer who is not in the conversation
Unread has always been derived from the viewer's own MediaSessionMember row, so a conversation they had not joined produced no count at all. On a support queue ...
A punch can be voided without being deleted
Four nullable columns and a second write-once transition on TimecardPunch. A void says the punch should never have existed — a double tap on the clock, an aband...
Quote the feed queries' aliases, and stop counting your own support messages against you
Two independent defects in the Chats feed, both invisible from the Java side. The native chat/support/social queries aliased columns in camelCase without quoti...
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...
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 ...
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...
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...
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.
Org configuration, holiday calendars and schedules
TimecardOrgConfig holds the workweek, workday boundary, rounding, rule-set pointers and the review switches. Nothing in it is read at calculation time — every v...
Carry the adjustment reason on the punch itself
A corrected or inserted time now records WHY on the wage record rather than only in the audit log. Under Anderson v. Mt. Clemens Pottery an employer with inadeq...
Add the meal start deadline to the break rule
California requires the first meal to BEGIN before the end of the fifth hour. A 30-minute meal taken at hour seven is a full violation even though it was the ri...
Pay periods, breaks, premiums, labor accounts, accruals, export
Batches the remaining wage-and-hour schema into one shared-lib change so the whole domain lands in a single KamoInitializer run rather than a migration per phas...
Exception model and detector
Makes the blockingExceptions gate real. Until now the transition table read a count that nothing wrote, so every timecard looked clean and 'a missing punch is n...
APPROVE_TIMECARD_ADJUSTMENTS (197) and FINALIZE_PAY_PERIODS (198)
Split so separation of duties is expressible: whoever approves a timecard is not automatically whoever may close a pay period over it. MANAGE_TIMECARDS (183) st...
The approval tier state machine
Employee submits -> manager approves -> payroll closes, per the owner's decision. Four rules, enforced in a pure transition table and pinned by 25 tests: 1. A...
Database-clock accessor on the punch repository
Every punch instant comes from the DB, never the JVM: pods restart and node clocks skew, and a wage record whose ordering depends on which pod answered is not a...
Workday bucketing, stage 2 of the pipeline
Resolved intervals become per-business-date seconds, ready for the allocator. An interval is SPLIT at every workday boundary it crosses: a 22:00-06:00 shift un...
Workweek and workday boundaries
The workweek is the FLSA overtime unit -- a fixed, regularly recurring 168-hour period -- and it is NOT the pay period. A biweekly period holds exactly two work...
Interval resolution, stage 1 of the calculation pipeline
Punches become resolved spans. Pure, total, and over value types rather than entities so every stage is fixture-testable with no persistence context. Durations...
Non-pyramiding overtime allocator with jurisdiction presets
Rules are DATA on the RequirementRule shape already used in this library, not code branches, so California is a configuration row instead of a rewrite. Allocat...
WorkSite, the jurisdiction anchor
Named WorkSite, not WorkLocation: TeamMember.workLocation is an existing office/remote enum and a second symbol by that name would collide in every grep. zoneI...
Employment and effective-dated assignment revisions
Punches will reference an ASSIGNMENT, not a member. That is what makes concurrent positions, the 29 CFR 778.115 weighted-average regular rate, multi-site jurisd...
Effective-dated, append-only pay rate
No employee compensation existed anywhere on this platform before this entity. It is required: overtime is computed against the FLSA regular rate, CA requires t...
Append-only punch log and audit event
Both served by NARROW Repository interfaces, not JpaRepository: deleteAllInBatch and bulk JPQL bypass entity callbacks, so the interface shape is what makes app...
Timezone-of-record resolver
Authority order work site -> member -> org -> UTC. The work site wins because wage-and-hour rules follow where the work is PERFORMED. A production census this ...
Shared WORM refusal guard
@Column(updatable=false) does NOT enforce immutability -- Hibernate silently omits the column from the UPDATE and the stale write looks like it succeeded. The o...
Domain enums and point-in-time version resolver
Enums are all @Enumerated(STRING) at the call site: ORDINAL emits a numeric range CHECK containing AND, which SchemaCleanupRunner's IN-list sweep deliberately s...
Let a billing group be its own payer
A group could be named and nothing else. Its subscription was never set — nothing in the platform called setSubscription — so subscription_uid stayed null forev...
The four training email templates
Same constant/dotted-key split as the HR legal family: the CONSTANT is the filename stem, the templateKey the platform SENDS is the dotted value inside each .js...
Stream document uploads and add the HR Training schema
ImageService gains uploadDocumentStreaming, the streaming counterpart of uploadDocument. The buffered form cannot express a large upload at all: readInputStream...
Recreate a durable consumer whose stored filter no longer matches
A durable JetStream consumer keeps the filter subject it was created with for the life of the stream. When the owning code later changes that subject, jnats ref...
Stop the pay-group entity sitting on a legacy table
BillingGroup was mapped to billing_groups. That table already existed — one of a seven-table subsystem (billing_group_members, _subscriptions, _licenses, _invoi...
Never let the quota service stop a service from starting
StorageQuotaService took its five repositories as required constructor arguments. Services in this estate component-scan com.kamo with a wildcard but declare an...
Pin how the pool divides into per-mailbox limits
Dovecot needs a byte figure per mailbox, but storage is one organization-wide pool across eighteen domains. The division has to hold one property above all — th...
Make a failed payment mean something
PAST_DUE counted as fully live in both entitlement resolvers, with no timestamp and no cap, so a customer whose card failed kept every feature for as long as St...
Pin the delegation-mode semantics
These predicates are what the surfaces hide themselves on, so getting one wrong either offers a button that cannot work or silently permits a charge the owner m...
Let members and groups pay for themselves, under the owner's rules
Three things were missing and one was actively harmful. account_members carried a global unique on member_id — a member could administer exactly ONE billing ac...
Show what turning off fail-open would cost
kamo.entitlement.fail-open grants any app the plan matrix never mentions. It is documented as a temporary valve for the catalog backfill — turn it off once the ...
Opt-in auto-expand with a ceiling
Two columns on the subscription that holds the blocks: whether to buy another one automatically when the organization runs out of room, and the most it may ever...
Record what each Stripe price was created with
The mapping stored only which price id to use, so a catalog price change could not even be noticed. ensurePlanPrices short-circuited on the row's existence and ...
Give the storage allowance an effect
Storage was measured across nineteen domains, nightly, with a build-failing coverage test — and nothing anywhere computed an allowance or refused a byte. The pl...
Give add-ons a unit size and a purchasable quantity
An add-on's unit only ever existed as prose inside its description ("Each unit adds 25 GB") and as a hardcoded constant in the marketing site, so nothing could ...
Durable record of a conversation the client raised by itself
MediaSessionMember gains AUTO_OPENED_AT, beside msgIdLastViewed because it is the same grain — a fact about one member's relationship to one session. That one a...
Restore the CRLF endings on the attendee repository
The previous commit rewrote the file through a script that normalised its line endings, so a twelve-line addition arrived as a fifty-line rewrite. That buries t...
Batched guest lookup, and delete-by-event
The event dialog shows who an event is with, and the list endpoint returns a month of events at a time. Asking for guests per event is a query per row; findByEv...
AUTO_ASSIGNMENT strategy and a durable record of an unseen handover
AUTO_ASSIGNMENT(3) is appended to SupportAssignmentStrategyType — assign immediately to an agent who is genuinely online, preferring whoever holds the least wor...
Record when an account was created
Account carried no creation timestamp at all — not a null column, no column. The account list has a Date Created column and orders by it, so that column has bee...
Geolite range index must be ASC, not YugabyteDB's default HASH
The IP lookup is a range scan: WHERE network_start <= ? ORDER BY network_start DESC LIMIT 1 YugabyteDB partitions the LEADING index column by HASH unless tol...
Like what you see shipping?
All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.
