A kind for the meeting that is about to start
MEETING_REMINDER, so MediaService can raise the start-time nudge as a notification instead of a popup only it knows about. Its own kind rather than CALENDAR_EV...
Delete the three chat-channel rights — 196
CREATE_CHANNELS (74), MANAGE_CHANNELS (75) and MODERATE_CHAT (76) gated nothing and could not be implemented as written: chat is real but the platform has no ch...
Scope notes to a membership instead of an account
A note hung off USER_ID alone and carried no organisation at all. A user is global and a member is that user inside one organisation, so an account belonging to...
One table for the three layers of the event-sound stack
Platform defaults, an organization's overrides and a member's own are the same shape, so they are the same table: a scope, the id that scope is about, and the s...
Parent/child hierarchy for all 199 rights
RoleRightType has declared a 'parent' field and a public getParent() for years. Every constant passed null and nothing ever called it. This finishes that scaffo...
A note records whether it is rich text or plain text
The mode cannot be derived from the content. A rich note the member has not formatted yet serializes byte-for-byte identically to a plain one — both are a Lexic...
Org-level default legal text
LegalSettings is one row per organization carrying the wording a NEW legal package starts with. It is a DEFAULT, never a live reference: creating a package copi...
Let the history be queried by specification
The browsable history filters by kind and by whether a notification has been read, and those combine freely — which as JPQL is a query per combination, or one q...
Stop an omitted date window failing every event lookup
The calendar page could never list anything. It asks for every event a member has, with no window, and these queries took the range as nullable and tested it wi...
Pending callbacks for a whole organisation in one query
Feeds the leads list's per-row callback marker. The grid holds every lead the member can see, so asking per lead would be a request per row to render one column...
Member notification centre, and an event's origin
Adds MemberNotification and MemberNotificationPreference: one row per member per notification, because read, dismissed and snoozed are per-person answers and a ...
Map is_answered, now that the column exists
KamoInitializer added **************** on 2026-08-13 **************** verified in Yugabyte: boolean, default false, no nulls). Mapping it is safe now and was no...
Unmap is_answered until its migration has run
Mapping the column ahead of the migration that creates it is armed, and I armed it. SearchIndexEntity is hydrated from fullTextSearch, which is a native SELECT ...
Record whether a message was replied to in the mail index
email_metadata.search_index has carried is_read and is_starred since it was created but never the third IMAP flag, \Answered. That was harmless while the index ...
Bind the system-event pattern — a brace in native SQL never reaches the database
Hibernate scans native SQL text for its legacy {alias.path} placeholders, so the inlined '{"systemEvent"%' raised QueryException: Unmatched braces for alias pat...
ADP takes per-org credentials, not a platform registration
ADP shipped classified PLATFORM_OAUTH on the strength of ADP publishing a Marketplace ISV model, where Kamo would hold one partner client id, secret and certifi...
One definition of an unread support conversation
The navtop badge and the ticket list have twice drifted apart by answering different questions. findUnreadStateForViewer is the single answer both now read, so ...
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...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.