| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| README.md | 2026-05-21 | 3.5 kB | |
| v4.2.3 -- Security hardening + observability + bundle slimdown source code.tar.gz | 2026-05-21 | 248.6 MB | |
| v4.2.3 -- Security hardening + observability + bundle slimdown source code.zip | 2026-05-21 | 251.2 MB | |
| Totals: 3 Items | 499.8 MB | 0 | |
Round 3 wave: security hardening, observability foundation, and a sizeable frontend bundle slimdown.
Security
POST /api/v1/jobs/{job_id}/cancelnow requires authentication (closes unauthenticated mutation surface).- Path-traversal hardening in CAD/BOQ smart-import: 3 sites that built
Path(tmpdir) / file.filenamenow normalise viaPath(filename).nameand 400 on empty /./... - AI photo / file estimate uses
require_signature(...)magic-byte validation — bytes whose declaredContent-Typemismatches the file's magic prefix return HTTP 415. - StampTemplateEditor XSS closed. The shared-template preview no longer renders raw SVG via
dangerouslySetInnerHTML; it mounts inside a sandboxed iframe (emptysandbox=""attribute, content viasrcDoc) — no scripts, no same-origin, no forms.
Observability foundation
RequestIDMiddlewaregeneratesuuid4().hex[:16](or honours a client-suppliedX-Request-ID), stores it in aContextVar, echoes it on every response. Every log line in the process now carries[%(request_id)s].- Slow-query SQLA event listeners log statements over
OE_SLOW_QUERY_MS(default 500 ms) at WARNING with structuredextra={elapsed_ms, statement[:200], executemany}. /api/healthdeepened withalembic_head_matches+frontend_dist_present; either being false flips top-levelstatusto"degraded"(still HTTP 200).- New
oe_client_errorsmodule — frontenderrorLogger.tsnow POSTs anonymised payloads toPOST /api/v1/client-errors/(30/min per IP, message capped at 2048 chars, stack capped at 64 lines). docs/RUNBOOK.md(156 lines) extracted from internal memory for on-call ops.
DB integrity
alembic v3096_round3_fk_indexesadds 6 missing foreign-key indexes:oe_contracts_progress_claim_line.contract_line_id,oe_clash_issue.{first_seen,last_seen,resolved}_run_id,oe_crm_opportunity.lost_reason_code,oe_equipment_work_order.schedule_id. Inspector-guarded so re-running is safe.
API hygiene
- 3 silent-fail
200 + {error}responses converted to proper status codes:fieldreports/weather200 to 503,costs/vector/index200 to 503 (× 4 branches),costsrate-import "no rate_code column" 200 to 422. - Broken collection in
test_tendering_leveling.pyrepaired (module-level skip with reactivation conditions); pytest now collects all 5,922 tests cleanly.
Frontend performance
index-*.jsbundle: 1.76 MB to 1.27 MB (gzip 311 KB).- 11 packages removed:
leaflet,react-leaflet,@types/leaflet,jszip,i18next-http-backend,i18next-browser-languagedetectorplus transitives. - 7 admin pages converted from eager to
React.lazy(...)(Settings, Modules, ModuleDeveloperGuide, Assemblies + 3 siblings, ImportDatabase, OnboardingWizard, LoginPageNext, QuickEstimate). About 530 KB raw split off the main chunk. BOQGridcolumn stability: previoususeMemodep ontfromuseTranslation()(a fresh function each render) rebuilt column defs on every render. Now keyed oni18n.languagewith atReffor the latestt.MoneyDisplay/QuantityDisplayuse Zustand field selectors instead of full-store subscription — the BOQ grid no longer re-renders every money/quantity cell on unrelated preference changes.- 4 orphan
describe.skipblocks annotated with reactivation conditions.
Notes
109 modules load on boot (was 108: oe_client_errors added). No new Python deps. Alembic chain stays single-head at v3096_round3_fk_indexes.