Commission links under My Account, tab reordered, duplicate headers removed
Nav and landing entries move under My Account rather than a separate section. The tabs live on that page, so that is where they belong; the reason I split them ...
Register the commission pages in the settings nav and landing page
The tabs existed but nothing linked to them. **************** is the cautionary example already in this repo: a real page with no card, no tab and no nav entry,...
Scope the opportunities read, and give the relay client timeouts
/me/opportunities called reservationRepository.findAll() and filtered org and member in Java. That pulls every reservation on the platform — every tenant's — in...
Make the atomic claims actually atomic, and stop starving the oldest payout
An adversarial review of the money path found the concurrency design was not running at all. @Modifying without @Transactional. Spring Data opens no transactio...
Send the status bucket as repeated params, not a CSV
Opening **************** errored with "Unknown status: **************** for every member. listMyAssignments sent the whole bucket as one CSV value. A comma in ...
Restore row positioning and make folders actually draggable
Two regressions from 8ab88d59. The message list grew a gap that widened with every row. This project builds Tailwind with `important: true`, so every utility o...
Accept repeated status params so the gateway cannot corrupt the filter
Opening **************** answered "Unknown status: **************** for every member. The member grid sent the bucket as one CSV value. A comma in a query valu...
Member commissions tab and the two finance account tabs
Member tab (self-only, team members only): balance + ledger, commissioned opportunities, payout setup, and withdrawals. Account settings gains Organization Stri...
Folders you can act on, mail you can select
Right-click any folder for its actions. The menu header is not chrome — it names the folder and shows its live unread/total, so Mark all read and Empty folder c...
Act on a whole folder, not just the page you scrolled
Mark all read and Empty folder are folder-wide operations the client cannot express by batching uids: it only ever holds the page it has scrolled, so a folder w...
Browser-facing relay for the commission feature
Resolves the session, authorizes, and relays to CommissionService with the org and member stamped from that session — never from anything the caller sent. This ...
Find a member's commission splits for their own commissions view
Org-scoped rather than keyed on the member alone: ORG_ID is duplicated onto this table so a row can never be read cross-tenant by id, and a finder that ignored ...
Make the member surface a real kamo data grid
The member's packages were a card list with no motion, which is not how the rest of kamo looks. This is now the house AG Grid: Pending and Completed sub-tabs sy...
Drop the Notes settings page and section
The Notes settings page was only a ComingSoonTab placeholder, so it gave members a nav entry and a landing card that led nowhere. Remove the route along with ev...
Server-side paging for the member assignment listing
The member surface asked for MAX_SIZE unconditionally and sliced the result in the browser, so a grid that showed a page had already downloaded a whole employme...
Personal Email Notifications card replaces the Notifications tab
Both switches move onto My Profile in the same shape as the password card: one card, an icon tile and help text per row, and a tinted inset that appears only wh...
Expose the user-account email on your own member profile
The profile's Personal Email Notifications card has to name the address missed-message notices actually reach, and that address is the user account's — not the ...
Send missed-message emails to the user account, not the org mailbox
The notice existed to say "you have a message waiting, sign in and read it", and it was being delivered to the mailbox this organization assigned the member — w...
Accounting & Finance permission group and finance-right access to account settings
The Access Security and Administration groups existed only in SecurityRoleManager as inline name lists, so JobTitleManager, DepartmentManager and RolesPermissio...
Migration for the commission ledger and Stripe payout tables
Mirrors com.kamo.z.shared.commission. ddl-auto would create these from the annotations anyway; the explicit DDL is the house convention and is what makes the sh...
Seed the finance rights onto every branch model's ADMINISTRATOR template
The three commission rights gate a feature that did not previously exist, so NEW_RIGHT_SEEDS deliberately says nothing about them - that mechanism carries an ex...
Team-member commission ledger and Stripe payout domain
Adds com.kamo.z.shared.commission: an append-only signed ledger, a per-member balance row that exists purely to serialize concurrent withdrawals, the Commission...
Re-point the doc manager tab at editedDocs
f98c5edc rebuilt its tree from a pre-8cb0a485 index and carried the old line back with it. `modifiedDocs` no longer exists in the dictionary, so main was callin...
Fold MFA into the password card and drop the Sign-in Security tab
Two places asked one question — how do I get into this account — so the second factor now lives beside the password on My Profile, in a card retitled "Password ...
The second doc manager tab reads Edited Docs
Points at the renamed key `docManager.tabs.editedDocs`; `modifiedDocs` is gone from the dictionary, so this has to move with it.
Never chase a member who already signed, and keep the subject plain
Two behavioural defects in the phase-8 notification path. 1. The reminder sweep ran over OPEN_STATES, which includes AWAITING_OTHERS — "this member finished...
Stop HTML-escaping the package title in the four HR subjects
EmailTemplateService renders a template's SUBJECT and BODY from ONE variable map, and all four canonical HR subjects carry {{packageTitle}} — which LegalNotific...
Suggest the org's own mailboxes, aliases and shared mailboxes
The recipient autocomplete only knew contacts and addresses scraped out of the Sent folder, so the organisation's own addresses — everything managed on ********...
One mailbox view, and a column that is all list
The Conversational/Classic toggle is gone and every member gets the classic list. Conversation view carried its own list, its own thread pane and its own API su...
Consolidate the member surface onto ?tab=legal-compliance
The standalone **************** route rendered the same component as the settings tab behind a second URL. Delete it and keep the tab: one surface, one entrance...
Expose contact email in the by-department roster
The Interaction Center needs a member's address to pre-fill a composer, and the only endpoint that carried one was the single-member detail fetch — one request ...
Email a member straight from their row
The row's action dock could chat, meet, dial and open a profile — the one thing it could not do was start an email, so reaching a colleague by mail meant leavin...
Extract the HR Legal & Compliance rendered key set
A literal t('…') scan misses 8 of the module's 81 keys: assignmentStatusKey and statusStateKey return key strings as DATA, and hrTabs.ts holds labelKey and desc...
Daily legal-package reminder tick
DaemonService owns the tick because DocsService cannot. DaemonService is strategy:Recreate — the old pod is gone before the new one starts, so a deploy window c...
Due-date reminder ladder and the batched, read-only sweep
The bucket is a pure function of (dueDate, today) and never of "when we last sent": UPCOMING_D{n} for the configured offsets, DUE_TODAY, then PAST_DUE_P{floor(d...
Tell the member — assigned, voided and completed
ONE hr.package_assigned per member per package, never one per document: that is what suppressInvite exists for, and 8 documents x 200 members is 1,600 envelopes...
Outbound email client and a Redis notification ledger
Idempotency with NO schema change. The reminder bucket is a pure function of (dueDate, today) and never of "when we last sent", so the only durable state a noti...
DocsService's first inbound internal-auth filter
DocsService has no service-to-service authentication: ResourceServerConfig is anyRequest().permitAll() and OTKPreAuthFilter CONTINUES the chain when X-OTK is ab...
Four canonical HR legal-package templates
hr.package_assigned, hr.package_reminder, hr.package_voided and hr.package_completed, as {json,html} pairs plus four CANONICAL_KEYS entries. The CONSTANT is no...
React to ASSIGNED and stop trusting a channel that cannot replay
Three ways the support badge went stale, all of them silent. ASSIGNED was published on /topic/support/agent/{memberId} and this handler only branched on PENDIN...
Give every agent a live badge instead of one owner an unread count
The nav badge and /support?tab=tickets answered different questions. The page lists every ticket in the org; the badge counted unread chat messages belonging to...
Stop the badge costing portal members a request a minute
Three things, all of them about who the count is for. THE PROVIDER GATES ON THE SAME CONDITION AS THE BUTTON. It mounts in the root layout for every authentica...
Drop client SENDs to guarded topics, and repair the build at HEAD
TWO THINGS, both of which stop MediaService main from shipping. 1. main does not compile. MediaController:1361 calls **************** which does not exist: ...
Let a failed pending-count read out instead of downgrading it
publishFor caught Exception around countByTeamMemberIdAndStatusIn and turned it into a WARN. That catch was not only around the badge: the query runs inside the...
Signature button with a live legal-package badge
Hand-written into the fixed left cluster between My Profile and Log out. NAV_REGISTRY cannot express a position between two fixed controls and its badgeKey fiel...
Live pending-package count over the EXISTING chat socket
LegalPackageCountContext consumes **************** rather than opening a fourteenth STOMP connection for one integer, and subscribes to **************** — the d...
Relay the legal-package count and guard per-member SUBSCRIBEs
legal.packages.> -> **************** core NATS, no stream — the same shape SupportStompRelayController and PlatformStompRelayController already use. topicFor is...
Proxy the member's pending-package count
A static segment sibling to [uid] so App Router matches it first. PATH ONLY — forwardToApi owns the query string — and one upstream call, because the OTK is sin...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.