Route all esig API calls through forwardToApi() to fix save failures
All 10 esig route handlers were pointing to ESIG_SERVICE_URL which resolves to a non-existent kamowsesig-service proxy. Replace every handler with forwardToApi(...
Replace upsertSigners with full delete+insert to handle frontend temp UUIDs
The frontend assigns temporary crypto.randomUUID() values to newly-added signers before any backend call. The previous upsert-by-uid logic would throw 404 for t...
Add /api/esig/** gateway routing to ESigService
Route all /api/esig/** requests through the existing API gateway to the dedicated ESigService (kamowsesig-service) instead of the non-existent proxy target. Add...
Add layer position option to Watermark modifier (behind / above content)
- WatermarkModifier gains a 'layer' field: 'behind' | 'above' (defaults to 'behind') - ModifierLayer now takes a 'pass' prop ('below' | 'above'): - below pass...
Add Watermark modifier to esign toolbox
- WatermarkModifier type: logoType (full/simple), startPage, endPage, rotation (−180–180), size (10–90% of page width), opacity (2–60%), solidColor toggle, colo...
Extend Label modifier to full 8-position grid with LM/RM rotation
- LabelModifier.position now uses ModifierPosition8 (same 8-position grid as Page Numbers) - LM (Middle Left): each line rendered as a vertical pill with writin...
Add Tools/Modifiers tabs to esign Toolbox with live canvas overlays
- Split Toolbox left sidebar into Tools and Modifiers tabs - Modifiers tab: split list + settings panel (Option B) - Page Numbers modifier: start/end page, 8-...
Switch preview-banner-text to inline flow so changelog link sits on the same line
Correct rotated thumbnail positioning and restore rotation transform
Two bugs in ThumbnailCanvas: 1. Replaced `height: \`${displayAspect * 100}%\`` (percentage height on abs- positioned element — unreliable when containing bl...
Show today's changelog count in preview banner with link to /changelog
Fix floating zoom control visibility and polish thumbnail placeholders
- Move floating zoom controls outside the scroll container and use position:absolute so they remain visible at all times regardless of scroll position; offs...
Page selection with animated glow border synced between canvas and thumbnail sidebar
- DesignTab holds selectedPageIndex as the single source of truth - Clicking any page in the main canvas selects it (onPageSelect) - Clicking a thumbnail select...
Move scroll ownership from PdfCanvas to canvasContainerRef
PdfCanvas root Box previously had overflow-auto + h-full, making it its own scroll container. This meant: - scrollbarGutter: stable on canvasContainerRef had no...
Fit to Width calculates actual container width instead of resetting to zoom 1
Reads **************** (which accounts for the stable scrollbar gutter) and the page's natural width via **************** then computes fitZoom = (availableWidt...
Replace all hardcoded purple with var(--color-primary) on Settings & Signers page
Signers icon, icon background, count badge, Add Signer buttons, Add First Signer button, empty-state illustration tint, add-another hover, and the ALL_OF_TYPE s...
Auto-select first signer, fix zoom control scrollbar gap, animate properties panel
- Toolbox auto-selects the first signer's UID when signers go from 0→1 - Canvas container uses scrollbar-gutter: stable so the sticky zoom/undo control mainta...
Reorder tabs, gate field tools by signer, redesign Settings & Signers tab
- Design is now the first tab; Settings & Signers is second - Toolbox shows "Add Signer" CTA (navigates to Settings) when no signers exist - Signature Tools, Id...
Render field controls as actual-looking form elements with signer color tinting
Each field type now renders a visual representation of the real control (text input, checkbox, toggle, dropdown, radio group, date picker, etc.) tinted with the...
Remove fixed height and scroll bars from field properties panel
The panel had two vertical scrollbars: 1. DesignTab wrapper had height: 200 + overflowY: auto 2. FieldPropertiesPanel root had height: 200 + overflow: hidden, ...
Defer setTotalPages until after PDF dim loop to prevent PDF.js worker saturation
On a 50-page PDF, calling setTotalPages before the getPage() dimension loop mounts all 50 ThumbnailCanvas components immediately. Each falls back to PDF.js (ser...
Expand component scan and add full datasource/JPA/Redis/MinIO config
ConversionServiceApplication was only scanning com.kamo.ConversionService, missing all shared library beans (ImageService, MinIOStorageService, MemberRepository...
Add kamo-shared-library build stage to resolve missing dependency
The Dockerfile was trying to fetch kamo-shared-library from Maven Central, which doesn't exist there. Mirror the SecurityService pattern: clone the shared libra...
Migrate all imaging API routes from SecurityService to ConversionService/DocsService
Upload routes now call ConversionService directly via CONVERSION_SERVICE_URL: - POST /api/imaging/upload → /api/conversion/imaging/upload - POST /api/imaging/te...
Remove ImagingController and beans/imaging — moved to ConversionService and DocsService
Upload endpoints now live in ConversionService at /api/conversion/imaging/*. All management and download endpoints now live in DocsService at /api/docs/imaging/...
Add imaging management endpoints — move all non-upload imaging from SecurityService
- Add 17 imaging DTOs to beans/imaging/ (folders, documents, templates, updates) - Add ImagingController at /api/docs/imaging with all management + download end...
Add imaging upload endpoints — move all upload logic from SecurityService
- Add JPA, Redis, NATS, kamo-shared-library, JJWT, commons-io, jackson-hibernate6 to pom.xml - Add datasource, Redis master/replica, NATS, MinIO config to appli...
Upgrade to Next.js 16.2.3, TypeScript 6.0.2, Node 24, React 19 types
- Pin next to 16.2.3 and eslint-config-next to match - Upgrade typescript to exact 6.0.2, @types/node to ^24 - Replace framer-motion with motion ^12 (motion/rea...
Delegate thumbnail generation to ConversionService, remove PDFBox dependency
ThumbnailGenerationJob now POSTs the converted PDF to ConversionService **************** unzips the response, and stores each thumb_p{n}.png in MinIO. PDFBox re...
Delegate thumbnail generation to ConversionService, remove PDFBox dependency
generateAndStoreThumbnails now POSTs the converted PDF to ConversionService **************** unzips the response, stores each thumb_p{n}.png in MinIO, and publi...
Add ThumbnailService and POST **************** endpoint
Accepts a PDF file, renders each page at 150 DPI via PDFBox, packs per-page PNGs into a ZIP (thumb_p0.png, thumb_p1.png, …) and returns it. Centralises all thum...
Add Thumbnails step to upload progress indicator, track generating_thumbnails WS stage
Synchronous per-page thumbnail generation during template upload with granular WS progress
- Add PDFBox dependency to pom.xml - After storing converted PDF, render all pages via PDFRenderer and upload each as {id}_thumb_p{n}.png - Publish generating_t...
Prevent page stacking, fix thumbnail slivers, add server-side thumbnails with PDF.js fallback
- Add flexShrink: 0 to page divs in PdfCanvas so pages don't compress in flex column - Add flexShrink: 0 to thumbnail items in PageThumbnailSidebar for same rea...
Add GET **************** endpoint to serve per-page PNG thumbnails
Generate per-page thumbnails for all PDF pages, store as {id}_thumb_p{n}.png
Add thumbPageCount field and findNeedingPageThumbnails query for per-page thumbnail support
Eager PDF rendering, natural scale normalisation, no horizontal scroll
- PdfCanvas: replace IntersectionObserver with eager render-all-pages. The observer-based approach was unreliable when the design tab starts with display:no...
Upgrade to Next.js 16.2.3, TypeScript 6.0.2, Node 24, React 19 types
- Next.js 16.2.3 with Turbopack as default dev server - TypeScript 6.0.2 with erasableSyntaxOnly and ES2022 target - @types/react@^19 and @types/react-dom@^19 (...
Eliminate removeChild DOM conflict in PDF thumbnail rendering
Replace container.innerHTML + appendChild pattern in ThumbnailCanvas with a React-managed <canvas> ref. The old approach cleared React-owned DOM nodes directly,...
Handle applicablePlanIds and applicableBillingCycles as string arrays
These fields are typed as string[] but had .split(",") calls on them, causing TypeScript build failures.
Add CockroachDB transaction retry for template init endpoint
CockroachDB serializable isolation can trigger RETRY_SERIALIZABLE on the read-then-write pattern in initTemplate. Retries up to 3 times with backoff when detect...
Revert proxy routes to OTK auth, remove unused esigProxy helper
OTK is the correct auth mechanism — the prior session-header approach bypassed the established security pattern. All esig proxy routes now use generateOTK from ...
Correct OTK Redis key format and add imaging template list endpoint
OTK keys use OTK<id> and ***<id> (no colon) matching the Next.js proxy. Added POST /api/esig/templates/list to query imaging templates via shared library ImgRep...
Use direct session headers instead of OTK for ESigService proxy routes
Read *** session from Redis in Next.js and pass orgId/memberId as trusted headers to ESigService via internal K8s DNS. Removes OTK dependency.
Replace OTK auth with trusted session headers for internal K8s calls
ESigService is internal — the Next.js backend reads the session from Redis and passes orgId/memberId/userId as X-Org-Id, X-Member-Id, X-User-Id headers. No OTK ...
Use init endpoint to find-or-create template by imgId on editor load
The create page passes imgId in the URL. The edit page now calls the init endpoint to find or create the ESignTemplate, then uses the returned UUID for design o...
Like what you see shipping?
All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.
