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...
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...
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...
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...
Show a sent attachment without waiting for a reload
MediaService announced a new chat message twice — once when the row was saved, before any attachment existed, and once after the attachment rows committed. The ...
Announce a message once, when it is whole
Both callers that finish building a message after the row is saved now tell createMessage not to announce it: MediaController attaches the images and publishes ...
Let a caller own the realtime announcement of the message it is still building
createMessage announced every new message on the session's realtime subject the moment the row was saved — inside the caller's transaction, before the caller ha...
Lay the profile header's wallpaper chrome out in a row
The Source / Console / Tone pod was the Stage's stacked one, and stacked it is taller than the 100px avatar it sits beside — so it, not the identity block, set ...
Guard the destructive imaging paths and make the repair reachable
DELETE /imaging/delete/{imgId} is the one destructive imaging path and was not wired to the issued-document guard. ImageService.deleteDocument authorizes on org...
Restore the profile header wallpaper and wire its controls to the editor
The band behind the avatar on **************** had gone flat gradient. Not the wallpaper feature — ae85a8ae routed the header's photos through next/image + safe...
Sit the head tabs on the header's bottom edge and flatten the identity row
The tab strip was vertically centred in a row whose height was set by the action cluster beside it — a default-size More icon button (40px) plus the cluster's o...
Stop colleagues reading a member's HR-issued documents
isPerPartyRestrictedAssoc covers only ACCOUNT_MEMBER_VAULT and LOAN, so assoc 1 — SERVICE_APPLICATION, what /settings/member/{id}?tab=docs renders — has no per-...
Restore the files 2b23346 dropped, and answer an oversized send with 413
2b23346 was committed through a private index that was never seeded from HEAD, so its tree held only the three files staged into it and the commit deleted the o...
Store attachments through the dedup pipeline instead of one object per upload
Attachments wrote their own "<imgId>/<fileName>" object on every upload, bypassing the content-addressed store entirely — the same logo-draft.png attached three...
Stop capping every send at 1MB, so a pasted image can actually go out
Composing with a pasted image failed with a bare "Failed to send email". The composer inlines the paste into the body HTML as a base64 data URI, which rides in ...
Resolve the document bucket from ImageAssocType.BUCKET
DocumentService hardcoded "imaging-mydocs" while every other read path went through ImageAssocType.getBucket(). Now that storage is one bucket, point it at the ...
Store every image in one bucket so dedup means one copy
Association is metadata, not a storage boundary. Each ImageAssocType used to name its own MinIO bucket, which contradicted the hashing pipeline: dedup is scoped...
Wire DocsService to ESigService so Deliver stops 503ing
LegalEsignClient.isConfigured() was false in the cluster: neither internal.auth.secret nor legal.esig.service-url was supplied, so Deliver refused every package...
Put memberId on RecipientSummary, and stop the IP check DNS-resolving
A caller that acts on a recipient's status has to be able to establish WHOSE status it is. DocsService's legal-package Finish writes a WORM attestation on the s...
Prove WHOSE signature Finish counts, and report the live one
verify() compared the caller to assignment.teamMemberId but never to the ENVELOPE RECIPIENT's member — it trusted the recipientUid the delivery fan-out wrote. A...
Let a member actually finish a package, and reach the page at all
canFinish required every document row to already be SIGNED/ACKNOWLEDGED, but **************** is the ONLY writer of those statuses — the delivery worker writes ...
Drop the outer padding around the member Docs tab
DocManager brings its own toolbar and grid chrome, so the p:4 inset just shrank the grid and left a visible gap the /hr/resources page does not have. Matches th...
Copy a deduplicated document's objects into its own association bucket
Object storage is bucket-per-association (every reader resolves img.getAssocId().getBucket()), but deduplication is scoped ORG-wide or GLOBALly and so crosses a...
Cap the legal audience roster, and refresh after Deliver
The Assigned Packages grid filled its team-member filter column by asking audience-preview for allTeamMembers:true on mount -- a name and an email address for e...
Commit before the fan-out, and stop redeliver reissuing nothing
Redeliver published the new version row, flipped every OPEN assignment to SUPERSEDED, and submitted the reissue from inside that same uncommitted transaction. T...
Widen the read gate to match hrTabs.ts, make a cleared due date actually clear
LegalPackageAccess.requireRead demanded VIEW_EMPLOYEES alone while hrTabs.ts admits the Legal & Compliance tab on VIEW_EMPLOYEES || EDIT_EMPLOYEES || MANAGE_HRS...
Wire publish and audience preview, and stop rendering a broken label
publishPackage, previewAudience and getPackage shipped with no caller. The templates grid now has a Publish row action — disabled when the package has no binder...
Enforce HR rights and make the fingerprint see the e-sign design
All seven /api/docs/legal mappings authorized on org membership alone, so any authenticated member could list, edit, delete and publish legal packages — and aud...
Restore external images in email bodies
External images stopped rendering when the page-level image policy shipped. The middleware sets `img-src 'self' data: blob: https://theme.<apex> https://*.<apex...
Cap the send dialog's recipients at the template's declared slots
The Send for signature dialog seeds one recipient row and offers an unbounded "Add recipient", but it never fetched the template's signer slots. ESigService rej...
Let a send under-fill a template's signer slots, keep rejecting over-fill
The signer-count check added last round demanded an EXACT match against the template's declared slots, which would have silently stopped mortgage disclosures go...
Complete delegated envelopes, and reject a bad signer count before sending
envelopeComplete required a literal SIGNED from every recipient, but delegate() leaves the delegator DELEGATED forever and ADDS the replacement instead of subst...
Scope a decoder to the recipient who decoderd
Any single recipient declining set the whole envelope DEcoderD, so a counter-signer could destroy signatures the other parties had already given, with no recove...
Enforce required fields on the server, not just in the browser
submit() validated only consent and step-up; it accepted an empty values list and still marked the recipient SIGNED. Ports validation.ts (esign-core), including...
Bind every recipient to a template signer slot
No caller supplied signerUid, so recipients were created without one. buildSession filters a signer's fields by signerUid, so myFields came back empty, completi...
Drive the mail badge from pushed unread counts, not a 30s poll
MailButton ran setInterval(fetchUnreadCount, 30_000) in every open tab, and each tick called /api/email/folders — an endpoint that opens every folder in the mai...
Fail the run when a required UNIQUE index cannot be created
ensure() caught Exception and logged, so a failed CREATE UNIQUE INDEX reported success and the service booted with no uniqueness guarantee at all — the one outc...
Make the audience FKs and the attested wording actually hold
Five defects from the whole-branch review, all in the evidence path. The audience FKs did not cascade. cascade = CascadeType.DETACH is a persistence-context ca...
Enforce document/binder collection scope in addItem
BinderService.addItem checked read access and refused VAULT/LOAN documents, but never compared the document's own collection to the binder's, so a hand-crafted ...
Scope empty binders to (MY_DOCS, '') not the owner's member id
The My Docs DocManager never passes an assocObjectId prop, so it always resolves and queries (3, ''). BACKFILL_EMPTY_SQL was scoping empty binders to (3, member...
Guard loadBinders by request identity, not scope value
sameBinderScope alone can't tell two in-flight requests for the SAME scope apart (A -> B -> A), so a slower older request could still overwrite a newer one. Tra...
Show only the binders belonging to the open collection
OrganizerTab already received assocType/assocObjectId and passed them to the editor's document picker, but loaded the binder LIST unscoped — so every DocManager...
Correct javadoc on Hibernate ddl-auto behavior for NOT NULL columns
CockroachDB rejects ADD COLUMN ... NOT NULL without a DEFAULT on a populated table, so Hibernate's ddl-auto attempt fails (logged, non-fatal) rather than no-opp...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.