Loud Project Engine and general operations management system.
  • Python 56.7%
  • JavaScript 37.9%
  • CSS 5%
  • HTML 0.2%
  • Shell 0.2%
Find a file
2026-08-11 17:24:57 +04:00
apps Refine site report document layout 2026-08-11 17:24:57 +04:00
docs Doc closeout: rack room ISO analytic HLR state + open blocker 2026-07-06 07:31:15 +04:00
infra/scripts v0.7: add phase6 deployment profile baseline 2026-02-20 17:10:51 +04:00
scripts Add CAD template designer and registry workflow 2026-04-05 07:25:50 +04:00
uploads Document repo handoff and server cleanup 2026-04-28 05:27:19 +04:00
.env.example v0.18 reporting workspace: backend site-reports lifecycle, AI regen/edit/delete UX, and venue identity fix 2026-02-26 23:18:39 +04:00
.gitignore Document repo handoff and server cleanup 2026-04-28 05:27:19 +04:00
buglog.md Close out site access session 2026-07-19 19:03:50 +04:00
changelog.md Refine site report document layout 2026-08-11 17:24:57 +04:00
continuation_prompt.md Refine site report document layout 2026-08-11 17:24:57 +04:00
docker-compose.yml v0.18 reporting workspace: backend site-reports lifecycle, AI regen/edit/delete UX, and venue identity fix 2026-02-26 23:18:39 +04:00
estimation_module_prompt.md Document repo handoff and server cleanup 2026-04-28 05:27:19 +04:00
featurelog.md Refine site report document layout 2026-08-11 17:24:57 +04:00
README.md Refine site report document layout 2026-08-11 17:24:57 +04:00

Loud Engine

Production-grade lighting infrastructure documentation platform.

Current Version

  • Working version: 0.9 (complete)
  • v0.12 closed: Deliverables Circuit Schedule (003.0) backend-locked generation and template finalization complete
  • v0.13 in progress: Circuit Schedule (003.0) multi-page pagination density + per-page frame cleanup applied
  • v0.13 in progress: Circuit Schedule (003.0) totals/advisory row now follows last data row with final-page fit guards
  • v0.13 in progress: Circuit Schedule (003.0) v3 flow layout corrected to stop totals/advisory from dropping to page bottom
  • v0.13 in progress: Dimmer Schedule (004.0) backend generation baseline added with DIM/EDIM-only rows, 4-channel grouping, and per-group subtotal rows
  • v0.13 in progress: Dimmer Schedule subtotal strip refined to compact right-aligned solid dark-grey bar (Dimmer N | * W | * A)
  • v0.13 in progress: Dimmer subtotal amps now round up to whole amps (0 decimal places)
  • v0.13 in progress: Dimmer subtotal W/A cells aligned to match row W/A column widths
  • v0.13 in progress: Dimmer subtotal PDF alignment fine-tuned to row-chip spacing/anchor geometry
  • v0.13 in progress: Dimmer header labels normalized for consistent typography across all header cells
  • v0.13 in progress: Dimmer whole-sheet total strip added (Total Load | * kW | * A) with watt-sum-derived kW and A (220V, ceil 1dp)
  • v0.13 in progress: Dimmer subtotal strips updated to lighter grey palette (total-load strip unchanged)
  • v0.13 in progress: Dimmer grouped pagination hardened so 4+subtotal blocks and trailing total strip do not split across pages
  • v0.13 in progress: Dimmer one-page space usage corrected by limiting reserve behavior to multi-page schedules
  • v0.13 in progress: Site Wide (006.0) backend generation baseline added with dedicated template/CSS and all-circuit-type rows
  • v0.13 in progress: Site Wide cell palette aligned to locked schedule style (Circuit colored chip; other active cells white; placeholders grey)
  • v0.13 in progress: Site Wide Circuit column width reduced to ~50% with adjacent column rebalance
  • v0.13 in progress: Site Wide header+rows horizontally scaled (~30% effective width gain) with title bar unchanged
  • v0.13 in progress: Site Wide scaling corrected to proportional scale-to-fit (no horizontal squash), with width compensation
  • v0.13 in progress: Site Wide typography aligned to locked schedule characteristics (bold headers, lighter body text, colored circuit prefix + bold black numeric suffix)
  • v0.13 in progress: Site Wide Rack width now matches locked Universe width, with centered text
  • v0.13 in progress: Site Wide Phase Load/Rack/Node now backend-contract fields with conditional greying only when values are missing
  • v0.13 in progress: Site Wide pagination now prioritizes fuller page usage (tail rebalance removed) with scaled-density row packing calibration in active tuning
  • v0.13 in progress: Site Wide moved from transform-based body scaling to intrinsic scaled row/header metrics to improve true page-fill behavior
  • v0.13 in progress: Site Wide intrinsic scale calibration narrowed to preserve prior visual proportions while maintaining full-page row packing and per-page frame chunking
  • v0.13 in progress: Site Wide now mirrors Circuit Schedule special type rules for GFS/ARC/ETH/FIB power-cell blank+grey behavior, with GFS/ARC DB source resolved via control-circuit mapping
  • v0.13 in progress: Site Wide DB rules aligned: GFS/ARC use control-circuit remap output; ETH/FIB render PoE only when wattage > 0 (else -)
  • v0.13 in progress: Site Wide (006.0) contract lock validation completed: backend row payload now includes control_circuit_* fields required for GFS/ARC remap generation parity
  • v0.13 in progress: Circuit Schedule source parity updated: ETH/FIB Source now follows conditional PoE rule (max_watts > 0) with - fallback
  • v0.13 in progress: Design workspace UX update: floating circular up-arrow button added to Site Wide Circuit Patch editor (appears on scroll-down, smooth-scrolls to top, hides near top)
  • v0.14 in progress: Deliverables CAD template baseline (001.0) started with PDF-native A1 composition (LIGHTING_PLAN_TEMPLATE) for viewport + right-sidebar metadata rendering
  • v0.14 in progress: Deliverables 001.0 CAD options dialog baseline added (opened from Options) with notes/revision/sidebar field inputs and temporary no-viewport render support for layout testing
  • v0.14 in progress: CAD compositor/runtime path alignment completed (/uploads in containers), with template fidelity pass to match owner blank frame geometry and tighter sidebar logo fit
  • v0.14 in progress: CAD field-mapping calibration started with owner-provided center-coordinate mapping for copyright text box
  • v0.14 in progress: Copyright disclaimer now backend-locked and rendered justified (11-line cap) in calibrated title-block box (dialog input removed from authority)
  • v0.14 in progress: Copyright disclaimer sizing tuned to target full 11-line fill in calibrated box
  • v0.14 in progress: Copyright disclaimer font tuned to 11.8pt (owner calibration pass)
  • v0.14 in progress: Notes header mapping updated; fixed NOTES title at 12.5pt bold now left-aligned with text-left edge x=734.5mm
  • v0.14 in progress: Notes body text region now mapped to owner-provided center/bounds (x=781.04, y=414.23, 93.2mm x 173.7mm)
  • v0.14 in progress: 001.0 Notes editor UX upgraded to a dedicated modal (Notes Section) with single-box rich input and inline Regular/Bold/Italic; backend notes renderer now supports italic + inline run flow
  • v0.14 in progress: Notes overflow guard pass applied: wider Notes editor, hard-wrap for unbroken text in UI, and backend hard-wrap in PDF renderer to prevent off-page spill
  • v0.14 in progress: Notes toolbar formatting fix: selection-preserving Regular/Bold/Italic now applies visibly in-editor and persists to output
  • v0.14 in progress: CAD options persistence hardened: saved Options/Notes now persist by project+stage+revision+doc, reopen reliably, and seed forward into newer revisions when empty
  • v0.14 in progress: Notes modal layout cleanup applied (calibration caption removed, compact uniform width, right-side dead space removed)
  • v0.14 in progress: 001.0 viewport upload workflow added: filename display + Upload action in Options dialog, persisted by project/stage/revision with carry-forward and historical recall by revision
  • v0.14 in progress: CAD viewport upload now validates source PDF page size (713mm x 575mm, ±1mm) before accepting server storage
  • v0.14 in progress: viewport upload stack now uses proper multipart file handling (python-multipart) in API runtime (temporary base64 workaround removed)
  • v0.14 in progress: viewport placement frame in compositor locked to owner geometry (713mm x 575mm, center x=364.5, y=299.41)
  • v0.18 in progress: Reporting workspace reset to shared Clients/Venues with backend Site Reports authority (letterhead PDF generation + manual/summary draft flow)
  • v0.18 in progress: Reporting post-generation lifecycle added (persisted report Edit with rich formatting + AI Regenerate, and latched Remove Report deletion mode)
  • v0.22 complete: Site Works Report PDFs use the LOUD letterhead content grid with refined typography, bold metadata labels, and a curated sign-off treatment
  • v0.20 in progress: Office user role added for quote-only internal operations, with backend-authoritative quote management access (clients, venues, grants, uploads, view/download/archive/delete)
  • v0.20 in progress: Deliverables workspace recovery hardened so issued rows can be reconstructed from backend-generated artifact authority when browser-local plan state is missing
  • v0.20 in progress: CAD deliverables now have a standalone backend-authoritative Template Designer with saved named templates, default template assignment, base-PDF upload, and mapped text/image field rendering
  • v0.20 in progress: Rack Drawing module architecture approved as a standalone backend subsystem, with DB-backed symbol/rack/slot contracts now started separately from the CAD template designer
  • v0.20 in progress: Rack Drawing now has a standalone app workspace (/rack-drawing) for symbol uploads, project rack definitions, backend-owned slot editing, paired device-library DXF assets, and backend render jobs
  • v0.20 in progress: Rack Drawing generated artifacts can now be previewed, downloaded, and deleted directly from the Rack Drawing workspace
  • v0.20 in progress: Rack device rendering now uses shared rack scale, hidden-line DXF output, paired FRONT / SIDE device assets, and DXF text-anchor handling rather than placeholder fit-to-box geometry
  • v0.20 in progress: 008.0 is now explicitly split out as a later Rack Room module with separate room/spatial rendering requirements
  • v0.20 in progress: Rack device assets now use the structured /opt/loud-engine/uploads/rack-symbols/devices/front and /opt/loud-engine/uploads/rack-symbols/devices/side folders and sync into a shared system-wide rack item library
  • v0.20 in progress: Rack slot equipment selection now supports searchable/autocomplete library lookup across projects
  • v0.20 in progress: Rack Layout editor replacement has been rebuilt around backend position_u slot semantics, preserving DOM-targeted drag/drop while removing the failed dual-coordinate draft model
  • v0.20 in progress: Rack Layout drag presentation now uses a consistent compact ghost across device heights while rack-slot preview remains the authority for true occupied span
  • v0.20 in progress: Cost Estimation backend baseline started with a standalone /api/v1/estimations module, DB-backed estimation projects/lines/FX snapshots, fixture-library commercial fields, locking/snapshot authority, and admin/designer-only access
  • v0.20 in progress: Cost Estimation currencies now support manual live refresh from the free open.er-api.com feed into backend-owned AED-normalized DB rates via an admin-only refresh action, keeping budgets stable until the operator explicitly pulls new rates
  • v0.20 in progress: Cost Estimation now has a backend regenerate action that rebuilds project-linked estimation lines from saved site-wide patch quantities while preserving manual advisory lines
  • v0.20 in progress: Cost Estimation now has a first internal web workspace with project-scoped advisory totals, current line breakdown, manual Pull Currency Rates, and backend-driven Regenerate Pricing
  • v0.20 in progress: Cost Estimation workspace now supports project pricing controls, line editing, and admin-owned fixture commercial defaults so regenerated pricing can be maintained from backend library data
  • v0.20 in progress: Cost Estimation workspace can now add linked estimation lines directly from the current project fixture library without requiring a full regenerate pass
  • v0.20 in progress: Cost Estimation now auto-derives cable and install allowances in backend calculations when project overrides are left at 0, with discounts applying to commercial products (products + cables) but not install
  • v0.21 closed: CAD 001.0 Logo Registry upload, vector viewport rendering, landscape normalization, title-comment project-location binding, and BOQ Advice module completed
  • v0.21 closed: BOQ Advice is backend-derived from the current saved Site Wide patch and project fixture library, excludes Decor Lighting (DL), preserves unresolved patch items as review warnings, and exports PDF/XLSX from the same adjusted backend payload
  • v0.21 closed: BOQ Advice supports project-scoped control-system devices, backend-owned reused/existing-kit Adjustment deductions, fixture-library-style dialogs, and adjusted UI/PDF/Excel totals
  • v0.22 in progress: Server Fixture Library now has optional backend-owned Brand and BOQ Ledger fields per system fixture row, editable from the admin server library UI
  • v0.22 in progress: Site Wide Circuit Patch rows now preserve backend fixture identity (project_fixture_entry_id + fixture_code) and BOQ Advice resolves by that identity so same-code server fixture renames propagate cleanly into patch/advice output
  • v0.22 in progress: Deliverables SHARE PACKAGE now supports both legacy completed export packages and current generated deliverable artifacts, with a skinned public client download page, individual-file/package download options, and backend download tracking
  • v0.22 in progress: Generated Circuit Schedule/Site Wide HP rows now use the HP deep-red schedule palette instead of falling back to HPD green
  • v0.22 in progress: Deliverables 020.0 MEP Specifications now has an Options flow to upload and choose active shared circuit-type spec PDF versions, then regenerates a merged project MEP specs PDF from the saved Site Wide Circuit Patch type order, with an incomplete cover/page-row pill when source pages are missing
  • v0.22 in progress: BOQ Advice control-system device rows now present as CS - Control System and Networking, with BOQ additional-kit storage fully migrated to CS-xx.0 codes and additional-kit rows also allowed in MI - Miscellaneous
  • v0.22 in progress: CS is now a first-class Server Fixture Library and Project Fixture Library section, while MI - Miscellaneous remains available for non-networking miscellaneous items
  • v0.22 in progress: BOQ Advice Additional Kit can add BOQ-only rows to CS or MI without affecting Circuit Patch
  • v0.22 in progress: BOQ Advice category output is backend-sorted so the original lighting/rack sections remain above, followed by CS - Control System and Networking, then MI - Miscellaneous as the final normal kit section
  • v0.22 in progress: BOQ Advice item output columns are Code | Brand | Order Code | Description | Qty across the page, PDF/HTML render, and XLSX export
  • v0.22 in progress: Server Fixture Library rows now include backend-owned BOQ price metadata with AED default currency plus GBP/EUR/USD options for future estimation-system use
  • v0.22 in progress: CAD Template Options now carry forward from prior project stages when the current stage has no saved options yet, while saving back only to the current stage scope
  • v0.22 in progress: CAD 001.H / 001.L options now seed from 001.0 when their own variant scope is empty, then remain isolated after saving
  • v0.22 in progress: Estimation workspace has been rebuilt around backend BOQ Advice data, Server Fixture Library BOQ retail pricing, Additional Kit rows, cable/install factors, discount, VAT, and category/section totals
  • v0.22 in progress: BOQ Additional Kit CS/MI rows are mirrored into the Server Fixture Library so Estimation can price and inline-edit them through the same system fixture backend
  • v0.22 in progress: Estimation-only Grouping can collapse selected current-project CS/MI items into named LOT-priced CS-00.x / MI-00.x quote rows without altering BOQ Advice or fixture libraries
  • v0.22 in progress: Server Fixture Library manual fixture codes now allow one-decimal suffixes such as LA-05.1; auto-numbering remains whole .0 only
  • v0.22 in progress: Site Wide Circuit Patch rows now sort numerically within each circuit type from the backend save/read contract, so a restored lower-numbered circuit slots back into order after Save
  • v0.22 in progress: Added HP - Hot Power as a normal power circuit type after EHPD and before GFS, and corrected TP to Track Power
  • v0.22 in progress: Generated Circuit Schedule and Site Wide deliverable CSS now includes the deep-red HP - Hot Power palette instead of falling back to HPD green
  • v0.22 in progress: Project Split module added as a non-destructive backend-owned split layer for BOQ Advice and Estimation, with retained phases, Boneyard reconciliation, phase-filtered BOQ exports, and phase Estimation totals
  • v0.22 in progress: Quotes Manage Venue now supports confirmed venue-name correction through the existing backend venue update contract for Admin/Office users
  • v0.22 in progress: Site Access quick issue now creates a complete issued access package from the selected client/venue/staff, includes active LOUD company documents, generates the HSE PDF, issues the backend package snapshot, creates a public attendance share link, and exposes Copy/Open/Download Package actions.
  • v0.22 in progress: Site Access package exports now use the browser-facing attendance share-link origin, flatten generated HSE PDFs, and write issued ZIPs to 001 Trade Licence, 002 RA & MS, 003 Staff Details, and 004 Insurance folders with site-specific documents at the archive root.
  • v0.22 closed for current Site Access scope: package history/delete, public package page, MS Agreement, Risk Assessment, ATP Permit + appended Staff List, staff document previews, flattened generated PDFs, and day-first generated document dates are complete for the owner-defined workflow.
  • v0.22 Site Access extension: issued package history now has Edit for marking permits granted; granted permits can be uploaded as PDF/JPEG/PNG, image uploads are converted to PDF, non-ATP permits are placed in the package root, ATP approved permits replace the generated ATP form with the staff-list page appended again, existing ZIP/share downloads are rebuilt, and GRANTED pills show in package history and the public access-package page.
  • v0.22 Site Access general permit extension: every issued package now includes a backend-generated, two-page LOUD General Permit Application with universal special-work requirements, client/venue authorization, selected-personnel identity details, optional digital LOUD signature placement, and ATP paperwork retained as an additional venue-specific form.
  • v0.22 Deliverables sharing extension: SHARE SELECTED added beside SHARE PACKAGE; operators can enter row-selection mode, choose issued generated deliverables, and create one public share link containing only those selected files.
  • v0.22 Deliverables revision control: revision dropdown now loads backend project revisions, always keeps Rev 0 available, opens on the latest revision, and includes New Revision to create/switch to a backend revision before uploading or regenerating files.
  • v0.22 Deliverables revision isolation follow-up: generated-artifact row state and rendered preview caches are now keyed by project/stage/revision so a new revision cannot inherit ISSUED pills or cached previews from an older revision. New Revision creation also skips revision numbers whose artifact folders already contain generated files from older frontend-only revision runs.
  • v0.22 CAD notes/options follow-up: 001.x CAD options revision rows now size short fields correctly, the Notes Section editor supports plain-text paste with preserved line breaks, and CAD template PDF notes auto-scale to fit the mapped notes body box. API and worker were restarted after the renderer change so regenerated CAD PDFs use the auto-fit path.
  • v0.22 Rack Room Drawing baseline: 008.0 now has a backend-owned rack-room layout contract, rack-core STEP asset discovery, and a Rack Room / 3D mini-CAD dialog for line/polygon drawing, snapping, door placement, and draggable rack placement next to Edit Rack Layout. The mini-CAD editor now behaves more like real CAD: scroll-zoom-to-cursor, pan (Pan tool / Space-drag / middle-mouse), click-drag or chained wall drawing with ortho/45° snapping, rack rotate snapping, automatic rack-to-wall dimension lines, an adaptive grid, and a live coordinate/length readout (all view-only, contract unchanged). The 008.0 ISO view is now rendered with EXACT analytic hidden-line (OpenCASCADE via FreeCAD TechDraw.projectEx), matching Vectorworks-native quality (opaque, smooth curves, full device detail, no tuning constants). Open blocker: device parts modelled as open shells render see-through (exact HLR needs closed solids); owner to re-export symbols as solids. Surrounding deliverable elements (room, containment, power, dimensions, labels, populated title block) not started - rack element first.
  • Site Access date convention: human-visible generated document dates are DD-MM-YYYY / DD/MM/YYYY; filename/date suffix tokens stay sortable YYYYMMDD; month-first display dates are not allowed.
  • Latest functional code commit before this documentation handoff: d2a57cb Auto-fit CAD notes text
  • Current default CAD template: LOUD GENERAL LIGHTING for 001.0
  • Next focus: new session should start from the current owner priority. Site Access is closed unless package testing reports a specific issue or a new venue-specific form is required.

Repository Remote

  • Canonical commit/push target: https://repo.calhta.com/calum/Loud-Engine.git
  • Remote name: origin
  • Transport: HTTPS only; SSH is not used for this repo handoff.
  • Git HTTPS user: calum
  • Server credentials are stored through the local Git credential helper, outside tracked files.
  • A session closeout commit must be pushed to origin/main; local-only commits are not considered complete unless the owner explicitly asks not to push.

Export Output Path Safety

  • Export artifact paths are restricted to EXPORT_OUTPUT_ROOT (default: /tmp/loud_engine_exports).
  • Absolute or relative paths outside that root are rejected with 422 invalid_export_output_path.
  • Public share-link URLs default to PUBLIC_SHARE_BASE_URL (default: http://localhost:8000).

Local Development (Scaffold)

  1. Copy env file:
    • cp .env.example .env
  2. Start stack:
    • docker compose up --build
  3. API health:
    • http://localhost:8000/health
    • http://localhost:8000/api/v1/system/health
  4. Web app:
    • http://localhost:5173

UI Kickoff (v0.6 baseline, expanded through v0.9)

  • Added branded dark-grey shell inspired by loud-dxb.com tone:
    • high-contrast monochrome baseline
    • bold uppercase hero typography
    • card-based module overview layout
  • Added theme toggle (dark/light) with logo switching.
  • Brand assets wired:
    • dark surfaces: /brand/loud-logo-white.png
    • light surfaces: /brand/loud-logo-black.png
  • New frontend files:
    • apps/web/src/styles.css
    • updated apps/web/src/main.jsx
    • reusable UI panels: apps/web/src/components/dashboardPanels.jsx
    • reusable auth/session hook: apps/web/src/hooks/useLoudSession.js
    • reusable dashboard orchestration hook: apps/web/src/hooks/useDashboardData.js
  • Frontend build scripts:
    • npm run build
    • npm run preview
  • Added first API-connected dashboard slice:
    • login form against JWT auth endpoints (/api/v1/auth/login, /api/v1/auth/refresh)
    • session persistence in browser storage with token refresh lifecycle handling
    • live project list (GET /api/v1/projects)
    • selected project detail context (name/code/stage/lock)
    • live validation summary + issue list for selected project (GET /api/v1/projects/{id}/validation)
    • live export stats and package list/detail for selected project:
      • GET /api/v1/projects/{id}/exports/stats
      • GET /api/v1/projects/{id}/exports
      • GET /api/v1/projects/{id}/exports/{export_package_id}
    • async export queue action from UI (POST /api/v1/projects/{id}/exports/generate-async)
    • package status transition control from UI (PATCH /api/v1/projects/{id}/exports/{export_package_id}/status)
    • export document controls in selected package panel:
      • template-aware add/replace (POST /api/v1/projects/{id}/exports/{export_package_id}/documents)
      • document delete (DELETE /api/v1/projects/{id}/exports/{export_package_id}/documents/{document_id})
      • template metadata source (GET /api/v1/reference/export-templates)
      • payload-field editor generated from template payload_schema
      • per-field payload validation hints before submit
    • async export task polling view (GET /api/v1/projects/{id}/exports/tasks/{task_id})
    • recent task shortcut list for quick re-polling
    • action feedback toasts for export + task operations
    • timeline-style action history panel for recent export/task events
    • action history taxonomy filters (all, generate, status, document, task, system)
    • copy-ready payload preview JSON block with one-click copy action
    • persistent action journal (browser storage-backed)
    • doc-type payload preset management (save/load/delete)
    • preset library transfer box for JSON export/import across browsers
    • preset transfer schema bundle (__meta.schema_version) for cross-version portability
    • preset import compatibility diagnostics (legacy vs versioned schema, imported counts)
    • optional encrypted preset transfer bundle (AES-GCM + passphrase) for sensitive workflows
    • shared dashboard response typedefs expanded for action journal and preset import diagnostics contracts
    • export panel distribution controls:
      • share-link creation/list with one-click URL copy
      • share-link lifecycle controls (deactivate/reactivate, expiry update, revoke)
      • share-link tracking visibility for total downloads + last download timestamp
      • share-link activity drill-down (filter + paged event rows)
      • sync-to-folder job trigger with inline status feedback
      • sync-job history list for selected export package
    • dedicated share-link tracking panel:
      • selected-project share-link list view
      • global share-link list view across projects
      • click-through event timeline with date/time and request metadata
      • server-side list filters (status + created/download date windows)
    • permit tracking panel:
      • selected-project and global permit lists
      • status-filtered permit scope views
      • click-through permit status timeline with date/time checkpoints
      • permit create/status-transition/approval controls
    • field callout tracking panel:
      • selected-project and global callout lists
      • status/priority/due filters
      • click-through callout status timeline and note trail
      • callout create/status-transition/note controls
    • report workflow panel:
      • selected-project and global report lists
      • manual authoring fields (summary + sections)
      • formatted rendered output preview
      • publish action + revision history tracking
    • collaboration workflow panel:
      • selected-project and global collaboration thread lists
      • status/priority/context filtered views
      • assignment + thread status updates
      • thread comments and review actions with traceable timeline
    • module navigation split:
      • core lighting operations remain on /
      • Site Attendance module shell mounted on /attendance with separated navigation placement
      • Site Attendance panel grouping now contains permits/callouts/reports/collaboration/share-link tracking
    • Site Attendance permissions baseline:
      • PROJECT_MANAGER has full write access for permits/callouts/reports/collaboration workflows
    • attendance package workflow baseline:
      • selected-project and global attendance package lists
      • attendance package create/update/issue controls
      • attendance package event timeline (created/updated/issued/status-changed)
      • package builder references for venue/staff/company-document IDs
    • attendance package share-link baseline:
      • package-level share-link issuance/listing/revoke controls
      • global + selected-project attendance share-link tracking
      • public no-auth attendance share page + JSON download endpoint
      • tracked events (view, download) with date/time trail
    • attendance staff database baseline:
      • selected-project and global staff record lists
      • mandatory identity fields: ID number, passport number, visa reference
      • optional license/certification list
      • create/update controls in Site Attendance module
    • attendance venue database baseline:
      • selected-project and global venue record lists
      • required venue code/name with duplicate-code protection per project
      • venue paperwork requirements, escape-route notes, and key contacts
      • create/update controls in Site Attendance module
    • attendance company document vault baseline:
      • global LOUD company document records for compliance and access templates
      • active-only filtering and document detail editing controls
      • code/title/type contracts with JSON payload metadata support
    • action journal retention controls (max entries, max age days, manual clear)
  • Added quick UX polish:
    • persisted theme choice in browser storage
    • refresh button for selected project data modules
    • clearer selected-project context and issue/status presentation
    • explicit export workflow guardrail hints (allowed status transitions, complete-package immutability)
    • Site Wide line universe field now resolves live from latest address-plan data per mapped circuit (circuit_id/circuit_tag with type+number fallback)
    • GFS lines now support control-circuit-driven universe rules (HPD/EHPD control source) with GFS-ID replacing load field
    • ARC lines now include backend ArcLamp intelligence (name-detected ArcLamp counts, computed ARC load, and auto driver/channel reference allocation such as ARC-150-01/1)
    • ARC rows now use staged Control Circuit behavior like GFS, and replace Load with Driver Patch to show computed ARC driver reference output (ARC-700-01/1 style)
    • ArcLamp allocation now prioritizes fewer total drivers by consuming existing spare channels across the project before creating new drivers; ARC includes a Calculate Driver Patch action for explicit non-save recomputation
    • VCN/EVCN/ETH/FIB rows now repurpose fields for network workflows: Universe -> ETH Patch; DB stays on VCN/EVCN and becomes read-only PoE on ETH/FIB; ETH/FIB Load -> VLAN-ID (fed from a minimal backend networking feed endpoint placeholder)
    • ETH auto legend baseline: default LCN Circuit, switches to sequential WAP_001 style when EAP device names are present, with manual legend override retained
    • Site Wide filename/save controls now float into the top page banner on long scroll so save state remains accessible
  • Frontend maintainability refactor:
    • moved large dashboard JSX blocks into focused component modules
    • kept API/state orchestration in main.jsx to preserve behavior while improving change velocity
    • extracted theme/session persistence + login/logout + token refresh lifecycle into useLoudSession
    • extracted project/export/template/task orchestration (loaders/actions/polling) into useDashboardData
    • added in-hook toast queue + payload normalization for schema-driven doc upsert inputs
  • Dev proxy enabled in Vite:
    • /api and /health route to API service in Docker dev (http://api:8000)

Database Bootstrap

  1. Apply baseline migration:
    • docker compose exec api alembic -c alembic.ini upgrade head
  2. Seed reference/lifecycle data:
    • docker compose exec api python -m app.db.seeds --profile reference
  3. Seed demo bootstrap data (optional for local dev):
    • docker compose exec api python -m app.db.seeds --profile demo

Auth (JWT Baseline)

  1. Login:
    • curl -sS -X POST http://localhost:8000/api/v1/auth/login -H 'Content-Type: application/json' -d '{"email":"admin@local.dev","password":"change_me_now"}'
  2. Use returned access_token:
    • curl -sS http://localhost:8000/api/v1/system/me/roles -H "Authorization: Bearer <ACCESS_TOKEN>"
  3. Refresh:
    • curl -sS -X POST http://localhost:8000/api/v1/auth/refresh -H 'Content-Type: application/json' -d '{"refresh_token":"<REFRESH_TOKEN>"}'

Project API (v0.5 baseline, expanded through v0.9)

  • GET /api/v1/projects
  • POST /api/v1/projects
  • GET /api/v1/projects/{project_id}
  • PATCH /api/v1/projects/{project_id}
  • GET /api/v1/projects/{project_id}/permits
  • GET /api/v1/projects/{project_id}/attendance/packages
  • GET /api/v1/projects/{project_id}/attendance/staff
  • POST /api/v1/projects/{project_id}/attendance/staff
  • GET /api/v1/projects/{project_id}/attendance/staff/{staff_id}
  • PATCH /api/v1/projects/{project_id}/attendance/staff/{staff_id}
  • GET /api/v1/projects/{project_id}/attendance/venues
  • POST /api/v1/projects/{project_id}/attendance/venues
  • GET /api/v1/projects/{project_id}/attendance/venues/{venue_id}
  • PATCH /api/v1/projects/{project_id}/attendance/venues/{venue_id}
  • POST /api/v1/projects/{project_id}/attendance/packages
  • GET /api/v1/projects/{project_id}/attendance/packages/{package_id}
  • PATCH /api/v1/projects/{project_id}/attendance/packages/{package_id}
  • POST /api/v1/projects/{project_id}/attendance/packages/{package_id}/issue
  • GET /api/v1/projects/{project_id}/attendance/packages/{package_id}/events
  • POST /api/v1/projects/{project_id}/attendance/packages/{package_id}/share-links
  • GET /api/v1/projects/{project_id}/attendance/packages/{package_id}/share-links
  • PATCH /api/v1/projects/{project_id}/attendance/packages/{package_id}/share-links/{share_link_id}
  • DELETE /api/v1/projects/{project_id}/attendance/packages/{package_id}/share-links/{share_link_id}
  • GET /api/v1/projects/{project_id}/attendance/packages/{package_id}/share-links/{share_link_id}/events
  • GET /api/v1/projects/{project_id}/attendance/share-links
  • POST /api/v1/projects/{project_id}/permits
  • GET /api/v1/projects/{project_id}/permits/{permit_id}
  • PATCH /api/v1/projects/{project_id}/permits/{permit_id}
  • POST /api/v1/projects/{project_id}/permits/{permit_id}/status-events
  • GET /api/v1/projects/{project_id}/permits/{permit_id}/status-events
  • POST /api/v1/projects/{project_id}/permits/{permit_id}/approvals
  • GET /api/v1/projects/{project_id}/permits/{permit_id}/approvals
  • GET /api/v1/projects/{project_id}/callouts
  • POST /api/v1/projects/{project_id}/callouts
  • GET /api/v1/projects/{project_id}/callouts/{callout_id}
  • PATCH /api/v1/projects/{project_id}/callouts/{callout_id}
  • POST /api/v1/projects/{project_id}/callouts/{callout_id}/status-events
  • GET /api/v1/projects/{project_id}/callouts/{callout_id}/status-events
  • POST /api/v1/projects/{project_id}/callouts/{callout_id}/notes
  • GET /api/v1/projects/{project_id}/callouts/{callout_id}/notes
  • GET /api/v1/projects/{project_id}/reports
  • POST /api/v1/projects/{project_id}/reports
  • GET /api/v1/projects/{project_id}/reports/{report_id}
  • PATCH /api/v1/projects/{project_id}/reports/{report_id}
  • POST /api/v1/projects/{project_id}/reports/{report_id}/publish
  • GET /api/v1/projects/{project_id}/reports/{report_id}/versions
  • GET /api/v1/projects/{project_id}/collaboration/threads
  • POST /api/v1/projects/{project_id}/collaboration/threads
  • GET /api/v1/projects/{project_id}/collaboration/threads/{thread_id}
  • PATCH /api/v1/projects/{project_id}/collaboration/threads/{thread_id}
  • GET /api/v1/projects/{project_id}/collaboration/threads/{thread_id}/comments
  • POST /api/v1/projects/{project_id}/collaboration/threads/{thread_id}/comments
  • GET /api/v1/projects/{project_id}/collaboration/threads/{thread_id}/review-actions
  • POST /api/v1/projects/{project_id}/collaboration/threads/{thread_id}/review-actions
  • GET /api/v1/projects/{project_id}/circuits
  • POST /api/v1/projects/{project_id}/circuits
  • PATCH /api/v1/projects/{project_id}/circuits/{circuit_id}
  • GET /api/v1/projects/{project_id}/fixtures
  • POST /api/v1/projects/{project_id}/fixtures
  • PATCH /api/v1/projects/{project_id}/fixtures/{fixture_id}
  • GET /api/v1/projects/{project_id}/address-plans
  • GET /api/v1/projects/{project_id}/address-plans/{plan_id}
  • POST /api/v1/projects/{project_id}/address-plans/generate
  • POST /api/v1/projects/{project_id}/address-plans/{plan_id}/freeze
  • POST /api/v1/projects/{project_id}/address-plans/{plan_id}/overrides
  • GET /api/v1/projects/{project_id}/stage-history
  • GET /api/v1/projects/{project_id}/audit-logs?limit=100
  • POST /api/v1/projects/{project_id}/stage-transitions
  • GET /api/v1/projects/{project_id}/site-wide-circuit-patch
  • POST /api/v1/projects/{project_id}/site-wide-circuit-patch/save
  • POST /api/v1/projects/{project_id}/site-wide-circuit-patch/calculate
  • GET /api/v1/projects/{project_id}/network/vlan-feed
  • GET /api/v1/projects/{project_id}/fixture-library
  • POST /api/v1/projects/{project_id}/fixture-library/entries
  • PATCH /api/v1/projects/{project_id}/fixture-library/entries/{entry_id}
  • DELETE /api/v1/projects/{project_id}/fixture-library/entries/{entry_id}
  • GET /api/v1/projects/{project_id}/fixture-library/system-search
  • GET /api/v1/projects/{project_id}/revisions
  • POST /api/v1/projects/{project_id}/revisions
  • GET /api/v1/projects/{project_id}/revisions/{revision_id}/diff?against_revision_id=...

Fixture Library API (v0.4 baseline)

  • GET /api/v1/fixture-types
  • POST /api/v1/fixture-types
  • GET /api/v1/fixture-types/{fixture_type_id}/versions
  • POST /api/v1/fixture-types/{fixture_type_id}/versions

Export API (v0.5 baseline, expanded through v0.9)

  • GET /api/v1/projects/{project_id}/exports
    • supports query params: status, limit, offset
  • GET /api/v1/projects/{project_id}/exports/stats
  • GET /api/v1/projects/{project_id}/validation
  • GET /api/v1/projects/{project_id}/exports/{export_package_id}
  • POST /api/v1/projects/{project_id}/exports/generate
    • supports optional idempotency_token to safely deduplicate retries
    • each document supports optional typed template_payload (validated by doc_type)
  • POST /api/v1/projects/{project_id}/exports/generate-async
    • async retries with the same idempotency_token now short-circuit to:
      • state='SUCCESS'
      • idempotent_hit=true
      • existing export_package_id
  • GET /api/v1/projects/{project_id}/exports/tasks/{task_id}
  • PATCH /api/v1/projects/{project_id}/exports/{export_package_id}/status
    • status transitions are constrained:
      • queued -> queued|processing|failed
      • processing -> processing|complete|failed
      • failed -> failed|queued
      • complete -> complete
    • transitioning to complete requires at least one export document
  • POST /api/v1/projects/{project_id}/exports/{export_package_id}/documents
    • blocked for completed packages (409 export_package_immutable_when_complete)
  • GET /api/v1/projects/{project_id}/exports/{export_package_id}/documents/{document_id}/preview
  • GET /api/v1/system/attendance/packages
  • GET /api/v1/system/attendance/staff
  • GET /api/v1/system/attendance/venues
  • GET /api/v1/system/attendance/company-documents
  • POST /api/v1/system/attendance/company-documents
  • GET /api/v1/system/attendance/company-documents/{document_id}
  • PATCH /api/v1/system/attendance/company-documents/{document_id}
  • GET /api/v1/system/attendance/share-links
  • GET /api/v1/public/attendance-share-links/{share_token}
  • GET /api/v1/public/attendance-share-links/{share_token}/download.json
  • DELETE /api/v1/projects/{project_id}/exports/{export_package_id}/documents/{document_id}
  • DELETE /api/v1/projects/{project_id}/exports/{export_package_id}
    • blocked while package is processing (409 export_package_processing_delete_forbidden)
  • Distribution contract endpoints:
    • GET /api/v1/system/distribution/share-links
    • GET /api/v1/projects/{project_id}/distribution/share-links
    • POST /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/share-links
      • supports package scope (default)
      • supports single-file scope via:
        • document_ids (export-document scoped), or
        • issued-artifact scoped payload (artifact_stage_name, artifact_revision, artifact_code, artifact_file_path)
    • GET /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/share-links
    • PATCH /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/share-links/{share_link_id}
    • DELETE /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/share-links/{share_link_id}
      • lifecycle revoke/deactivate (can be re-enabled via PATCH is_active=true)
    • DELETE /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/share-links/{share_link_id}/permanent
      • permanent share-link delete (does not delete source export files)
    • GET /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/share-links/{share_link_id}/events
    • POST /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/sync-jobs
    • GET /api/v1/projects/{project_id}/exports/{export_package_id}/distribution/sync-jobs

Share-link list filters supported on global and project list endpoints:

  • status: active | inactive | revoked | expired
  • created_from, created_to (ISO datetime)
  • download_from, download_to (ISO datetime; based on doc/zip download events)

Public distribution endpoints:

  • GET /api/v1/public/share-links/{share_token}
  • GET /api/v1/public/share-links/{share_token}/documents/{document_id}
  • GET /api/v1/public/share-links/{share_token}/download.zip

Public web route:

  • /public/share/{share_token} renders a package page with:
    • package metadata
    • explicit scope metadata (package or single file, including issued-artifact share links)
    • lightweight package access counters (views/file downloads/ZIP downloads)
    • per-document download actions
    • one-click full ZIP download

Task polling now returns progress metadata when available:

  • progress_percent
  • detail.message

Reference API

  • GET /api/v1/reference/export-templates
    • now includes payload_schema metadata per doc type/template version
    • LIGHTING_PLAN_TEMPLATE template available for A1 CAD viewport composition into 001.0 layout frame with sidebar metadata fields
    • CIRCUIT_SCHEDULE now includes include_dimmers payload control (default false)
    • DIMMER_SCHEDULE template available for dimmable-only circuit schedule output
    • SHOW_POWER_SCHEDULE template available with voltage-based total/domain load summaries
    • SITE_WIDE_CIRCUIT_PATCH template available with patched/unpatched circuit mapping summaries
    • CAT6_PATCH_SHEET, ARTNET_NODE_PATCH_SHEET, and BOQ_ADVICE template contracts are available

System API

  • GET /api/v1/system/fixture-library (admin)
  • POST /api/v1/system/fixture-library/items (admin)
  • PATCH /api/v1/system/fixture-library/items/{item_id} (admin)
  • DELETE /api/v1/system/fixture-library/items/{item_id} (admin; permanent delete across linked project entries)
  • GET /api/v1/system/validation/projects
    • supports query params: limit, offset, errors_only
  • GET /api/v1/system/permits
    • supports query params: status, limit, offset
  • GET /api/v1/system/callouts
    • supports query params: status, priority, due_from, due_to, limit, offset
  • GET /api/v1/system/reports
    • supports query params: status, report_type, limit, offset
  • GET /api/v1/system/collaboration/threads
    • supports query params: status, priority, context_type, limit, offset

Validation responses include explicit blocking semantics:

  • project validation payload now includes has_blocking_issues, blocking_issue_count, validation_policy
  • system validation summary now includes has_blocking_issues, blocking_issue_count
  • stage rulesets can now override validation behavior per issue code via validation_policy.issue_overrides
    • supports severity (warning|error), blocking (true|false), and disabled (true|false)

Test Scaffolding (v0.5)

  • apps/api/tests/test_export_service.py
  • apps/api/tests/test_permit_service.py
  • apps/api/tests/test_callout_service.py
  • apps/api/tests/test_report_service.py
  • apps/api/tests/test_collaboration_service.py
  • apps/api/tests/test_validation_service.py
  • run in container: docker compose exec api pytest -q tests
  • API integration scaffold:
    • apps/api/tests/integration/test_export_lifecycle_api.py
    • apps/api/tests/integration/test_validation_stage_async_api.py
    • run from worker container against live API:
      • docker compose exec worker env RUN_API_INTEGRATION=1 API_BASE_URL=http://api:8000 pytest -q /app/tests/integration

Test Strategy (v0.7)

  • Strategy doc: docs/quality/test-strategy-v0.7.md
  • Seed strategy doc: docs/quality/seed-strategy-v0.7.md
  • Backup/restore runbook: docs/operations/backup-restore-v0.7.md
  • Observability runbook: docs/operations/observability-v0.7.md
  • Deployment runbook: docs/operations/deployment-debian-compose-v0.7.md
  • Standard local matrix script:
    • infra/scripts/run-test-matrix.sh
  • Backup/restore scripts:
    • infra/scripts/backup-runtime.sh
    • infra/scripts/restore-runtime.sh
    • infra/scripts/deploy-compose.sh

Observability env controls:

  • LOG_LEVEL (default INFO)
  • ENABLE_REQUEST_LOGGING (default true)
  • API pytest markers:
    • unit
    • service
    • api_integration

Audit API

  • GET /api/v1/projects/{project_id}/audit-logs
    • supports query params: limit, entity_name, action

Current Artifacts

  • Database baseline: docs/architecture/data-model-v0.1.md
  • SQL baseline: docs/architecture/schema-v0.1.sql
  • Lifecycle ruleset: docs/architecture/lifecycle-ruleset-v0.1.md
  • Permit baseline: docs/architecture/permit-management-v0.7.md
  • Callout baseline: docs/architecture/callout-tracking-v0.7.md
  • Report workflow baseline: docs/architecture/report-workflows-v0.7.md
  • Collaboration workflow baseline: docs/architecture/collaboration-workflows-v0.7.md
  • Product backlog: featurelog.md
  • Change tracking + operating laws: changelog.md

Notes

  • PM role currently has write access for Site Attendance workflows; finer-grained permission tuning remains deferred.
  • Transition gating uses lifecycle ruleset policies including required export document types.
  • AI-assisted report drafting is deferred as a future module; v0.7 reports remain manual-entry and fully trackable.
  • CAD template preview/regenerate can run long on heavy viewport PDFs; dev proxy timeout is set to 10 minutes in apps/web/vite.config.js for /api and /health.
  • 001.0 CAD viewport uploads are preprocessed into cached raster artifacts (cad-viewports-cache/{sha256}.png) for fallback resilience; generated deliverables use the uploaded vector PDF whenever available.
  • 001.0 generation is fidelity-locked to vector viewport merge whenever source PDF is available; raster cache is fallback-only.
  • 001.0 regenerate now uses async task orchestration (preview-pdf-async + task polling + download endpoint) to avoid long blocking HTTP render requests.
  • Deliverables UI now surfaces CAD regenerate stage text with animated activity bars for 001.0 (preparing / rendering / finalizing).
  • generated CAD PDFs are post-processed with lossless Ghostscript optimization (no downsampling), and optimized output is used only when smaller.
  • Deliverables action row includes REGENERATE PACKAGE with In Place and New Revision queueing flows for submission-wide regeneration.
  • package regenerate queue state is persisted client-side and auto-resumes after refresh; all rows display queue lifecycle states (queued / running / complete) during package runs.
  • deliverables row regenerate action width is fixed to prevent progress/status layout shift while a row transitions to Regenerating....
  • package row progress indicators are cleared automatically after package completion (including resumed runs after refresh).
  • REGENERATE PACKAGE is right-aligned in the Deliverables action row for stable control placement.
  • 002.0 is now wired as upload-only CAD (.dwg) with row-level Upload dialog and regenerate/export rename flow; revision 0 omits revision suffix in filename while revision 1+ appends rev.xx.
  • CAD upload dialogs now retain and display the original uploaded filename (tracking label) even after regenerate/export applies LOUD output renaming.
  • Deliverables row Upload now opens the same upload-dialog pattern for both 001.0 and 002.0 (with type-specific file rules: 001.0 PDF, 002.0 DWG).
  • Upload action is intentionally hidden (with preserved row-action gap alignment) for 003.0, 004.0, 006.0, and 020.0.
  • Deliverables row action label is scope-aware: button shows Generate until first successful render for the current project + stage + revision + code, then switches to Regenerate.
  • Generate/Regenerate label now includes artifact-presence fallback signals for existing scopes (render cache, CAD upload presence, and completed export package in scope) so established rows do not falsely reset to Generate.
  • Deliverables row action columns are now explicit slot-aligned (including Options/Upload gaps) to keep all button columns visually aligned across rows.
  • Backend now exposes generated-artifact authority endpoints per stage/revision scope; row regenerate persists rendered outputs server-side and export prioritizes server-stored artifacts.
  • Deliverables selection plans are now also persisted server-side per project + stage + revision (deliverables-plans/...) and auto-synced from the UI, so issued package composition survives browser/local-storage loss.
  • 001.x CAD template geometry now has a versioned backend manifest authority at apps/api/app/assets/cad_layout_v1.json; the compositor loads layout coordinates/slots from that manifest instead of relying only on scattered code constants.
  • CAD-missing generate failures now set a scope-persisted inline warning banner beside the deliverable title and keep it across refresh until successful generation clears it.
  • Non-negotiable engineering rule: deliverables generation state is backend-authoritative and persisted; UI-only draft truth is disallowed.
  • Generated artifact storage now separates internal server filename from user-facing filename; downloads/share naming uses canonical human filename (with compatibility fallback for older artifacts).
  • Expected CAD-missing generate failures are handled inline on the deliverable row and no longer emit raw global error-card codes.
  • Client download helper now preserves deliverable extensions (including .dwg) and no longer forces .pdf suffix on non-PDF files.
  • Backend now enforces canonical user-facing naming policy for 001.0 and 002.0 generated artifacts (including .dwg extension guarantee for 002.0).
  • 002.0 generate path now hard-requires DWG source; non-DWG legacy scoped files are rejected instead of being renamed/exported as PDF variants.
  • CAD upload endpoints now preserve the operator-uploaded filename for stored source files (no sanitize/UUID rename), so upload dialog tracking reflects the true upload name.
  • CAD upload dialogs now support editable source filename labels and post them to backend (original_name_override) to handle short-alias filename environments (e.g. browser-provided ~1 names).
  • CAD template family now includes 001.0, 001.H, and 001.L on the same backend-first pipeline (PDF upload + options + async regenerate/export/view), with code-specific naming and titles.
  • CAD template family now also includes 007.0 and 008.0 with the same workflow parity (PDF upload + options + async regenerate/export/view) and code-specific naming/titles.
  • Dynamic 010.* detail-drawing deliverables now use the same CAD template workflow parity (PDF upload + options + async regenerate/export/view), including per-row title baselines and discovered generated-artifact status.
  • Distribution share links now persist origin-aware host metadata (share_base_url) at creation time and generate public URLs from the accessed system host instead of localhost/IP fallbacks.
  • Deliverables workspace now supports package-level share creation (SHARE PACKAGE) and single-file share link creation per row (Share) when a complete package exists for the selected stage/revision.
  • Deliverables rows now show an ISSUED tick when backend generated-artifact authority confirms an issued file exists for current project/stage/revision/code.
  • Row-level Share now uses issued-artifact authority (not export-doc-type mapping), so CAD/hybrid rows with doc_type = null can still be shared after regenerate.
  • Share creation now opens a copy-first modal UX: click link field to copy and auto-close, with explicit Cancel option.
  • Public share links now include social-preview metadata (Open Graph / Twitter) with LOUD branding image so pasted links can render rich preview cards in chat tools that support URL unfurling.
  • Share preview image now uses dedicated asset path: /brand/share-preview-logo.png (source managed in apps/web/public/brand/share-preview-logo.png).
  • Share preview description follows: Secure Link: ProjectStatus - Venue - Revision, with runtime public-share values injected from loaded share payload.
  • Public share URLs are canonicalized as /public/share/{token}.
  • Web server now injects per-token public-share metadata for /public/share/{token} at request time (Vite middleware), so unfurl clients receive true values:
    • Secure Link: {ProjectStatus} - {Venue} - Rev {revision_no}
  • Public share payload now emits stage display labels (owner-facing status) instead of internal canonical stage keys (e.g. Detailed Design instead of Coordinated).
  • Sharing is now a dedicated top-level module with grouped tracking by project/stage and row-level controls: revoke/re-enable, permanent link delete, URL copy, and download counters.
    • POST /api/v1/projects/{project_id}/deliverables/generated-artifacts/share-links
      • creates single-file public share links directly from issued generated artifacts (stage/revision/code/file path payload), without requiring an already-complete export package in that scope.
  • Site Attendance package payloads now resolve to a backend-owned canonical access structure (001 Trade Licence, 002 RA & MS, 003 Staff Details, 004 Insurance, 005 Venue Specific) using selected venue/staff/company-document refs.
  • Site Attendance package payloads now include backend-generated expiry_alerts for company docs and staff ID/passport/visa timelines.
  • Company document vault now supports explicit expiry controls (expires_at, warning_days) and computed status flags (is_expired, is_expiring) via backend contracts.
  • Project attendance now exposes expiry monitoring endpoint:
    • GET /api/v1/projects/{project_id}/attendance/alerts/expiry?warning_window_days=45
  • Site attendance now supports file-backed package sharing:
    • issue action snapshots referenced package files into /uploads/attendance-packages/{project_id}/{package_id}/issue-{timestamp}/
    • public attendance share links expose:
      • per-file download (/api/v1/public/attendance-share-links/{token}/documents/{document_id})
      • package ZIP download (/api/v1/public/attendance-share-links/{token}/download.zip)
      • JSON payload download remains available (/api/v1/public/attendance-share-links/{token}/download.json)
  • New upload endpoints for attendance sources:
    • POST /api/v1/system/attendance/company-documents/{document_id}/upload (multipart)
    • POST /api/v1/projects/{project_id}/attendance/staff/{staff_id}/documents/upload (multipart)
  • Attendance module UI now includes operator upload controls for:
    • selected company document file (vault panel)
    • selected staff member document (staff panel)
  • New standalone operations reporting backend domain is now available and intentionally separate from design-build projects:
    • distinct venue registry (ops_reporting_venues)
    • attendance call records (ops_reporting_attendance_calls)
    • reporting records (ops_reporting_reports)
  • New reporting APIs (system scope):
    • GET/POST/PATCH /api/v1/system/ops-reporting/venues
    • GET/POST/PATCH /api/v1/system/ops-reporting/attendance-calls
    • GET/POST/PATCH /api/v1/system/ops-reporting/reports
    • POST /api/v1/system/ops-reporting/reports/{report_id}/issue
  • UI navigation now includes dedicated Reporting module beside Site Attendance.
  • Reporting module now includes a working operator UI for:
    • ops venue creation/selection
    • attendance-call creation/selection (scoped to selected venue)
    • report creation/listing/issue flow (scoped to selected attendance call, with status filtering).
  • Current Site Works Report PDF composition aligns the report title, metadata, body, and sign-off with the supplied letterhead logo/footer margins. Regeneration applies this layout to saved manual or AI-assisted reports without changing their content.
  • Reporting summary generation can run against local Ollama for real LLM rewriting:
    • compose service: ollama (docker compose up -d ollama)
    • configured via:
      • SITE_REPORT_AI_OLLAMA_URL=http://ollama:11434
      • SITE_REPORT_AI_OLLAMA_MODEL=qwen2.5:7b-instruct
    • first-time model pull:
      • docker compose exec ollama ollama pull qwen2.5:7b-instruct
    • backend falls back to deterministic heuristic summary only when Ollama is unavailable or generation fails.
  • Quotes repository baseline is now available:
    • finance quote PDF upload + storage (server-retained)
    • quote indexing by ops venue + client name
    • backend PDF text analysis for extracted title/total metadata
    • searchable quote listing and authenticated quote download endpoints.
  • Quotes workflow upgraded to backend-first v0.17 contracts:
    • dedicated quote entities and grants now exist:
      • ops_quote_clients
      • ops_quote_venues
      • ops_quote_client_access
      • ops_quote_venue_access
      • ops_quote_documents
    • parse/finalize lifecycle is backend-owned:
      • POST /api/v1/system/quotes/parse (parse-only, no persistence)
      • POST /api/v1/system/quotes/upload (final persistence + rename policy)
      • final quote filename contract:
        • Venue - Location - QuoteNumber.pdf
        • venue/location abbreviations override full labels when configured.
      • date parser supports month-name, slash, hyphen, and dot numeric formats (including DD.MM.YYYY).
      • flattened-header hardening: explicit full-text Date: extraction with Expiry Date exclusion plus filename fallback (DDMMYYYY) when needed.
      • notes parser supports Item Description and Description headings, including flattened same-line note+heading extraction.
    • storage path now scales by client/venue/year/month:
      • uploads/quotes/{client_id}/{venue_id}/{year}/{month}/...
    • internal management APIs added for client/venue CRUD and grant/revoke:
      • GET/POST /api/v1/system/quote-clients
      • GET/POST /api/v1/system/quote-clients/{client_id}/venues (POST accepts optional name_abbreviation / location_abbreviation)
      • PATCH /api/v1/system/quote-venues/{venue_id} (venue naming overrides for file token precedence)
      • POST /api/v1/system/quote-clients/{client_id}/grant|revoke
      • POST /api/v1/system/quote-venues/{venue_id}/grant|revoke
      • GET /api/v1/system/quote-venues/{venue_id}/quotes
      • DELETE /api/v1/system/quotes/{quote_id}
      • POST /api/v1/system/quotes/{quote_id}/archive
    • venue-level filename token overrides are now backend-managed:
      • optional name_abbreviation and location_abbreviation persisted on ops_quote_venues
      • when present, these override venue/location tokens in generated quote filenames.
    • shared venue identity contract (Quotes/Site Access/Reporting):
      • venue uniqueness is client + venue_name + location (case-insensitive),
      • allowing multiple branches with the same brand name under one client.
  • New CLIENT role is now supported:
    • client users can be provisioned via Settings -> Manage Users (Client)
    • client users are restricted to dedicated quote-view area only (no access to internal project modules)
    • venue-scoped access control for client users is backend-managed via client-to-venue assignments.
  • Client portal quote APIs expanded:
    • GET /api/v1/client/quote-portal/summary
    • POST /api/v1/client/quotes/{quote_id}/archive
  • Quotes UI refinement notes (v0.17):
    • internal module now uses explicit Venues / Users and Upload split-pane labeling.
    • staged upload review displays backend-parsed fields as read-only summary before finalize.
    • client/venue listing emphasizes recency ordering and compact scroll density for operator speed.
    • visual polish pass applied for selected-row clarity, upload empty-state composition, and grant/revoke suggestion-list ergonomics.
    • client quote portal browser-tab branding is client-session scoped:
      • tab title: Loud Quote Portal
      • favicon: system-theme aware
        • dark mode: /brand/loud-logo-white.png
        • light mode: /brand/loud-logo-black.png
    • client quote portal username displays as a grey pill badge for immediate account-context clarity.
    • subtle spacing buffer added between username pill and client-name line for readability.
    • client quote portal mobile topbar behavior:
      • no refresh button
      • top-right action row with Light/Dark to the left of Sign Out.
      • compact theme-toggle label in portal mode: Light / Dark.
      • Project Engine subtitle remains visible under LOUD logo in compact centered form.
    • client quote portal mobile quote rows now display normalized identity:
      • Venue - Location
      • QU-*
      • with quote date value directly underneath.
    • quote-row Archive and Download actions are right-pushed and held in a stable single-row alignment group.
    • client portal quote-row actions now stack vertically (Archive above Download) while staying right-aligned.
    • desktop client portal quote-row actions render on one line (Archive, Download) while mobile remains vertically stacked.
    • archived client-portal quotes support 2-second press-and-hold unarchive interaction.
    • mobile QU-* line has a slight font-size bump for readability.
    • mobile quote identity block (Venue - Location, QU-*, date) is center-aligned.
    • mobile quote rows include notes line between QU-* and date in reduced text size.
    • desktop quote rows show notes and date on the same second metadata line (notes first, date second).
    • desktop notes/date metadata line includes | separator between notes and date.
    • desktop separator spacing tuned with slightly larger post-| gap.
    • portal quote title display omits trailing .pdf extension for cleaner UI.
  • Backend Contract Law (permanent):
    • business rules and persistence authority live in backend services/contracts.
    • frontend is orchestration/presentation only; no parallel/fallback business rule implementations.
    • conflicting or duplicated backend behavior is treated as a bug and logged for repair (buglog.md).
  • Server Fixture Library edits (admin settings dialog) now persist reliably and propagate to linked Project Fixture Library entries, including fixture attributes (wattage, dmx_channels, weight, order_code) as well as name/code.
  • Circuit field terminology now uses Termination in operator-facing UI and deliverable schedule headers (003.0, 004.0, 006.0); backend storage keys remain unchanged to preserve existing data.
  • Site Wide Circuit Patch now supports Add Copy per circuit type section:
    • duplicates the latest line in that type as a starting point
    • assigns the next sequential circuit number
    • preserves existing Add behavior for blank new lines.
  • Site Wide Circuit Patch network-row label refinement:
    • ETH/FIB PoE field is now labeled Termination (UI terminology alignment only).
  • Site Wide Circuit Patch ETH/FIB termination behavior now matches other non-control circuits:
    • field is editable text (no PoE auto-value substitution)
    • deliverables (003.0, 006.0) render entered termination text directly.
  • Site Wide Circuit Patch ETH/FIB termination save persistence fixed:
    • ETH/FIB termination values are no longer cleared during frontend normalize/save cycles.
    • ETH/FIB now persist custom text entries (e.g. Main Rack) exactly like other termination fields.
  • Site Wide Circuit Patch ETH description edit persistence hardened:
    • normalized description section fallback logic now avoids rehydrating stale split-section fragments.
    • ETH descriptions now persist cleanly after save without legacy section-data reversion behavior.
  • Site Wide Circuit Patch Add Copy now supports row-select copy mode:
    • pressing Add Copy enters per-type copy mode instead of cloning last row immediately.
    • a green tick selector appears on each row (same slot as remove X).
    • selecting a row copies that rows data into the next sequential circuit number, then exits copy mode for that type.
  • CAD options dialog now supports viewport-file removal for fast alignment iterations:
    • Remove PDF button added beside Upload in 001.0 CAD viewport controls.
    • action clears scoped viewport path/raster/filename fields from CAD options store without affecting generated artifacts.
  • CAD overlay status label calibration update:
    • added explicit bold Status: text on the PDF overlay.
    • positioned from A1 bottom-left coordinate input at top-left anchor:
      • x=734.44, y=275.6.
  • CAD overlay notes heading punctuation update:
    • notes heading now renders as NOTES: (with trailing colon).
  • CAD overlay status value calibration update:
    • backend project-status value field now renders center/center at:
      • x=781.05, y=271.64
    • font size set to 13pt.
  • CAD overlay consultant label calibration update:
    • added bold left-aligned Lighting Consultant: label.
    • top-left anchored at:
      • x=734.44, y=257.6
    • font size set to 10pt.
  • CAD overlay party label calibration update:
    • added bold left-aligned labels:
      • Client: at x=734.44, y=210
      • Interior Designer: at x=734.44, y=190
    • both top-left anchored, 10pt.
  • CAD overlay title-block label expansion:
    • added bold left-aligned labels (top-left anchored, 10pt):
      • Main Contractor: at x=734.44, y=170
      • MEP Contractor: at x=734.44, y=150
      • Lighting Integrator: at x=734.44, y=130
      • As Per Drawing: at x=734.44, y=102
      • Site: at x=734.44, y=69
      • Title: at x=734.44, y=49
      • Scale At A1: at x=734.44, y=29
  • CAD overlay status/title-block vertical tune:
    • moved all fields from Status: through Revision: down by 2.0mm as a uniform Y shift.
  • CAD overlay lower title-block refinement (Scale through Revision):
    • moved this subset back up by 1.0mm (half of prior down-shift).
    • reduced label font size for this subset by 0.2pt (10.0pt -> 9.8pt).
  • CAD overlay lower title-block micro refinement (Scale through Revision):
    • moved this subset up by an additional 0.5mm.
    • reduced label font size by a further 0.1pt (9.8pt -> 9.7pt).
  • CAD overlay consultant/party label typography refinement:
    • reduced label size by 0.2pt for:
      • Client
      • Interior Designer
      • Main Contractor
      • MEP Contractor
      • Lighting Integrator
      • As Per Drawing
  • CAD overlay consultant/title-block follow-up refinement:
    • reduced label size by 0.2pt for:
      • Lighting Consultant
      • Site
      • Title
    • moved this display group up by 0.5mm:
      • Lighting Consultant
      • Client
      • Interior Designer
      • Main Contractor
      • MEP Contractor
      • Lighting Integrator
      • Site
      • Title
  • CAD notes heading typography refinement:
    • reduced NOTES: heading font by 0.2pt (12.5pt -> 12.3pt).
  • CAD status value positional refinement:
    • moved project status value field (not Status: label) up by 0.5mm.
  • CAD logo registry workflow (backend-authoritative) is now available:
    • added global system logo registry for CAD roles:
      • Client
      • Interior Designer
      • Main Contractor
      • MEP Contractor
      • Lighting Consultant
      • Lighting Integrator
    • CAD options dialog now uses backend-driven dropdowns for these roles (no manual path typing).
    • each role row supports Upload:
      • prompts for server display name
      • accepts image file from local machine
      • stores logo in server uploads + registry
      • uploaded logo becomes selectable in dropdown and is auto-selected for current CAD options scope.
    • migration required before use:
      • apps/api/alembic/versions/0026_cad_logo_registry.py
  • CAD logo placement calibration (center-point coordinates) and scale policy:
    • removed extra logo downscale factor in CAD compositor (full slot-fit, no additional shrink multiplier).
    • updated center-point placement for:
      • Lighting Consultant center: x=781.02, y=236.6 (84x23 slot)
      • Client center: x=781.02, y=198.8 (84x11 slot)
      • Interior Designer center: x=781.02, y=178.93 (84x11 slot)
      • Main Contractor center: x=781.02, y=158.3 (84x11 slot)
      • MEP Contractor center: x=781.02, y=138.3 (84x11 slot)
      • Lighting Integrator center: x=781.02, y=119.4 (84x11 slot)
  • Site Access workspace staging reset (v0.17 -> v0.18 prep):
    • Site Access module UI is intentionally reduced to a single full-width shell card.
    • module button now uses latched highlight behavior (matching Quotes) and unlatches Design/Deliverables selection when activated.
    • project selection card is hidden while Site Access module is active.
  • Site Access workspace starter expansion:
    • restored Site Access to three cards.
    • first card now provides a dedicated client/venue selector UI patterned from Quotes left pane.
    • this selector reads from the same backend quote clients/venues model and endpoints (shared data source, separate UI implementation).
  • Site Access UI sizing pass:
    • Site Access cards now use a taller 160% height profile (scoped to Site Access only).
    • client/venue selector list viewport is constrained to ~3 visible rows before scroll.
  • Site Access client selector create action:
    • added Create Client button + modal in Site Access client/venue card.
    • action writes to the shared quotes clients backend model and refreshes selector list on success.
  • Site Access selector metric alignment:
    • removed quote-access user pills and quote counters from Site Access selector rows.
    • added backend-driven ACCESS PACKAGES counters.
    • quote client/venue system contracts now include access_package_count computed from issued attendance packages.
  • Site Access create-action context behavior:
    • selector action now switches from Create Client to Create Venue when inside a selected client's venues list.
    • venue creation uses shared quote venues backend contract.
  • Site Access card 2 baseline:
    • card 2 heading now set to Staff / Document Control.
    • card 2 heading typography aligned with Site Access card 1 heading style.
  • Site Access card 2 staff controls:
    • includes Staff subheading, search, and scroll list sized for ~5 visible entries.
    • includes Add Staff dialog path and Remove Staff latch mode with per-row red remove trigger.
    • remove flow confirmed via backend delete endpoint and storage cleanup for associated staff documents.
  • Site Access add-staff contract alignment:
    • add dialog now omits project picker and notes field.
    • staff code is backend-generated as LS-### (next available), not user-editable.
    • added backend-backed Job autocomplete source via GET /api/v1/system/attendance/staff/jobs.
    • attendance staff contracts now include job_title for create/update/read flows.
  • Staff row visual polish:
    • remove X trigger now sits fully within row bounds.
    • each staff row now displays a right-aligned settings cog icon.
  • Staff document upload/storage baseline remains active:
    • endpoint: POST /api/v1/projects/{project_id}/attendance/staff/{staff_id}/documents/upload
    • persisted path: uploads/attendance-staff-documents/<project_id>/<staff_id>/...
  • Site Access staff settings workflow baseline:
    • cog button now opens Edit Staff Member dialog.
    • top staff details load as read-only by default with explicit Edit Details toggle.
    • Full Name and Staff Code remain non-editable in edit mode.
    • upload controls added for EID, Passport, Visa, and Licences.
    • licence uploads now persist license_name + license_abbreviation metadata and upsert backend licence registry for autocomplete reuse.
    • backend autocomplete endpoints available:
      • GET /api/v1/system/attendance/staff/jobs
      • GET /api/v1/system/attendance/staff/licenses
    • migration added for backend licence registry:
      • apps/api/alembic/versions/0029_attendance_staff_license_registry.py
    • runtime note:
      • apply migration 0029 (alembic upgrade head) to enable licence registry persistence/autocomplete.
      • backend guards now prevent upload-path 500s if migration is temporarily missing.
  • Site Access staff document filename contract (backend-authoritative):
    • on upload, staff docs are renamed to:
      • StaffCode - FullName - Document.ext
    • Document uses doc kind (EID, PASSPORT, VISA) and uses license_name for license uploads when supplied.
    • file extension is preserved/inferred backend-side.
    • upload replacement policy:
      • uploading a document for an existing staff document slot replaces in place (same metadata id and same stored path/name when present).
      • slot matching:
        • EID/PASSPORT/VISA: one slot per kind
        • LICENSE: one slot per license name
      • metadata stores sha256 for uploaded file content.
    • issued package/share links now resolve live backend document sources (not frozen snapshot copies), so updated staff documents are reflected in previously issued package downloads.
  • Site Access company document control baseline:
    • system-level company documents can be managed from Site Access via backend-backed upload actions.
    • required upload slots:
      • Trade Licence
      • Insurance Certificate
      • Insurance Schedule
      • Insurance Policy
    • persistence is immediate on upload (no draft-only frontend state).
    • company-document upload naming contract:
      • Loud - <Document Title>.<ext>
    • replacement behavior:
      • uploads replace in place for existing document records (stable storage path when present).
  • Site Access create access package baseline:
    • card 3 is now an active backend-connected package creation flow.
    • selecting a venue in Site Access card 1 unlocks package fields in card 3.
    • top context fields shown as system text (server-sourced selection + system date):
      • client
      • venue
      • location
      • date
    • manual fields persisted in package payload:
      • prepared by
      • operator
      • security
      • main contractor
      • works commencing date/time
      • works ending date
      • project overview
      • exit routes
    • staff selection workflow in card 3:
      • Select Staff -> selectable list with green selected state
      • Cancel + Confirm Staff actions while selecting
      • confirmed staff list rendered in grey with staff code/name and license pills
    • Create Access Package now creates a persisted attendance package record immediately via backend API.
  • Site Access HSE package generation status (002 RAMS):
    • previously attempted HSE generation slice has been intentionally purged/reset by owner instruction.
    • no active HSE generation endpoints/UI test pane are currently wired.
    • next implementation pass should rebuild HSE generation from clean backend-first architecture using owner templates under:
      • uploads/access-package-templates/002-rams/
    • update (2026-02-26): clean backend-first rebuild completed.
      • active endpoints:
        • POST /api/v1/projects/{project_id}/attendance/packages/{package_id}/documents/hse
        • GET /api/v1/projects/{project_id}/attendance/packages/{package_id}/documents/hse/download
      • active template source:
        • /uploads/access-package-templates/002-rams/Loud HSE - v01.pdf
      • generation metadata persisted in:
        • package_payload.generated_documents.hse_package
      • temporary full-width Site Access HSE output test card restored for iterative validation.
    • update (2026-02-26, repair):
      • HSE rendering now preserves template formatting by doing in-place placeholder replacement on the uploaded PDF template (no secondary full-body overlay).
    • update (2026-02-26, calibration):
      • added field-placement refinements to reduce overlap in edge placeholder positions (including shared venue/location site line behavior).
    • update (2026-02-26, bullets):
      • normalized introduction applicability list markers from * to bullet points during backend generation for visual consistency.
    • update (2026-02-26, stability cutover):
      • generation now uses fillable-PDF AcroForm field population (template-form mode) with required-field validation.
      • primary template:
        • /uploads/access-package-templates/002-rams/Loud HSE - Prep.pdf
    • update (2026-02-26, template v2):
      • primary form template updated to:
        • /uploads/access-package-templates/002-rams/Loud HSE - Prep - v2.pdf
    • update (2026-02-26, field appearance):
      • AcroForm output now enforces Prepared Name text-size style for all filled fields except Venue and Location.
    • update (2026-02-26, multiline fields):
      • Project Overview and Exit Routes are rendered as backend text-box overlays (wrapped/top-aligned) for stable layout.
    • update (2026-02-26, template v5):
      • primary form template updated to:
        • /uploads/access-package-templates/002-rams/Loud HSE - Prep - v5.pdf
      • added fixed-field mapping:
        • Loud -> Loud and Clear Audio Visual Equipment Trading LLC.
    • update (2026-02-26, alignment tweak):
      • Prepared Name receives a small backend vertical offset adjustment for visual alignment.
    • update (2026-02-26, readonly export):
      • generated form fields are written in read-only mode to reduce viewer field-highlighting artifacts.
  • Deliverables CAD template workflow (001.x) update:
    • active layout authority now begins with:
      • apps/api/app/assets/cad_layout_v1.json
    • backend compositor:
      • apps/api/app/services/cad_template_pdf.py
    • local extraction/inspection helper:
      • scripts/extract_cad_layout_manifest.py
    • host-side reference workflow:
      • run the extractor with /opt/loud-engine/.venv-tools/bin/python to inspect the owner-filled reference PDF, compare measured label geometry to the manifest, and derive suggested manifest updates/value-slot guidance without retuning code constants by eye.
    • render-mode update:
      • compositor now supports filled_reference_static_base mode from the manifest.
      • when active, the owner-filled reference PDF becomes the static chrome/background, the backend clears only dynamic regions, merges the live viewport, and redraws only mutable content.
    • mapping workflow update:
      • CAD options now expose a backend-persisted Template Mapping editor for 001.x-style outputs.
      • the editor uses a clean structural background generated by backend authority and saves draft text/image field rectangles via system endpoints.
  • Rack Drawing (007.0) render jobs are backend-authoritative artifacts: only complete, non-stale jobs with a real stored PDF are eligible as the current viewport source, and jobs remain queued until the worker actually begins rendering.
  • Rack Drawing render lifecycle is auditable end-to-end: duplicate rack selections are rejected, and queue/start/fail/complete transitions are recorded in project audit history.
  • Rack Drawing artifact reads are uploads-root constrained on the backend for both symbol SVGs and rendered PDFs.
  • Rack Drawing 007.0 backend rendering now outputs front-plus-side rack views rather than a single elevation-only stack representation.
  • Rack Drawing UI has been simplified back to a single full-width workspace card with project-context gating, a top-right Symbol Library dialog, and rack creation now includes a backend-owned rack number field.
  • Rack symbols no longer use a width tag in authoring or validation; equipment is treated as 19-inch rack equipment regardless of outer rack enclosure width.
  • Rack Drawing backend now carries owner-supplied core front and side rack element metadata for 600/800/1000 DXF assets, plus a project rack include_castors flag so rendered rack height can follow real assembly pieces more closely.
  • Rack Drawing device symbols are now treated as paired rack-item assets: a library item is only complete when it has both FRONT and SIDE DXF files, and the shared device library under uploads/rack-symbols/devices/front and uploads/rack-symbols/devices/side syncs complete pairs into a project-global searchable rack item library.
  • Rack Drawing rack-power layouts are now backend-persisted per rack and included in the render hash/output. The layout editor saves ordered power items, and generated PDFs reserve a left-side Lighting Rack Power panel when a rack has power entries.
  • Rack Drawing power DXF assets are expected under uploads/rack-symbols/power/ with the configured names POWER-16A.dxf, POWER-32A.dxf, POWER-32A-3PH.dxf, POWER-63A-3PH.dxf, POWER-1PH-ISO.dxf, and POWER-3PH-ISO.dxf; the renderer falls back to simple vector symbols until those files are supplied.
  • Rack Drawing side-view device DXFs now align by detected front vertical edge, set back 16mm from the side rack left edge, and are clipped to the rack aperture before side rack linework is redrawn.
  • Rack Drawing symbol names can be edited in the Symbol Library; manual symbol creation requires and preserves the typed name instead of deriving names from filenames.
  • Rack Drawing render staleness now includes device asset file fingerprints, so replacing a DXF at the same path causes old PDFs to become stale and the next render uses the new file.