Download the executed document, and choose a real signing order
The sender had no route to the finished document at all. EnvelopeSummary advertised a signedDocumentUrl pointing inside the kamo-signer app's own BFF, authentic...
Keep co-borrowers on one routing order
deriveSigners numbered borrowers 1, 2, 3… as a display index. ESigService now ENFORCES routing order instead of merely reporting it, so leaving the counter in p...
Close out the signing lifecycle — notices, routing, guards, expiry
Everything after a signer presses Finish was incomplete. Notices: an envelope's last signature produced a flattened PDF in MinIO that only the final signer eve...
Preview variables for the e-signature templates
The admin template editor renders every placeholder blank for a key with no sampleVariables arm, so the seven esign templates previewed as a page of empty gaps ...
The five envelope-lifecycle email templates that were never written
An e-signature envelope had exactly two templates: the invite and the step-up code. Nothing existed for anything that happens AFTER a signer signs — which is wh...
Rebuild the mortgage market settings into seven coherent tabs
The MORTGAGE market page carried fifteen tabs, twelve of them lender config, and several answered the same question in two places: hedging was switched on under...
Pick the From address from a searchable dialog, not a dropdown
A select cannot hold this list. Everything the /messages switcher offers is sendable, and for a member with ACCESS_ALL_MEMBER_MAILBOXES that is every mailbox in...
Searchable, paged endpoint for the addresses a member can send from
GET /api/email/mailboxes/sendable answers the same question as /accessible — every address the member may send as — but as one merged stream that is searched an...
Match the TypeScript DTOs to the Java ones they proxy
/api/webinar/* is a passthrough, so every TS field name that drifted from the Java DTO silently read as undefined instead of failing to compile. The settings ta...
GET /types/{typeId}/slots so the settings editor can list slots
The settings UI has always fetched this path, but only POST/PUT/DELETE were mapped, so the Availability Slots tab got a 405 and rendered empty. Unlike /slots/av...
Record the compatibility bridge and what retires it
The bridge is invisible from the code that will eventually delete it -- the field looks like a real part of the request. Name the condition that ends it: Securi...
Assign a mailbox to a department and to the organization
The department dialog's contact email was free text, so it could name an address the org does not own. It becomes a picker over the org's real mailboxes -- the ...
Mailbox pointers for departments and orgs, and backfill the departments
DEPTS.MAILBOX_ID and ORGS.CONTACT_MAILBOX_ID, both plain UUID with no FK to email_provider.mailboxes: mailboxes sync from external providers and can be removed ...
Populate the Quick Tips and use the shared help primitives
The scheduled-support tips rendered four placeholder strings ("How Step1"…); replace them with real guidance covering the type → presenters → slots → reminders ...
Compose from the mailbox you have open, and offer every one you can access
New Message opened the composer on the member's default mailbox: only onBehalfOf was passed, and only for another member's mailbox, so a personal or shared mail...
Let a department and an org point at one of their mailboxes
A department's contact email was free text, so it could name an address the org does not own -- two of the three departments with one set today do exactly that....
A Manager field on Position, and one people picker for the whole app
The Position card gains Manager, optional. It is a search, not a dropdown: an org can hold thousands of names, and the only thing a select with all of them guar...
Set a manager, and search the directory a page at a time
GET **************** answers one page of the session org's directory. Search, ordering and paging happen in the database; a hostile ?size= is capped. Words are ...
A manager, and a directory search that survives a big org
TeamMember gains an optional self-reference for who it reports to. columnDefinition is pinned to INT8 so Hibernate cannot copy Member.ID's DEFAULT unique_rowid(...
Give a team member a manager
Adds MANAGER_ID to member_team_member, a nullable self-reference for the reporting line. Nothing is backfilled: no manager is a complete answer, both at the top...
Add DEPTS.PARENT_DEPT_ID for nested departments
Nullable with no backfill -- null means top level, which is what every existing department was and most will stay. Declared plain UUID with an explicit DROP DE...
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...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.