Release 1.60.0
Important Release Documents
Release Notes - Seatmap Platform
Version 1.60.0 - 2026-03-19
Release Focus: Event Lifecycle Management, Admin Section Selection, Table Editing, Seat Name Conflict Detection, Round Tables, and Keyboard Shortcuts
Event Lifecycle Management and Events Hub (SEAT-850/851)
Events now have a formal lifecycle with three states and controlled transitions:
- DRAFT – event is being configured, not visible to end users
- PUBLISHED – event is live and accessible through the booking API
- ARCHIVED – event is retired but can be restored back to DRAFT
New status transition endpoint replaces the old delete operation:
POST /api/events/{eventId}/status
Body: { "status": "PUBLISHED" | "ARCHIVED" | "DRAFT" }
The event model is extended with: status, description, posterUrl, tags, externalId, source (MANUAL or API), and publishedAt. Events created through the UI default to PUBLISHED; events created via the API default to DRAFT.
Events list endpoint now supports filtering by venueId in addition to schemaId, status, and full-text search. A new endpoint returns per-schema event counts for an entire venue, shown in the schema cards.
Events Hub
The Events Hub provides status-aware action buttons:
- DRAFT events show Publish
- PUBLISHED events show Archive (with confirmation modal)
- ARCHIVED events show Restore
Hard delete is removed. Events can be filtered by status and venue. The event table shows source badge (MANUAL or API), status badge, and links to the schema configuration in the editor.
Documentation: Events Hub
Preview Modal Multi-Event Switching
The editor’s Preview Modal supports switching between all events assigned to a schema without closing and reopening the modal.
- Event Switching: When a schema has multiple events, the preview modal displays an event selector bar. For up to 10 events, horizontal tabs appear; for larger event sets, a dropdown with prev/next navigation is used.
- Event ID Copy: The active event’s ID is displayed (truncated) in the modal header. Clicking it copies the full ID to clipboard with visual feedback.
- Action Buttons: Dedicated “Copy event link” and “Open in new window” buttons reflect the currently selected event.
- PricingPanel Integration: The event play button in PricingPanel now opens the in-app preview modal instead of a raw browser window.
- CSS Isolation: Editor outline styles no longer leak into the booking renderer preview. Hover interactions in the preview work correctly.
Event switching in the preview is exploratory only – it does not affect the active event selection or pricing state.
Schema Events Modal
A new Events toolbar button in the schema editor opens a self-contained event management modal without leaving the editor page. The modal:
- Lists all events linked to the current schema with status badges and dates
- Provides inline Publish / Archive / Restore action buttons per event
- Opens the event detail form pre-filled with the current schema (no venue/schema selectors needed)
- Shows a preview button per event that opens the booking renderer inline
- Refreshes the event list after create/update without a page reload
The Events button is visible whenever the schema has at least one event. It is positioned in the toolbar between the inspector and publish buttons and respects the standard hiddenItems configuration.
Navigation
The top navigation bar now always shows Venues and Events links with active highlighting, regardless of whether a schema is open in the editor. A visual separator divides the navigation links from the language selector.
Booking API Enforcement
The booking API now enforces that only PUBLISHED events are accessible. Requests for events in any other state receive HTTP 422 with error code EVENT_NOT_PUBLISHED. This applies to all public and private event endpoints (list, get by ID, get by public key).
Editor Error Handling
The editor page gracefully redirects to the venue list on load failures (403/404) instead of showing a broken page with cascading errors.
Database Migrations
| Migration | Description |
|---|---|
| V90 | Adds status, source, external_id, description, poster_url, tags, published_at to event table |
| V91 | Makes kill_after nullable (deprecated field) |
| V92 | Sets all existing events to PUBLISHED for backward compatibility |
Internationalization
Added Polish (pl) locale. All existing locales (en, de, es, fr, it, ru, zh) updated with Events Hub and schema events modal translations.
Breaking Changes
DELETE /api/events/{eventId} removed – Use POST /api/events/{eventId}/status with {"status": "ARCHIVED"} instead.
Booking API rejects non-published events – Returns HTTP 422 instead of event data. All existing events are migrated to PUBLISHED by V92, so no data is lost.
killAfter deprecated – The field is now optional. Existing values are preserved. New integrations should not rely on it.
Admin Renderer Section Selection (SEAT-815)
The Admin Renderer gains a dedicated selectSections mode for selecting one or more venue sections at a time.
New mode: selectSections
renderer.setMode('selectSections');
In this mode:
- Clicking any section (GA, tables, regular) toggles its visual selection state
- Dragging draws a rectangle and selects all sections that intersect it
- Keyboard modifiers control how drag selection merges with the existing selection:
- No modifier – replaces the current selection
- Shift or Cmd/Meta – adds to the current selection
- Alt/Option – removes from the current selection
Existing modes (pan, select, selectRows) are not affected.
New callback: onSectionsSelectionChange
Fires after every selection change with the current selection array:
const renderer = new SeatmapAdminRenderer(container, {
publicKey: 'your-key',
onSectionsSelectionChange: (sections) => {
console.log(`${sections.length} sections selected`);
sections.forEach(s => console.log(s.id, s.name, s.seatCount));
}
});
ISection enriched with seatCount
The ISection object passed to onSectionClick and onSectionsSelectionChange now includes seatCount – the number of seats in the section (for non-GA sections).
Documentation: Admin Renderer
Smart Section Click at Full View (SEAT-818)
When the entire venue map is visible (fully zoomed out), clicking a section no longer zooms/pans into it. Instead, the renderer fires the onSectionClick callback, treating the click as a selection rather than navigation.
This applies regardless of the configured interactionZoomStrategy. Zooming in past the full-view threshold restores normal zoom-to-section behavior.
Consumers who need programmatic zoom after a section click can call renderer.zoomToSection() from their onSectionClick callback.
Documentation: Section Click Behavior
Bug Fixes
Section Deletion Actually Deletes the Section (SEAT-880) – Deleting a GA or table section from the inspector list left an orphaned shape visible on the canvas. The shape appeared to remain, and attempting to delete it again showed a success message but did nothing, because the underlying section was already removed from state on the first delete attempt. The fix ensures deletion fully removes the associated canvas shape and clears any related bindings so orphaned data is not persisted on the next save.
Venue Deletion Fixed - No More Foreign Key Errors (SEAT-879) – Deleting a venue via DELETE /api/private/v2.0/venues/{id} previously failed with a database constraint error when the venue had schemas with associated events. The endpoint now performs a soft delete consistent with how the editor service handles venue deletion. Soft-deleted venues are invisible across all booking API endpoints: listing, lookup by ID, schema queries, event queries, and access-control checks.
Cloning a Schema Now Copies Existing Images (SEAT-844) – When a schema is duplicated, preview images are no longer regenerated from scratch. The clone operation copies all image variants (full, preview, and blurred) directly from the source schema. Each clone holds an independent set of images, so regenerating the source no longer silently breaks the clone’s preview.
Booking-Service Clone Now Copies Full Seatmap (SEAT-883) – The asynchronous clone triggered via the booking-service private API (POST /api/private/v2.0/schemas/clone/{id}) only copied schema metadata (name, venue association) but not the actual seatmap content (seats, rows, sectors, shapes). The cloned schema appeared empty in the booking renderer. The Redis message subscriber now performs the full two-step clone: metadata duplication followed by seatmap data copy, matching the behavior of the editor’s direct clone endpoint. A security context is established for the background Redis listener thread so that audit columns (created_by, modified_by) are populated correctly.
Clone Result API Now Returns newSchemaId (SEAT-882) – The clone result endpoint (GET /api/private/v2.0/schemas/clone/result/{uuid}) always returned null for newSchemaId even after a successful clone. The shared CloneCommand model used by MapStruct was missing the newSchemaId field, so the mapper silently dropped it. The field is now present and the clone result includes the ID of the newly created schema.
Clone Result Swagger Docs Corrected (SEAT-884) – The OpenAPI description for the clone result endpoint listed incorrect state values (PENDING, RUNNING, COMPLETED, FAILED). The actual states are CREATED, IN_PROCESS, DONE, and ERROR. The Swagger documentation now matches the implementation.
Polygon Shape Distortion in Renderer (SEAT-858) – Fixed polygon shapes appearing stretched or distorted in the booking renderer compared to their appearance in the editor. Polygons now use the same scaling formula in SVG generation as the editor, so the rendered polygon exactly matches the editor shape in both size and aspect ratio.
Duplicate Seats Prevention (SEAT-804) – Fixed seats being duplicated during concurrent saves or after undo operations. The save button is now disabled during an active save, and server-assigned seat IDs are preserved across undo.
Duplicate Key Violation on Seat Groups (SEAT-852) – Fixed an intermittent database constraint error on seat group IDs caused by a sequence allocation conflict. The seat group sequence now allocates one ID at a time, consistent with the existing seat sequence pattern.
CSS Isolation in Preview Modal (SEAT-850) – Fixed editor outline styles leaking into the booking renderer preview, causing gray section outlines to appear. Fixed hover interaction loss caused by style specificity conflicts. Preview and editor styles now use separate specificity hierarchies and no longer interfere with each other.
GA Sections Overflow in Schema Previews (SEAT-823) – Fixed schema preview thumbnails clipping GA (General Admission) sections. The SVG export now merges the viewbox from the database with the server-computed geometry viewbox so all content is visible. The editor save flow also correctly accounts for all content when computing viewbox bounds.
SVG Section Bindings Lost After Save (SEAT-881) – Fixed SVG section bindings being lost after save and preview due to a serialization/binding persistence issue.
Schema List Page Freeze (SEAT-888) – Fixed the schema list page freezing after navigating away from the editor. Loading flags were not reset on the CLEAR action, causing the schema list to enter a permanent loading state.
GA Section Text Color Not Displayed in Renderer (SEAT-817) – The textColor property on GA sections was stripped during SVG redraws by cleanSvgInlineStyles. The fix spans the editor, booking-service shape metadata, and renderer outline processing to preserve text color through the pipeline.
SVG Fetch via postMessage Restored (SEAT-857) – The postMessage-based FETCH_SVG mechanism stopped working. Fixed as a side effect of related SVG rendering work.
Inconsistent Zoom Levels (SEAT-176) – Inconsistent zoom levels across venues resolved by related zoom and scale changes.
Database Migrations
| Migration | Description |
|---|---|
| V93 | Changes seat group sequence to allocate one ID at a time |
Table Editing Mode (SEAT-786, SEAT-830)
Tables now support a dedicated editing mode for individual seat management. Double-clicking a table in the schema editor enters table edit mode, where each seat can be selected and configured independently.
Documentation: Table Editing
Seat-level controls
In table edit mode, selecting one or more seats exposes property controls in the right panel:
- Hidden checkbox – marks seats as invisible to the booking API and renderer
- Accessible and Marked attributes remain available
Hiding all seats in a table removes both the seats and the table outline from the booking response, effectively making the entire table invisible to end users.
Interaction improvements
- Clicking a seat selects it and shows its properties; clicking the same seat again deselects it (toggle behavior)
- Hovering over a table seat now shows a pointer cursor, consistent with regular section seats
- Section and table tooltips show “Untitled” as a fallback when the name is not set, preventing blank tooltip labels
Seat Name Conflict Detection (SEAT-819)
The editor now validates that seat names are unique within each row of a section, with three interconnected feedback mechanisms:
Canvas Warnings
Seats with duplicate names are rendered in red (#dc2626) on the WebGL canvas. Dotted SVG arc connectors (stroke-dasharray 4,3) link conflicting seats within each row, using DuplicateSeatsRenderer with non-scaling strokes that maintain visibility at any zoom level.
Inspector Panel “Active” Tab
A new Active tab in the Inspector panel shows rows and seats for the active section. Rows containing duplicates display a red background with red text. Individual seats with conflicts show a red dot indicator. The Inspector toggle button itself shows an error state (pink background) when any section has duplicates.
Status Bar with Conflicts Indicator
A new Status Bar component at the bottom of the editor displays zoom percentage, canvas position, underlay dimensions, and viewBox. When duplicate seat names exist, a red “Conflicts: N rows” indicator appears. Clicking it opens the Inspector panel. The Inspector auto-opens when conflicts are first detected.
Validation Behavior
Validation is non-blocking: toast notifications appear on rename, bulk-rename, and save operations, but the operations proceed. Performance uses O(n) linear scan with memoized selectors, benchmarked at ~11ms for 58,500 seats. All locales updated (en, de, es, fr, it, pl, ru, zh).
Documentation: Seat Name Validation
Round and Elliptical Tables (SEAT-73)
New ROUND and ELLIPTICAL table display modes with arc-length seat distribution for even spacing around the table perimeter. Both the editor and booking renderer support the new display modes. This extends the table editing mode from SEAT-786/SEAT-830.
Documentation: Round Tables
Per-Row Horizontal Seat Spacing (SEAT-68)
A new sidebar slider allows adjusting horizontal spacing between seats on a per-row basis for straight sections. Changes preview in real-time on the canvas and are persisted with the schema.
Documentation: Seat Spacing
Row Label Alignment Modes (SEAT-885)
Two alignment modes for row labels:
- PER_ROW – labels follow seat positions, aligning with the start of each row
- PER_SECTION – labels are vertically aligned in a straight column at the section edge
PER_SECTION mode is useful for venues with irregular seat counts per row where consistent label alignment improves readability.
Documentation: Row Label Alignment
Save Failure Messages (SEAT-75)
The editor now displays an error message to the user when a schema save fails, with diagnostic logging for troubleshooting.
Whole-Table Hover Events (SEAT-824)
Tables with section-level pricing now fire onSectorMouseEnter / onSectorMouseLeave hover callbacks in the booking renderer, consistent with regular section hover behavior. No new callback types are introduced; consumers can distinguish table sections via section.type.
Documentation: Renderer SDK Reference
Keyboard Shortcuts (SEAT-886)
New keyboard shortcuts in the editor:
| Shortcut | Action |
|---|---|
| Ctrl+S | Save schema |
| ] | Move selected object forward one layer |
| [ | Move selected object back one layer |
| Ctrl+] | Move selected object to front |
| Ctrl+[ | Move selected object to back |
| 1-6 | Switch between editor modes |
| I | Toggle Inspector panel |
All shortcuts are disabled when focus is in text inputs or modals.
Documentation: Keyboard Shortcuts
Infrastructure: Actuator Readiness Probes
Both backend services now expose dedicated health endpoints:
GET /actuator/health/readiness– returns 200 only when the database and Redis are connectedGET /actuator/health/liveness– lightweight heartbeat
Helm deployments now use a three-probe strategy:
- startupProbe – 150s budget absorbs JVM startup, prevents premature liveness kills
- readinessProbe – only routes traffic when database and Redis are connected
- livenessProbe – lightweight, won’t restart a pod for transient database issues
Helm Charts Aligned with Kubernetes 1.30.14 (SEAT-859)
All Helm charts (seatmap, converter, knowledge-base) have been reviewed and updated for Kubernetes 1.30.14 compatibility and security hardening.
Compatibility:
- Added minimum Kubernetes version constraint to all charts
- Replaced deprecated ingress class annotation with the current field across all ingresses
- Updated CI manifest validation to target Kubernetes 1.30
Security Hardening:
- Added pod and container security contexts to all deployments: non-root execution, dropped capabilities, seccomp profile
- Added security response headers (X-Content-Type-Options, Referrer-Policy, Permissions-Policy) to all ingresses
- Added SSL/TLS enforcement to all ingresses
Gzip Compression:
- Added nginx compression to converter, knowledge-base, and landing-page ingresses (editor/booking already had it)
Chart Versioning:
- Chart version and image tags are now injected by CI at deploy time instead of being hardcoded in source
Code Quality
TypeScript 5.9 Strict Mode – Upgraded both frontend projects to TypeScript 5.9.3 with full strict mode and strict index access checking. Over 1,050 type errors were resolved, uncovering 5 real latent bugs that could crash the application when encountering missing or invalid data in carts, sections, prices, and seat references.
Shared Base Configs – Unified TypeScript and ESLint configuration across both frontend projects, eliminating configuration drift.
Node.js 22 Alignment – Both frontend projects now require Node.js 22 LTS.
Jest to Vitest Migration (booking-client) – Migrated booking-client from Jest to Vitest 4, aligning both frontend projects on the same test runner. All 221 tests pass.
Pre-commit Hooks – Prettier now runs automatically on staged files before every commit.
ESLint for Editor Client (SEAT-855) – Eliminated all type safety warnings and errors. All implicit any types replaced with proper TypeScript types. Clean baseline for CI enforcement.
ESLint for Booking Client (SEAT-856) – Added ESLint to booking-client and fixed all lint issues across 46 files. Replaced implicit any types with proper TypeScript types and fixed various code quality issues. CI pipeline now enforces ESLint for both frontend products.
CI Lint Stage (SEAT-854) – Consolidated all frontend linting and type-checking into a dedicated lint stage in the CI pipeline as a required gate.
Auth Security (SEAT-853) – Server-side session invalidation on logout. JWT refresh tokens are invalidated server-side on logout, preventing reuse of tokens after a user signs out.
Migration Guide
For Self-Hosted Customers (Breaking Change)
Frontend Docker images (editor-client, booking-client) now use nginx-unprivileged and listen on port 8081 instead of port 80.
If you manage your own Kubernetes manifests or Docker Compose files, you must update the container port from 80 to 8081 in your Deployment spec and the targetPort in your Service spec. Without this change, frontends will appear to start normally but will not serve HTTP traffic.
See Deployment Guide for detailed migration steps with examples.
Backend services (editor-service, booking-service, converter-service) are not affected – their ports remain unchanged.
For Helm-Managed Deployments
No action required. The Helm chart has been updated to use port 8081 automatically.
Renderer API
No code changes required. The booking renderer API is fully backwards compatible.