Target a package at departments, job types or named members
Shaped on SystemUserAccess. Adds the audience resolver to TeamMemberRepo, which was an empty interface; the ACTIVE + recordState predicate is what keeps termina...
Add the legal package template entities
A package is an ordered set of binders plus an audience. Binder references are soft ids because binders are user-deletable and cascade their items. The attestat...
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...
Add the Legal & Compliance design and the binder-scoping plan
The design is the full cross-repo analysis of the HR Legal & Compliance module (package templates, delivery, execution wizard, navtop badge, notification email)...
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...
Make the binder store aware of its collection
The store is a module singleton, so it now tracks the active scope, clears on a scope change, and drops stale in-flight responses.
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...
List and create binders within one collection
Scopes the visible-binder query to the DocManager's (assocType, assocObjectId), stamps the scope on create, inherits it on duplicate, and bumps last_modified fr...
Backfill the collection each existing binder belongs to
Derives the scope from the first DOC item's Img; empty binders fall back to the owner's My Docs. Applies NOT NULL only after the backfill.
Narrow binder visibility to one document collection
Replaces findVisibleToMember with a scoped variant and drops the two unreferenced finders that sorted by the dead date_updated column.
Give a binder the document collection it belongs to
Binders had no assoc scoping, so every DocManager rendered the same global per-member pool and a binder built under Marketing could be filled with HR documents....
Add a close button to the automated-imports manage dialog
The manage popup had no dismiss affordance in its header — only the backdrop and Esc closed it. Add an X icon button beside the edit action.
Group the meeting-invite fields by meaning when maximized
Splitting the form into equal halves used the wrong unit. It stretched a date input across half the window and stranded its All-day box at the far edge, left tw...
Rename the DocManager Organizer tab to Binders
The tab lists binders, so name it for what it holds. Points the tab label and the row action at the renamed dictionary keys (tabs.binders, addToBinder); the pic...
Tell a tool component when its window is maximized
Maximizing a tool window repaints the shell at 100vw/100vh but leaves the window's stored size untouched, and that stored size is what ToolDock hands the compon...
Keep fields on the page when a document opens at a remembered zoom
Reopening a document could draw every field small and up in the corner, until one click of the zoom control snapped them all into place. The page box that fiel...
Keep the quoted original out of the editable body
Replying dropped the whole quoted message into the Quill editor as body text. Quill can only model a simple grid, so every layout table in the quote was flatten...
Stop replies drawing a gridded copy of the quoted signature
Replying to a message sent from Kamo showed the signature twice: the live one, and above it a mangled version of the quoted original's, drawn as a bordered spre...
Pair the meeting-invite fields into two columns when maximized
The invite form stacks eight full-width rows, which in a maximized compose window pushed the body editor most of the way off screen while leaving half the windo...
Number pages against the document the reader gets
Modifiers were keyed off a page's index in the design, which is an identity that survives deletion and reordering, not a position. So deleting page 2 left the p...
Apply page operations and modifiers to the signed document
The designer has always offered page rotate, delete, reorder and add-blank, plus watermark, page-number and label modifiers, and the flatten read none of it: it...
Stop tracking build output
target/ was committed here, alone among the Java services — every other one ignores it. Compiled classes and surefire reports churn on every build and can only ...
Give every popup tool window 40px more room in both axes
Each tool's defaultSize and minSize in the registry grows by 40x40, and the geometry that was hardcoded alongside it moves with it rather than drifting out of a...
Load the number in the softphone without placing the call
Tapping an extension or a number on a correspondent card passed autoDial, so the call went out the moment the softphone registered. The card opens on hover, whi...
Give the card's readout labels room to breathe
The label column was a hand-picked 76px. DEPARTMENT is wider than that, so it overflowed its box and sat flush against its value with no gap, and LOCAL TIME wra...
Drag, cut, copy and paste recipient chips between To, Cc and Bcc
Moving someone from To to Bcc meant deleting the chip and typing the address again from memory. Chips are now selectable and can be dragged or carried on the cl...
Group an imported radio field's buttons natively
The buttons of one AcroForm radio field are imported as separate linked fields, one choice each, so each keeps its own box on the page. They were named after th...
Rotate the field overlay with the page, flag unread imports, order fields for reading
Three things that only start to matter once a document arrives carrying forty detected fields instead of two hand-placed ones. Page rotation: rotating a page t...
Paint the correspondent card in the tenant's brand colour
The card was tinted with --accent-comms, the fixed indigo the instrument panel uses to mark the messages family. On the solid "New message" button that reads as...
Stop dark-mode pastes landing as invisible text in the composer
Copying an answer out of ChatGPT (or any dark-themed page) and pasting it into the compose body produced a large white block with nothing in it, and the message...
Share the public join link, not the members-only redirect
A meeting link written into an email was pointing at /meet/join/<id>, which mints a one-time key from the clicker's Kamo session — and redirects anyone without ...
Read Acrobat format actions when detecting fillable fields
Acrobat stores a field's intended format as JavaScript in /AA, which pdf.js surfaces as actions.Format. That is the author's declaration rather than a guess off...
Insert a new meeting link at the coder from the composer
Adds a footer action to the compose window that creates a meeting with the organization's configured provider and writes its join link into the body wherever th...
Stop Hibernate mangling the "::" casts in the native SQL
Hibernate's native-query parser treats "::" as an escaped colon and forwards a single ":". CockroachDB received **************** ARRAY[]:text[]), ' ') and r...
Keep retrying the indexer's durable NATS consumer after a deploy
A rolling deploy overlaps pods and the outgoing one still holds the durable consumer, so the incoming pod's bind to "email-metadata-indexer" fails with [SUB-900...
Rebuild a fillable PDF's AcroForm fields as native Kamo fields
Opening an editable PDF in the document editor now reads its AcroForm widget annotations off the pdf.js document and recreates each one as a DesignField on the ...
Stop recipient names being clipped to a letter
The chips were inline-flex boxes whose label carried `truncate`. A flex child with overflow hidden is allowed to shrink below its own content, and nested inside...
Put per-file upload settings inline to halve card height
The Description/Folder/Doc Type/Access Level fields sat on a second line under the file row, so every pending upload cost ~108px. Move them into the top row bet...
Create the email search_vector column and its inverted index
**************** never existed. EmailService's own V1__email_metadata_schema.sql declares it, but that migration never ran -- the table came from this service's...
Adapt the metadata indexers to array-typed columns
Follows the kamo-shared-library change that maps conversations/search_index array columns as String[]/UUID[] rather than List<T>, which is what stopped every in...
Map the metadata array columns as Java arrays, not List
Both entities declared their array columns as List<T> under an explicit @JdbcTypeCode(SqlTypes.ARRAY). On Hibernate 6.2.13 that combination resolves the array's...
Drop the inset around the Resources document manager
DocManager brings its own toolbar and grid chrome, so the 32px wrapper padding was only shrinking the grid inside an already-bounded pane. The wrapper stays as ...
A contact card behind every name on a message
Every person shown in a read view was a dead end. To and Cc rendered as displayNameFor(a).join(', ') — a comma wall of display names with no address, no hover, ...
Bound the bulk folder index and stop it on structural failure
Uncommitted work from a concurrent session, swept in so the tree is clean. The bulk index walked pages with totalPages set to Integer.MAX_VALUE and no ceiling,...
Resolve the people behind the addresses on a message
A message header knows an address and whatever display name the sender chose to put beside it. The organization already knows far more — colleagues, address boo...
Show the full section-index rail instead of a nested scrollbar
The left nav rail was capped at calc(100vh - 128px) with overflowY: auto, so an org with most features enabled (up to 18 sections across 4 groups, ~710px) grew ...
Stop the passdb from splitting a mailbox across two maildirs
password_query returned `email as user`, which overwrote the %Lu-lowercased login name with the row's stored casing. user_query then interpolated %n from the re...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.