Changelog
Active development, in the open. Sourced fromGitHub Releases.
v26.6.5 A stability and hardening release. Undo and redo resolve devices by id now, so the right device is affected after re-ordering. We fixed the undo bug. There was never an undo bug. Malformed or oversized layout files are caught at every read door instead of corrupting your work, and the rest is security hardening, storage-layer groundwork, and technical-debt paydown.
### Fixed
- Undo and redo resolve the target device by id, so redo deletes or edits the right device after an undo re-appends it (#2656, #2665)
- No-op colour or face updates no longer run a command and wipe the redo stack (#2660)
- Loading a layout clamps rail devices that extend above the rack back within bounds (#2661)
- Malformed browser-workspace and autosave bodies are validated through the schema and forward-compat version gate instead of crashing startup (#2657, #2664)
- NetBox-imported device types are validated and deduped, so an invalid u_height or slug can no longer destroy the autosave on reload (#2655)
- Storage popover z-index, verb-bar anchoring in dual view, and toast placement (now bottom-centre) corrected (#2637, #2645, #2646)
- Share-link decode no longer throws a Data-to-string type error (#2686)
- Rail positions are guarded as whole-U integers at the place and move chokepoints (#2667)
### Security
- Share-link decode is bounded by input and decompressed size to prevent a decompression-bomb denial of service (#2658)
- API rate limiting hardened: OIDC login initiation is throttled and spoofable client-IP headers are no longer trusted by default (#2659)
- hono override aligned to ^4.12.27 to clear CVE-2026-54290 (#2650)
### Removed
- Dead octocov coverage-badge workflow (The Count's Code Census) and its config. It had been disabled since January 2026, never ran again, and published badge JSON that nothing in the repo referenced. The orphan report/badges branch and its protecting ruleset were removed too (#2651)
- Verified dead code with zero call sites, nine items (#2669)
### Technical
- Storage driver interface with a per-request dependency-injection seam, an R2 storage driver, and a runner-agnostic contract harness, laying the groundwork for the Cloudflare migration (#2624, #2625)
- Decomposed three oversized modules: schemas/index.ts, yaml.ts, and archive.ts (#2668)
- Device-type import ingress routed through DeviceTypeSchema (#2666)
- Filename-slug sanitization consolidated through slugify(), URange deduped (#2670)
- ESLint regression guards added for html and raw web storage outside the storage seam (#2672)
- Self-host header and build-env parity guard added to CI (#2032)
- Pre-commit prettier resolved via node module resolution so it no longer fails open in worktrees (#2639)
- Stale and flaky e2e tests aligned to shipped behaviour: mobile top bar, device labels, dual-view FRONT/REAR selectors, single-face migration counts (#2680)
- Leftover sparse-checkout cleared in the prod smoke-test job, dev-first M018 Cloudflare migration plan documented (#2674)v26.6.4 A large usability release. The workspace is rebuilt around the canvas, and the storage layer is rebuilt to stop silently losing work. The rest is targeted fixes and technical-debt paydown that make the app faster to work in and more reliable. You can trust it with your data now. Please. It would mean a lot.
I'm looking forward to what's next.
@ggfevans
### Added
- Command palette is the search input for commands: one box runs any action or finds any device, opened from the toolbar search pill or with Ctrl+K, with recents, a selection-aware empty state, device search, and click-to-place on desktop (#2212, #2213, #2214, #2341, #2352)
- Tabbed side panel replaces the single edit panel: Layouts, Racks, and Devices tabs, contextual properties on the Edit tab, display toggles on the View tab, collapsible (#2076, #2077, #2078, #2082)
- Floating verb bars put context actions next to the selected device or rack, including a slot control for half-width devices (#2075, #2322, #2334, #2344)
- Layouts library lists every saved layout with cached previews, opened and managed from the sidebar (#2082, #2083, #2325)
- Open layouts persist as toolbar tabs and restore lazily on launch (#2079, #2080, #2324)
- Top bar reduced to workspace chrome (logo, app menu, layout name, storage status, settings); view and history controls relocated to a floating cluster at the canvas bottom-left, where the cursor already is (#2072, #2073, #2074, #2187)
- App menu behind the Rackula mark is now the main menu: reorganized by intent, with the menu-item registry contract completed, group headings renamed for clarity, dividers between groups, and a mobile sheet that renders the same projection (#2596, #2597, #2602, #2611)
- Settings dialog consolidates Appearance, Behaviour, and Data options (#2093)
- Device palette gains favourites, list virtualization for large libraries, and an image on/off toggle (#2094)
- New layouts open to a template picker instead of a blank canvas; the standalone StartScreen is gone, with entry routed through the sidebar and app menu (#2081, #2095)
- Export-all renders every layout with per-mode framing in one pass (#2045)
- Carrier device types host half-width and sub-U gear directly, replacing the fractional-rail model so sub-U placement is predictable (#2158, #2289, #2291, #2159)
- Storage status chip in the toolbar shows save state at a glance, with the storage location inline and a last-save details popover on hover or tap (#2035, #2446, #2640)
- Moving browser-stored layouts to server storage prompts before overwriting an existing server copy (#2608)
- Pre-overwrite snapshots are taken server-side with conflict detection; the Load dialog lists and restores them (#2040, #2041, #2042)
- Backup nudge tracks changes since the last export and warns before they are discarded, with a restore-from-file confirm step (#2034, #2038, #2039)
- Custom device images embed as base64 in the YAML save, so one file round-trips with its images (#617)
- Layout JSON Schema generated from the Zod schema for editor validation, under a documented versioning and compatibility policy (#1113, #2226)
- Full-depth devices render and collide on both rack faces, so a device stored facing front also occupies and shows on the rear (#2337)
- Keyboard alternative for placing devices, so a device can be added without a pointer (#106)
- Device images show a load placeholder, fade in when ready, and raise a toast on failure, with accessible alt text
- Create-custom-device promoted to a labelled button at the foot of the device palette (#2556)
- Hover-revealed edge grip on the panel seam as a second way to collapse a side panel
- Verb-bar and canvas-control tooltips are sourced from the command registry, so labels and shortcuts stay in step
- MikroTik CSS326-24G-2S+RM and CSS610-8G-2S+IN switches added to the device library (#1581)
### Changed
- Persistence runs through one storage interface with an explicit, injected mode, replacing runtime probe-and-guess (#2027, #2036, #2037)
- A twin-tab guard stops two open tabs from overwriting the same working copy, with placement images namespaced per layout (#2044, #2270)
- Unknown top-level sections in a layout file survive a save instead of being dropped (#2208)
- Sidebar tabs ordered Layouts, Racks, Devices (#2326)
- Zoom snaps to round ladder rungs (#2336)
- Edit panel resolves device brand from the authoritative library; category names shown in singular (#2217, #2218, #2219)
- Display-mode toggle icon redesigned for clarity (#2335)
- Coffin-tapered mark adopted as the canonical logo (#2048)
- Rack PDUs modelled as shallow power bars that render in rear view (#2337)
- App light theme (Alucard) removed; Rackula is dark-only (#2468)
- Edit and View tab strip unified with the sidebar's segmented-control style (#2600)
- flip-device-face verb uses a transition-right glyph for clarity (#2400)
- The API validates a layout against the JSON Schema before persisting it (#2449)
### Fixed
- Devices keep their container across same-rack and cross-rack moves, nudges, and YAML export; stale links are cleared on move (#2127, #2128, #2129, #2131, #2135, #2224)
- Keyboard nudge no longer ejects a contained device from its container (#2146)
- Undo and redo bind to the correct rack and no longer throw on deleted racks (#2126)
- In-progress device name edits stay attached to their device (#2223)
- Rack height input reverts when a bayed rack rejects the resize (#2222)
- Half-U stacking works again for 0.5U devices (#2152)
- NetBox import validates enum and interface fields instead of casting blindly (#2119, #2122)
- Export download no longer races object-URL revocation (#2201)
- Layout loads remap rack groups and container IDs in a two-pass load (#2155)
- Placement images survive server reconciliation and YAML round-trips (#2220, #2225)
- Layouts mark clean after a debounced auto-save (#2057, #2058, #2061, #2084)
- Snapshot data loss closed with strictly monotonic updatedAt and a per-layout write lock (#2067, #2233)
- Muted-text and QR-brand contrast raised to WCAG AA, nested-interactive controls flattened, and canvas racks given a listbox parent so axe WCAG AA passes (#2255, #2256)
### Security
- CSV export escapes spreadsheet formula injection (#2200)
- Patched libssl3 and libcrypto3 for CVE-2026-45447 (alerts #80-83)
- Automated security-alert triage via Claude Code (#2357)
- Pinned libexpat to >=2.8.1-r0 in the deploy image for CVE-2026-45186 (#2562)
### Technical
- Type checking restored across the utils, storage, and component layers; the last @ts-nocheck surfaces are gone (#1705, #2104, #2105)
- Layout store decomposed into per-layout instances behind a facade, with rack and device logic split into domain action modules; Canvas coordinate math and markup extracted; export.ts and EditPanel.svelte split into focused modules (#1077, #1080, #1396, #1398, #1610, #2024, #2025)
- E2E suite reworked: two-tier model with an environment approval gate, 4-way sharding, assertion-based waits, and role/label selectors, plus new undo/redo and accessibility coverage (#1227, #1231, #1420, #2002, #2003)
- Regression gates added: visual-diff tripwire, axe-core accessibility checks, a bundle-size budget, and a ban on CSS-class selectors in tests (#1423, #2098, #2099, #2185)
- Upgrade-safety net so a self-hosted deployment can take new images without losing saved data: prior-release layouts load through the real parse path in a self-discovering fixture corpus with silent-loss detection, plus a fail-closed release guard; the Docker upgrade smoke drives the compose stack from the previous released image to the new build against the same volume and confirms the saved layout survives byte-for-byte (#2448, #2515)
- i18n deferred to M011; the orphaned Paraglide runtime removed (#2184)
- Dev tooling hardened: cloud-safe superpowers bootstrap, worktree-aware main-edit guard, POSIX husky hooks, the /orchestrate-issues command, and pre-push gate fixes (#2102, #2288)
- Upgrade corpus exercises the loadLayout path with v0.6 single-rack YAML fixtures (#2450, #2451)
- Vendor asset directories normalized and the generic device library split from brand packs (#2552)
- @testing-library/svelte pinned to 5.3.1 to restore runes compatibility in the unit suite (#2587)
- SPA entry document revalidated on deploy so a stale cache stops serving the old build (#2599)
- DCO sign-off section added to CONTRIBUTING (#2559)
- Research spikes: accurate depth model for M021 (#2622) and Cloudflare Workers Static Assets for #2029 prep (#2620)
- Dependency updates across the production, development, vitest, eslint, and api groupsv26.6.3 For a while, the way Rackula got released was: someone pushed a tag and hoped. Nobody deployed the LXC install on an actual container first. They just believed in it. That is how v26.6.2 shipped an install that could not start on an unprivileged container, which is the default. We found the guy who did that. It was me. @ggfevans.
So now a release does not ship until it proves it works.
### Changed
- Release pipeline is now gated: stage as a prerelease, validate on real targets (Docker compose health plus an LXC smoke test on a throwaway unprivileged container), and promote only if every gate passes. A failed gate promotes nothing, so `:latest` and prod always point at the last known-good release (#1977)
### Added
- Release-free dev build mode for LXC payloads, so the install can be tested without cutting a release (#1959)
- Reusable LXC smoke-test with a Proxmox API driver, used by the release gate to deploy and verify on a real container (#1967, #1982)
### Fixed
- LXC deploy: unprivileged containers now work correctly; Bun runtime, nginx, systemd hardening, and data-safe update paths are all compatible with unprivileged CTs (#1961, closes #1969)
- LXC community-scripts: aligned with ProxmoxVED conventions and hardened build-lxc checkout (#1953, PR #1966)
- LXC install: unzip is now installed before use and the Bun installer fetch is more resilient (#1933, PR #1934)
- Accessibility: autofocus warning on layout name input resolved (#1896, PR #1963)
- Even spacing between toolbar button clusters (#1962)
- Cross-rack device moves now re-key placement images correctly so images are not lost after a move (#1478)
- CI: deploy-dev path filter repaired so pushes to main trigger the dev deployment again (#1924, PR #1925)
### Removed
- Umami analytics removed entirely from source code, deployment config, and documentation. No client-side analytics ship with Rackula anymore (#1972, #1973, #1975; PRs #1978, #1979, #1981)
v26.6.2 Maintenance release: release tooling and API dependency hygiene, plus an export fix and KWS device-library corrections.
### Changed
- KWS device library: corrected module widths and depths, dropped U-height from module names, and added magnetic patch panels (#1912) - thanks @ilanKushnir!
### Fixed
- Export: clipPath IDs are now unique across racks, faces, and devices, preventing collisions in multi-rack dual-view exports (#1904, PR #1911)
### Technical
- Release tooling: contributors.sh is now portable to macOS BSD tools and bash 3.2, so the per-release contributor block is written when /release runs locally (#1907, PR #1923)
- API: consolidated dependencies on Bun, removed the unused npm lockfile, and added a Dependabot bun ecosystem entry for /api (#1914, PR #1916)
- API: package version is now aligned by the release flow (#1915, PR #1917)
- Dependency updates: svelte, fuse.js, @types/node, and grouped GitHub Actions updates, plus api typescript and zod bumps (#1913, #1921, #1920, #1922, #1919, #1918)v26.6.1 The LXC release. For real this time. v26.6.0 proudly shipped a self-contained container and then forgot to install the runtime that actually runs the API, so the service never started. We shipped a box with no engine. Mortifying. This is the one that boots: the Bun runtime is installed, the API comes up, and /health answers. You wanted working LXC? You finally have working LXC.
### Fixed
- LXC install now installs the Bun runtime, so the API starts. v26.6.0 containers shipped without a JS runtime and the API service could not start (#1909, PR #1910)
### Changed
- LXC install and update scripts brought into community-scripts convention compliance: the update path uses fetch_and_deploy_gh_release instead of custom download logic, and custom SHA256 verification is removed from the scripts. The release still publishes a SHA256 asset; the scripts rely on the deploy helper and HTTPS (#1908, PR #1910)
v26.6.0 You wanted LXC?! You GOT LXC. The Proxmox VE deployment is production-ready, baby: Rackula installs as one self-contained Debian 13 container, web frontend and persistence API riding together, now on arm64 AND x86-64, with a SHA256-verified tarball because we are not handing you an unverified tarball like some kind of clown. You asked for the container. We made the container. It's the LXC release.
### LXC deployment
- arm64 support: the release tarball bundles the arm64 native binary and the install advertises arm64 (#1850, PRs #1852 and #1906)
- SHA256 verification for the release tarball (#1891, PR #1894)
- update_script rollback hardening and install idempotency (#1851, PR #1854)
- Hardened the release workflow against shell injection and split it into read-only build and write-only publish (#1897, PR #1898; #1899, PR #1900)
- Corrected notes format in rackula.json (#1213, PR #1831)
### Added
- Firewall device category (#1833, PR #1835)
- Port type categorization for network, power, and console ports (#1836)
- KWS 10-inch homelab rack brand pack, contributed by @ilanKushnir (#1837)
- Onboarding hint shown when a rack has no devices (#1827)
- Haptic feedback on touch selection, with a thicker selection outline on mobile (#1883)
- Rack height slider in the new-rack wizards (#756, PR #1865)
- API write-route rate limiting for self-hosted deployments (#1778, PR #1828)
- API explicit mutating-request origin policy (#1779, PR #1830)
- API storage abuse guardrails: per-layout quota and retention (#1780, PR #1875)
### Changed
- Save confirmation moved from the toolbar indicator to a toast, removing the toolbar layout shift (#1901, PR #1903)
- Storage quota rejections surfaced with clear, actionable messaging (#1390, PR #1893)
- Mini-PC devices moved from the Generic library into dedicated brand packs (#1840, PR #1844)
- API adopts pino structured logging with levels (#1888, PR #1892)
### Fixed
- Device placement images now render in exports, matching the editor (#1902, PR #1905)
- Auto-import undo no longer removes shared device types (#1479, PR #1859)
- Device palette: chassis added to category order, drift-proofed against future omissions (#1839, PR #1849)
### Security
- Patched libxml2 CVE-2026-6732 by busting the apk-upgrade layer cache (#1841, PR #1843)
- Dependency security updates: better-auth and dompurify (#1885, #1879)
### Technical
- OIDC behind a reverse proxy documented and verified (#1832, PR #1845)
- arm64 native-dependency load verified on a native arm64 CI runner (#1850, PR #1906)
- Automatic per-release contributor acknowledgements (#1876, PR #1889)v26.5.0 you might be wondering "hey, wasn't it on like v0.10??" - and you're right! Rackula has moved from SemVer (0.MINOR.PATCH) to Calendar Versioning (YY.M.MICRO). Future versions follow the format YY.M.MICRO where YY is the 2-digit year, M is the unpadded month, and MICRO is the release counter within that month (starting at 0). This is primarily so I don't have to overthink between a major, minor or patch release. Also, because biggest number is best number.
Also includes some prep work for an upcoming Proxmox Community Scripts LXC deployment method.
### Changed
- Migrated from SemVer (0.MINOR.PATCH) to CalVer (YY.M.MICRO) versioning (#1315, #1808, PR #1816)
### Fixed
- LXC installation script: community-scripts compliance, security hardening, and reliability fixes (#1211, PR #1797)
- Bun installer pipe suppressed by wrapper in LXC script (PR #1817)
- LXC install script: apt replaces apt-get for community-scripts compatibility (PR #1800)
### Technical
- CalVer release tooling: version script, deploy workflow, /release skill, and CI config (#1803-#1806)
- CLAUDE.md versioning policy rewritten for CalVer (#1807, PR #1812)
- README refreshed for FOSS professionalism (#1353, PR #1818)
- Writing style directives: no em dashes, no emoji in docs, succinct language (#1353, PR #1820)
- Deploy config parity safeguards and scripts documentation (PR #1799)
- Root config tidying: Playwright configs, env examples (PR #1798)
- Repo root cleanup: empty dirs, orphaned files, AI doc consolidation (PR #1796)
- Bump eslint 10.4.0 to 10.4.1 (PR #1801)v0.10.1 ### Added
- Make YAML the default save format (#619, PR #1754)
- Refit canvas on device orientation change in mobile mode (PR #1751)
### Fixed
- Half-width devices independently selectable at same U position (#1680, PR #1773)
- Enable mouse/pointer tap-to-place in mobile mode (≤1024px viewport) (#1757, PR #1760) - shoutout to @Jefferson-Butler1 for reporting this
- Canvas fills full window in mobile mode (#1764, PR #1765)
- E2E specs updated for YAML default save format (#1767, PR #1768)
- Verify live frontend version only on no-API prod (#1770, PR #1771)
- Remaining full-E2E failures — android long-press context menu + starter-library search (#1769, PR #1776)
### Security
- Remove Stryker mutation testing, fix CVE-2026-8723 (qs dependency) (#1774, PR #1775)
### Technical
- E2E regression tests for mouse tap-to-place in mobile mode (#1762, PR #1763)
- NPM library feasibility & LOE spike documentation (#1758, PR #1761)
- Scope deploy-dev.yml to relevant paths only (PR #1772)
- Dependency bumps: dompurify, eslint-plugin-svelte, svelte, @lucide/svelte
<3 @ggfevansv0.10.0
### Added- Right-click context menu for custom devices in the device palette (#1701)
- Persist viewport zoom/pan across page reloads (#118)
- Share URL length warning at 1800 chars with a download-layout-file fallback (#1720)
- Validate interface positions on half-depth device types (#254)
- Layouts navigation in the File Menu and mobile toolbar (#1722)
- Vector PDF export for AutoCAD compatibility (#1731, PR #1734)
- Cross-rack device drag-and-drop (#1592, PR #1744)### Changed
- Replace pako with lz-string for share-URL compression (#1718)
### Fixed
- Sync U-numbering settings across bayed rack groups (#1520, PR #1702)
- Convert position from internal units in the resize validator (#1683, PR #1695)
- Sync layout name to the first rack on creation (#1481, #1482, PR #1687)
- Clean up cables when a device type is deleted (#1483, PR #1693)
- Skip pointer drag events outside rack SVG bounds (#1467, PR #1690)
- Respect per-device face in PNG export filter (#1681, PR #1682)
- Respect half-width slot_position in PNG export (#1660, PR #1679)
- Drop legacy AUTH*\*/API*\* env-var fallbacks in the api (#1692)
- Recover slot_position and slot_width for half-width pairs on load (#1602, PR #1704)
- Fix OIDC auth redirect port when behind a reverse proxy (#1714)
- Right-click context menus now open at the cursor instead of the top-left origin (#1725, PR #1726)
- Reduce text stroke-width and remove unsupported paint-order (PR #1737)
- PDF export rendering regressions — bay labels duplicated in bayed racks, structural labels render in serif font, device names offset upward (#1738, #1739, #1740, PR #1741)### Security
- Resolve all 7 open Trivy code-scanning alerts on the api image by bumping better-auth 1.5.1 → 1.6.2 (#1676), removing/upgrading vulnerable transitive deps: kysely (CVE-2026-44635, -33468, -32763), defu (CVE-2026-35209), lodash (CVE-2026-4800), effect (CVE-2026-32887), drizzle-orm (CVE-2026-39356)
- Patch hono + defu dependency CVEs in the api (#1691)
- Add to Content-Security-Policy headers (#1723)
- Bump qs 6.15.1 → 6.15.2 (#1721)### Technical
- Enable TypeScript strict mode on the frontend (#1609, PR #1709)
- Split api security.ts into focused modules (#1611, PR #1689)
- Introduce mountWithAlias helper for /api/\* route aliases (#1684)
- On-demand Trivy security scan workflow aligned with deploy-prod (#1675)
- Post-release version-alignment test across published Docker images (#1728, PR #1730)
- Dev deploy workflow fails loudly if data dir not writable by uid 1001 (#1742)
- Disable binfmt cache to fix parallel cache-save collisions in CI (#1688)
- Resolve a CodeQL code-quality finding (#1703)
- Dependency bumps: svelte, vitest, tsx, marked, @types/node, eslint, typescript-eslint, and the production/development/actions dependency groupsv0.9.5
### Added- FS.COM brand pack with 4 switches (S8050-20Q4C, S5850-32S2Q, S5850-24S2Q, S3410-10TF-P) and 4 missing Netgear models (XSM7224S, GS752TXS, M4350-32F8V, M4350-24X8F8V) — first-time contribution from @churtado-tech (#1662)
### Fixed
- Claude code review workflow on fork PRs — use then revert to with fork skip (#1669, PR #1670, PR #1671)
- Code quality findings from CodeQL/Copilot analysis (#1639, #1640)### Security
- Patch Alpine packages in api Dockerfile to resolve CVE-2026-31789 (OpenSSL heap buffer overflow) and clear 7 related Alpine HIGH CVEs blocking the prod deploy gate (#1672)
### Technical
- TypeScript 5.9.3 → 6.0.3 (#1635)
- Svelte 5.55.5 → 5.55.7 (#1667)
- kysely 0.28.14 → 0.28.17 in /api (#1654)
- Update CodeQL action version and exit code
- VPS migration research documentation
- Dependency bumps: @types/node, fast-uri, @eslint/compat, @vitest/eslint-plugin, typescript-eslint, and production/development dependency groupsv0.9.4
### Added- Separate layout naming from rack naming — layouts and racks can now have independent names (#1005)
### Fixed
- Device type auto-import integrates with command system for proper undo/redo (#1470)
- Batch auto-import with placement command for atomic undo/redo
- Context menu move up/down now checks collisions (#1462, PR #1504)
- Unique SVG pattern IDs per rack instance to prevent cross-rack rendering conflicts (#1466, PR #1505)
- Auto-detect IPv6 availability to prevent nginx startup failure (#1516, PR #1527)
- Show error/warning toasts for device import failures (#1391, PR #1506)
- Preserve slot_position and slot_width in YAML serialization (#1564, contributed by @lorenzowood)
- Guard preset shortcuts when custom-height input is focused in new-rack wizard (#1580, PR #1604)
- Double bay device selection (#1522, PR #1545)
- Storage resilience — use safeStorage for all web storage access (#1392, PR #1530)
- Make nginx DNS resolver configurable for Kubernetes (#1535, PR #1538)### Security
- Fix escape order in NetBox importer to prevent double-escaping, scope CodeQL to src (#1595, PR #1601)
- Bump hono to 4.12.14 and dompurify to 3.4.0, closing 7 CVEs (#1594, PR #1596)### Technical
- Decompose App.svelte and Rack.svelte into rendering and interaction layers (#1395, #1451)
- Extract drag-drop and context menu logic from Rack.svelte
- Centralise E2E CSS selectors into locators.ts (#1458)
- E2E test suite recovery — 58 failures resolved (#1508)
- Remove root npm package-lock.json (project uses bun) (#1603)
- Dependency updates: Svelte 5.55.5, Vite 8.0.10, marked 18.0.2, hono 4.12.14v0.9.3 We hit 1k stars!! Thanks for all your support, I really appreciate it.
This patch release is mainly looking to fix an issue where the container would fail to start in environments without IPv6.
Also includes a bunch of dependency upgrades, mainly for security reasons and staying current.
## What's Changed
* fix: auto-detect IPv6 availability to prevent nginx startup failure (#1516) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1527
* add og-image for repo card by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1526
* chore(deps): bump jspdf from 4.2.0 to 4.2.1 by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1491
* chore(deps): bump svelte from 5.53.12 to 5.53.13 in the svelte group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1492
* chore(deps): bump svelte from 5.53.13 to 5.54.0 in the svelte group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1493
* chore(deps): bump eslint-plugin-testing-library from 7.16.0 to 7.16.1 in the eslint group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1494
* chore(deps): bump @types/debug from 4.1.12 to 4.1.13 in the typescript group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1495
* chore(deps): bump vite from 8.0.0 to 8.0.1 in the development-dependencies group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1496
* chore(deps): bump eslint from 10.0.3 to 10.1.0 in the eslint group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1499
* chore(deps): bump marked from 17.0.4 to 17.0.5 in the production-dependencies group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1500
* chore(deps): bump jsdom from 29.0.0 to 29.0.1 in the development-dependencies group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1501
* chore(deps): bump flatted from 3.3.3 to 3.4.2 by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1497
* chore(deps): bump kysely from 0.28.11 to 0.28.13 in /api in the npm_and_yarn group across 1 directory by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1498
* fix: context menu move up/down checks collisions (#1462) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1504
* chore(deps): bump kysely from 0.28.13 to 0.28.14 in /api in the npm_and_yarn group across 1 directory by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1502
* fix: use unique SVG pattern IDs per rack instance (#1466) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1505
* fix: address CodeRabbit feedback on SVG pattern IDs (#1466) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1507
* chore(deps): bump the vitest group with 3 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1509
* chore(deps): bump eslint-plugin-svelte from 3.15.2 to 3.16.0 in the eslint group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1510
* chore(deps): bump the development-dependencies group with 2 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1514
* chore(ci): bump the actions group with 2 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1515
* chore(deps): bump svelte from 5.54.0 to 5.55.0 in the svelte group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1511
* chore(deps): bump eslint-plugin-testing-library from 7.16.1 to 7.16.2 in the eslint group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1518
* chore(deps): bump happy-dom from 20.8.4 to 20.8.7 in the development-dependencies group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1519
* chore(deps): bump the production-dependencies group with 2 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1513
* chore(deps): bump happy-dom from 20.8.7 to 20.8.8 in the development-dependencies group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1524
* chore(deps): bump @lucide/svelte from 1.6.0 to 1.7.0 in the production-dependencies group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1523
* chore(deps): bump picomatch from 4.0.3 to 4.0.4 by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1525
**Full Changelog**: https://github.com/RackulaLives/Rackula/compare/v0.9.2...v0.9.3v0.9.2 Nothing user-facing in this one! Entirely refactoring, dependency upgrades and e2e improvements. Trying to pay down some tech debt from rapid development with LLMs.
As always, please report any and every issue you see.
Thanks for using my project :) - @ggfevans
## What's Changed
* chore(deps): bump svelte from 5.53.9 to 5.53.10 in the svelte group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1450
* refactor: decompose App.svelte (#1395) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1451
* chore(deps): bump devalue from 5.6.3 to 5.6.4 by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1452
* chore(deps): bump the vitest group with 3 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1453
* chore(deps): bump @types/node from 25.4.0 to 25.5.0 in the typescript group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1455
* chore(deps): bump svelte from 5.53.10 to 5.53.11 in the svelte group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1454
* refactor(e2e): centralise CSS selectors into locators.ts by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1458
* feat(e2e): add createTestLayout() factory builder by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1457
* fix(e2e): replace flaky filechooser pattern with page.setInputFiles() by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1459
* refactor: extract drag-drop and context menu logic from Rack.svelte (… by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1460
* feat: separate layout naming from rack naming (#1005) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1463
* fix: clear containerHoverInfo on native DnD drop (#1397) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1468
* chore(deps): bump undici from 7.22.0 to 7.24.1 by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1469
* chore(deps): bump the development-dependencies group across 1 directory with 3 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1464
* fix: mark store dirty on device type auto-import by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1472
* fix: batch auto-import with placement for undo/redo (#1470) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1473
* refactor: extract raw mutators and command adapters from layout store (#1078) by @ggfevans in https://github.com/RackulaLives/Rackula/pull/1465
* chore(deps): bump @vitest/eslint-plugin from 1.6.11 to 1.6.12 in the vitest group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1485
* chore(deps): bump svelte from 5.53.11 to 5.53.12 in the svelte group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1486
* chore(deps): bump @types/umami-browser from 2.18.0 to 2.18.1 in the typescript group by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1487
* chore(ci): bump the actions group with 4 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1489
* chore(deps): bump the development-dependencies group with 3 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1490
* chore(deps): bump the production-dependencies group with 2 updates by @dependabot[bot] in https://github.com/RackulaLives/Rackula/pull/1488
**Full Changelog**: https://github.com/RackulaLives/Rackula/compare/v0.9.1...v0.9.2v0.9.1
### Added- Multi-rack share URL support with v2 schema (#1207, PR #1417)
- Session save flush on pagehide/beforeunload to prevent data loss (#1404, PR #1413)
- Reverse proxy, access control, and deployment scenario documentation (#1107, PR #1411)### Fixed
- Cross-browser drag tooltip positioning for Safari 26 and Firefox 148 (#1443, #1444, PR #1446)
- Circuit breaker reactivity and health-check reset for persistence auto-save (#1088, PR #1416, PR #1434)
- Surface user-facing feedback for previously silent failures (#1389-#1392, PR #1407)
- Keyboard viewport input type coverage using allowlist instead of exclusion list (#1115, PR #1408)
- Pin Bun 1.3.10 in Dockerfile and regenerate lockfile### Technical
- Migrate E2E selectors to data-testid (#1228, PR #1435)
- Repair migration E2E tests and archive format detection (#1401, PR #1437)
- Rewrite shelf-category E2E tests for accordion palette (#1400, PR #1406)
- Unskip device-name undo/redo and cross-rack metadata E2E tests (#1405, PR #1436)
- Eliminate waitForTimeout in E2E tests (#1224, PR #1414)
- Update stale E2E selectors and save filename assertions (#1261, #1263, PR #1412, PR #1415)
- Triage and fix disabled E2E tests (#1226, PR #1439)
- E2E testing architecture research spike (#1393, PR #1424)
- Trim SPEC.md from 2,482 to 184 lines (#1399)
- Dependency updates: Svelte 5.53.9, Hono 4.12.7, DOMPurify 3.3.2, simple-icons 16.11.0v0.9.0
### Added- Local authentication mode with username/password login (#1117, PR #1356)
- Move compatible-only toggle from device palette to Settings menu (#1361, PR #1379)### Fixed
- Export dialog preview clipped for tall racks (#1350, PR #1380)
- Defence-in-depth guards for duplicate device IDs preventing layout load (#1363, PR #1378)
- Stale auth documentation referencing removed environment variables (#1102, PR #1373)
- Restore Trivy scan gating in deploy-prod workflow (#1360, PR #1381)### Security
- Reject control characters in to prevent CRLF injection (#1371, PR #1382)
- Require OIDC issuer pinning when discovery URL is configured (#1372, PR #1382)v0.8.4 ## [0.8.4] - 2026-02-20
### Fixed
- Prevented container startup crash in persist deployments caused by unresolved `AUTH_MODE` values rendering invalid nginx config (`unknown "auth_mode" variable`) (#1297) - thanks @P4r4n01dB34r for reporting!
- Normalized auth mode at container entrypoint and restricted nginx auth-mode mapping to sanitized `RACKULA_AUTH_MODE` values (`none|oidc|local`) with safe fallback to `none`
### Security
- Remediated open Dependabot alerts by upgrading vulnerable dependencies: `jspdf` to `4.2.0`, `svelte` to `5.53.0` (with patched `devalue` `5.6.3`), and `hono` to `4.12.0`v0.8.3
### Fixed- Production deploy workflow now keeps Trivy SARIF gating aligned with configured severity () via , preventing medium/low advisories from blocking deploy
v0.8.2
### Technical- Recut release after the deploy workflow was cancelled during , to republish and container tags
v0.8.1 Bugfixes! Cheers to @marcuspee, @mihai-b and @moviemakr1620 for the reports. Also added the underpinnings of a future Proxmox LXC distribution method 🤫
### Added
- Separate Save from Save As: dedicated Save action for backend persistence, Save As for ZIP export (#1219, PR #1247)
- ProxmoxVE LXC distribution infrastructure (PR #1218)
### Fixed
- Half-width device slot_position not threaded through pointer-based move events (#1244, PR #1246)
- Half-width device slot_position not threaded through keyboard/context-menu move events (PR #1242)
- Safari drag-and-drop broken due to missing text/plain fallback (#1200, PR #1243)
- Settings menu gear icon broken by incorrect GroupHeading usage (#1203, PR #1241)
- Share link encoding failure on large layouts (#953, #1195, PR #1242)
- Duplicating half-width device linked state with original (#1195, PR #1242)
- Half-width device context menu opening at wrong position (#1193, PR #1242)
- Half-width second-device placement inconsistency in same RU (#1191, PR #1242)
### Technical
- Harden Playwright config for CI stability (#1223, PR #1232)
- Pin GitHub Actions to commit SHAs in build-lxc.yml (PR #1256)
- Consolidate E2E test helpers and migrate specs to gotoWithRack (#1225, PR #1249)
- Bump Svelte from 5.50.1 to 5.51.2 (PR #1204, #1252)
- Bump ESLint group, @vitest/eslint-plugin, typescript-eslint (PR #1250, #1251, #1257)
- Bump actions group with 4 updates (PR #1253)
- Bump simple-icons, qs, and production dependencies (PR #1206, #1217, #1220, #1221)v0.8.0 Woohoo! So this release was primarily focused on mobile. There is plenty more work to do, though it should be usable. We also sprinkled in tons of bug fixes and security-minded improvements around the API.
Next up on the path to v0.9 is authentication. See #1095
Cheers,
@ggfevans
### Added
- Mobile bottom navigation bar with Framework7-inspired design (#641, PR #1055, #1062, #1063)
- Slim toolbar mode for mobile viewports (PR #1054)
- Mobile file actions sheet (PR #1059)
- Rack indicator strip with navigation dots (PR #1056)
- Mobile view sheet controls (#643, PR #1058)
- Compact mobile toolbar quick actions (PR #1060)
- Mobile device library trigger in bottom nav (PR #1061)
- Mobile rack swipe navigation (PR #1076)
- Touch long-press context menus (PR #1086)
- Mobile floating undo/redo controls (#1046, PR #1098)
- Virtual keyboard viewport adaptation (#1049, PR #1097)
- Phase 1 NetBox homelab device import: 40 image-priority devices (#1109, PR #1134)
- Phase 2 NetBox homelab device expansion: 45 image-backed devices (#1111, PR #1188)
- E2E test infrastructure and wizard keyboard shortcuts (#903, PR #1128)
- Layout store contract safety net tests (#910, PR #1083)
- BottomSheet interaction test coverage (PR #1072)
### Changed
- Mobile warning modal updated with positive messaging (PR #1053)
- Mobile export/share dialogs made responsive (#1047, PR #1123, #1126)
- BottomSheet refactored to one-way open prop (PR #1073)
- Tokenized shared dialog mobile content padding (#1162, PR #1165)
### Fixed
- Start Screen startup path stabilized (#1122, PR #1168)
- Svelte a11y build warnings resolved (#1028, PR #1172)
- App.svelte state_referenced_locally warning resolved (#1171, PR #1179)
- Stale canvas touch listener lifecycle hardened (#1089, PR #1099)
- Swipe pan rejection aligned with dominance ratio (#1090, PR #1093)
- Swipe listener lifecycle and logging tightened (PR #1082)
- Swipe gesture review follow-ups addressed (PR #1081)
- Two-way binding to derived sheet state avoided (PR #1064)
- Selection store sync, a11y improvements, and Safari iOS dark rack colours (PR #1057)
- Persistence Start Screen integration into app launch flow (PR #1065)
- Firefox logo SVG decode errors and persistence health handling hardened (PR #1092)
- Keyboard viewport scroll excluded from select elements (#1103)
- Zip export folder names sanitized (PR #1074)
- Review & Clean Up action routed through real cleanup workflow (#1125, PR #1138)
- Dev deploy env persistence and checkout permissions fixed (#1147, PR #1148, #1149)
- Persistence health validation hardened to prevent false-positive API status (#1087, PR #1197)
- API typecheck errors in security and storage modules resolved (PR #1186, #1192)
### Security
- API CORS hardened and write-route auth defaults tightened (#1124, PR #1135)
- CORS explicitly configured for dev domain
### Technical
- Restored svelte-check/typecheck baseline (#1121, PR #1136)
- NetBox homelab device curation spike delivered (#1096, PR #1118)
- Authentication v1 architecture spike and ADR (#1100, PR #1167)
- Security threat model research document added (#1069, PR #1070)
- Nginx auth hardening section added to self-hosting guide (#1112, PR #1127)
- Self-hosting docs: storage paths, persistence setup, and audit checklist updated (PR #1156, #1157, #1159, #1163)
- Container/self-hosting runtime and CI guardrails tightened (#1155, PR #1161, #1169)
- .env.example expanded for persistence and API security vars (#1153, PR #1159)
- Deploy dev workflow and docker-compose updated
- Hoisted mock resets in cleanup prompt spec (#1150, PR #1158)
- Star history chart added to README (PR #1071, #1075)
- Bumped dependencies: svelte 5.49.1→5.50.0, simple-icons, @types/node, eslint, Playwright, and others (PR #1139, #1140, #1141, #1142, #1143, #1146)
- Updated copyright year and owner in LICENSE (PR #1166)
- YAML viewer/editor spike recommendations (#573, PR #1173)
- ESLint v10 peer dependency conflict reverted pending ecosystem support (#1198, PR #1199)