• v0.9.14 7587b40d87

    v0.9.14 Stable

    calum released this 2026-08-01 18:19:09 +01:00 | 34 commits to main since this release

    0.9.14 — Rack Drawing Build 2 of 3: rack definitions + drag-and-drop editor + frame-DXF pipeline (ADR-N086).

    Second build of the three-build Rack Drawing feature; the DELIVERABLE OUTPUT is Build 3. This build wires the plumbing.

    • Frame-DXF transfer + normalise. 24 core rack frame DXFs copied server-to-server from loud-engine's rack module into services/net-library/app/assets/rack_frames/. Front/Side × {600,800,1000} × {TOP,1U,BOTTOM,CASTORS}. Naming normalised on transfer to a single BOT convention. rack_frame.json single source for u_height_mm (44.45), per-width piece heights, and file references — mirrors Loud Engine's rack_layout_v1.json shape (report §4).

    • ezdxf parse + inline-SVG pipeline. New services/net-library/app/rack_dxf.py. ezdxf.readfile parse → INSERT block expansion (depth 12) → bbox.extents → LINE + LWPOLYLINE/POLYLINE only. LRU-cached by (path, mtime, size). Compose helper stacks TOP + 1U×N + BOTTOM + optional CASTORS at correct piece heights and emits a single inline SVG. Verified: 600×42U + castors → 2293.99 mm; 800×24U no castors → 1270.85 mm. Same pipeline will serve per-MODEL device CAD symbols in Build 3.

    • Rack model in project.sqlite. Two additive migrations (SCHEMA_VERSION 19 → 21, pre-migration backup automatic per ADR-N024). Placements' identity IS devices.id (the real project instance, NOT a floating catalogue symbol). height_u NOT stored — RESOLVED from library_models.u_height (ADR-N085) at read time per ADR-N077 pattern. UNIQUE(device_id) + UNIQUE(rack_id, position_u) + application-side span-overlap check in Rust.

    • Rust commands (commands/racks.rs). LAYOUT ONLY — rack list/upsert/delete + placement list/upsert/clear. upsert_rack_placement enforces: rack exists, device exists, model is rackable (u_height set), span fits, no overlap. Cross-database resolve via open_library_db.

    • Client — Racks tab + drag editor. New /racks (list + CRUD) and /racks/:id (editor). Editor is a TypeScript REBUILD of Loud Engine's three-part drag algorithm (docs/loudengine-rack-report.md §3): (a) DOM-marker hit-test — walk elementsFromPoint up to [data-rack-slot-u]; (b) pure-function occupancy/validity check in lib/racks.ts; (c) document-level pointer lifecycle. Sidebar shows filtered PROJECT DEVICES (rackable + not-in-any-rack, composeDeviceLabel-ordered) — no Engine "stage-a-symbol" step. Canvas is a CSS Grid tower (data-rack-slot-u markers, placed devices as buttons spanning gridRow: N / span heightU). Save/Cancel diff pattern parallel to SystemDiagramArrange. Build 2 uses LABELLED BLOCKS in editor; per-device DXF is Build 3's deliverable job.

    • Verified: cargo 226/226 pass (219 baseline + 7 new rack round-trip tests: CRUD, position round-trip, occupancy overlap rejection, catalogue-height reflection, editor writes no device/catalogue data, non-rackable device refuse, cascade delete). TSC + Vite clean. Backend catalogue counts intact 21/35/18/9/30 after redeploy. DOCKER-USER firewall lock intact (ADR-N069). ezdxf pipeline verified inside container. Screenshots recorded per ADR-N066.

    • NOT IN THIS BUILD (Build 3): the Rack Drawing DELIVERABLE (payload builder, POST /render/rack-drawing endpoint, shared-frame template, front+side views per rack, Generate All one-per-rack, ZIP packaging, hidden-line side-view treatment). Power-symbol library and 3D are out of scope.

    Downloads