Thread the parent department through create and update
DepartmentService now takes its request DTO instead of eight positional arguments, so the parent joins the payload rather than becoming a ninth in a row of same...
Draw departments as an org chart with a parent picker
The departments tab was a flat list, so an org with Operations > Customer Success > Onboarding had no way to say so and no way to see it. Add/edit gets a Paren...
Let a department sit under a parent department
Departments were a flat list, so an org chart with Operations > Customer Success > Onboarding had no way to say so. Department gains an optional self-referencin...
Grow the To/Cc/Bcc fields to three rows, then scroll
The recipient fields in the compose tool window were a single nowrap row that had to be dragged sideways to read, and the window is 360px wide and not resizable...
Stop losing organizations to swallowed exceptions, and accept the full create payload
createOrganization could destroy a customer's signup and report nothing useful. Transaction integrity: - Five Docstors ran behind try/catch that only looked sa...
Make org creation survivable, and offer every branding option up front
The wizard could fail a customer in ways nothing on screen explained, and it asked for a fraction of what Settings → Behavior & Labeling exposes. Creation reli...
Encode the decoded token exactly once on the way upstream
21670e5 routed SocialWebhookController through UpstreamUri's FULLY-PRE-ENCODED entry point, but its URL is a hybrid: `token` is an @PathVariable, so Spring hand...
Make the create-account form tell you what happened
Creating an account from a lead appeared to do nothing. The server was returning a 500 (see the AccountAddress fix in kamo-shared-library), but the only error U...
Make the create-account form tell you what happened
Creating an account from a lead appeared to do nothing. The server was returning a 500 (see the AccountAddress fix in kamo-shared-library), but the only error U...
Make account creation atomic, org-scoped and rights-gated
createCustomer saved the Account before writing its addresses, and was not transactional — so when the address insert failed, the half-built Account stayed comm...
Keep the right-click menus inside the viewport
Right-clicking a folder low in the sidebar opened its menu below the fold. The flip-at-the-edge logic was there but never ran: the component returns null until ...
Stamp AccountAddress dates so an address can actually be saved
DATE_CREATED is NOT NULL with a DEFAULT now(), but nothing ever set the field. Hibernate names every insertable column in its INSERT, so it sent an explicit NUL...
Forward the caller's query bytes on the public-facing proxies
The gateway stopped double-encoding forwarded query strings in 3c24d32, but four other proxies in this service still concatenated already-percent-encoded bytes ...
Send the editor's back button where the member came from
The wallpaper editor was a dead end — no way out but the nav rail. Both entry points (the home top-bar chip and the member profile header shortcut) now stamp th...
Stop a menu click on an open settings page from bouncing back, and repair the dead tab links
Clicking Apps & Features (or Stats & Costs) while /settings/account was already open landed on the tab you came from. Next.js swaps the query string without rem...
Show a primary mailbox under its member's profile name
A mailbox held as somebody's primary is that person's address, so suggesting it as "Sales Desk" — whatever it happened to be labelled when it was provisioned — ...
Name a primary mailbox after the member who holds it
A mailbox someone holds as their primary is that person's address, so presenting it under whatever the mailbox was labelled at provisioning time — "Sales Desk" ...
Stop the tab content overflowing and touching the walls
Two causes, both mine. No padding. TabPanel deliberately supplies none — every tab pads itself, and I had not. The shell now uses p:{xs:3,md:4}, matching MyAcc...
Float the label off the placeholder on name prefix/suffix selects
MUI derives InputLabel shrink from `filled || focused || adornedStart`, and `isFilled({value: ''})` is false. Any select that still paints something while empty...
Send the timeline provider filter as repeated params, not a CSV
socialTimelineApi.timeline set providers to a joined CSV. A comma in a query VALUE travels as %2C, and any hop that re-encodes turns that into %252C — APIServic...
Accept the timeline provider filter as repeated params
The web client sent ?providers=facebook,x as one CSV value. A comma in a query VALUE has to travel as %2C, and a hop that re-encodes turns that into %252C; we d...
Forward the caller's query bytes instead of encoding them twice
Every URL this gateway builds is assembled from getRequestURI() and getQueryString() — both already percent-encoded — and was then handed to RestTemplate as a S...
Ask before any bulk action, not just the folder ones
Emptying and deleting a folder already confirmed. Everything else that moves mail or rewrites its read state did not — it ran the moment the icon was hit. The s...
Stop money fields loading a value that fails their own validation
The API stores money as NUMERIC(19,4) and serialises it with toPlainString(), so the shipped $50.00 minimum withdrawal arrived as "50.0000". Both money inputs a...
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.
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.