Skip to content

OpenConstructionERP v16.0.0

Choose a tag to compare

@github-actions github-actions released this 26 Aug 21:26
· 3822 commits to main since this release

This is a minor rather than a patch because three routes now refuse requests they used to accept, converted amounts change on the wire, and the install pulls a new library. Nothing here is a feature that needed a version of its own; the number moved because a patch is a promise that nothing at the boundary changed, and that promise would have been false.

A computer-aided design extraction session with no recorded owner used to read as permission rather than as the absence of one. The check compared the caller against the owner field and an empty field matched everybody, so any authenticated user could read any unowned session and the extraction inside it. Sessions arrive unowned in ordinary use, not only through error. The route answers a not found now, which is what it always meant to do. Callers that were relying on the old answer were relying on a gap.

Switching the market catalogue for a region was gated on read permission and described in a comment as a viewer-level action. It is not a read at all. It rewrites the description, unit and classification of every cost item in the region, and it also overwrites every stored resource price from the market file, including prices somebody had edited by hand, then reprices every work item and stamps the market currency across the region. Those rows are shared reference data that is deliberately never filtered by tenant, so a viewer in one account was destroying saved pricing work in all of them. It requires editor permission now. That closes the privilege escalation and does not make the operation tenant-safe, which is a property of the shared table rather than a defect left unfixed, and it is written down as such. Loading the reference cost database stays viewer-level on purpose, because onboarding, the command line quickstart and the partner pack installer all reach it.

Converted amounts are rounded to the currency they are denominated in. The rounding was currency-blind and always went to two decimals, so a Kuwaiti dinar lost its third decimal on every conversion, and yen, forint, rupiah and Chilean peso carried two decimals that cannot be settled in those currencies at all. Both directions were wrong in a way that survives arithmetic: the first silently discards money, the second invents a precision the payment rail will refuse. Amounts on the wire move accordingly. No stored data is rewritten and no migration runs, because the values in the database were never the problem.

A stored holiday means one day to every reader. The schedule engine and the progress engine read the same column through different code, and one of them walked a malformed value character by character and produced ten junk entries where there should have been one date, silently and with nothing logged. A calendar that cannot be read is now refused at the routes that write it rather than quietly degrading into a default working week, and a calendar column holding something that is not a calendar stops the read instead of returning confident dates computed from an assumption. The two country registries behind the working week are held together by an assertion now, and the assertion checks that both sides actually answered, because two lookups that both fall back to the same default agree with each other without either of them knowing anything.

The full text of the licence ships where the product says it ships. The root file was a summary, the about screen told the reader the complete text came with the source, and the complete text was in the tree, the wheel and the container image nowhere. The Windows installer was showing that summary on the page where the user accepts the licence. All of them carry the verbatim text now, and the attribution file was corrected in the same pass: it filed a dependency under an optional group it had left, listed a package that is not a dependency at all, and closed by telling anyone who installed without that group that they pulled in no copyleft upstream packages, which was not true of any build we have ever shipped. It says what we ship, and it records what the previous wording claimed, because a reader who acted on the old text deserves to find that out rather than to meet a quietly corrected file.

Thai and Devanagari print correctly in the wrapped text blocks that documents use for descriptions and narrative. The characters were reaching the page and landing in the wrong places: a tone mark drew at the height of the vowel it belongs above and merged with it. That needs shaping rather than a font, so the shaper ships with the product, and the desktop installers now actually contain it, which they had been promising and not doing. Korean and Chinese are correct on every surface, because those scripts need the right face rather than the shaper.

One surface is not fixed, and it is named here rather than left to be discovered. A plain table cell, the kind holding one short value rather than a wrapped block, still draws complex scripts unshaped. It is placement rather than support: the correct face draws the correct characters in the wrong shape. That reaches names and free text a Thai or Indian firm types into punch lists, meeting minutes, property summaries and dashboard exports. It does not reach contract billing descriptions, which are on the wrapped path and are correct. The measurement is done and the fix is understood, and it did not land in time for this release.

Two offered languages produce documents nobody can read, and this release fixes neither. Bengali sits in the language picker with a complete interface translation, and no bundled face covers the script at all, so every Bengali character in a generated document prints as an empty box. Urdu draws most of its text, but four of its characters have no face either, and they are not rare: two are among the commonest letters in the language and one is the full stop that ends every sentence. Both are a missing font rather than the placement problem above, which makes them a different piece of work, and they are named here because a release that says complex scripts print correctly should say where they do not.

A country resolves to one classification standard whatever the spelling of the region it arrives as. Five hand-written tables and one derived from them disagreed, and the fallback that was supposed to recover a standard from a city-suffixed region identifier could never fire for the identifiers it was written for, because an earlier step had already put a default in the slot it tested for emptiness. Seventeen countries were resolving to the wrong standard. A region that still cannot be resolved keeps the previous default rather than changing behaviour quietly, but it now says so, and the answer carries whether it was matched or defaulted.

Every offered language reports how much of itself it actually returns. A guard asks the real translation library what a reader of each language actually sees on screen, rather than parsing the files with a reader of its own, which is how a bundle with a missing comma once walked past four green gates. It found twenty five cells that render blank in Bulgarian, Italian, Romanian and Kyrgyz where English renders text, including a login headline that begins mid-sentence. Those are filled and the check is green. Case playbooks are translated across the offered languages, several screens that had never been translated at all now are, and a set of controls that had no accessible name now have one.

The install pulls one new library, the text shaper described above. Anyone installing on a restricted network should expect one additional wheel.

Full Changelog: v15.9.1...v16.0.0