Skip to content

v0.4.6 — mode-lock fix + dw_root wrapper + dashboard

Choose a tag to compare

@jpazvd jpazvd released this 30 May 16:17
· 97 commits to develop since this release
005bd11

v0.4.6 (2026-05-30)

Quality release. Four issues land in one cycle — one HIGH-severity
canonical-recognition fix that would have allowed reviewer-mode
overwrites of canonical Teams artefacts, plus three cleanups
(re-exported dw_root() wrapper, uniform .cso_require envelope on
standalone-source %>% gate, and an r/.gitattributes pin so the R
subtree checks out with LF endings on Windows). No public API
breaks.

dw_is_canonical recognises OneDrive-mounted Teams Documents path (issue #54) — HIGH severity

Pre-fix, dw_is_canonical() matched canonical paths against
teamsFolderCanonical and the Z: drive root only. On UNICEF laptops
where the Teams "Documents" library is mounted via OneDrive
(C:/Users/<user>/UNICEF/<team> - Documents/...), the canonical
prefix the helper saw at runtime did not match the literal path the
sector profile assembled when writing — so dw_is_canonical()
returned FALSE for paths that were, in fact, canonical Teams
deposits.

Combined with the v0.4.0 reviewer-mode write-refusal contract
(dw_save refuses canonical writes in reviewer mode unless
allow_canonical_write = TRUE), the false-negative meant a reviewer-
mode dw_save() call would have silently overwritten the canonical
Teams artefact instead of hard-stopping.

Surfaced empirically by the 2026-05-30 HVA + ED reviewer-mode
fanout runs (DW-Production): the canonical path through the
OneDrive-mounted Documents folder passed the
!dw_is_canonical(path) precondition and would have written to the
canonical artefact had the runs not been halted by the audit. The
fix extends dw_is_canonical() to also recognise the OneDrive-
mounted Documents form, so the canonical-write refusal contract
fires correctly on UNICEF-laptop reviewer sessions.

Tests in r/tests/testthat/test-dw-is-canonical.R extended to cover
the OneDrive-mounted form alongside the existing Z: and
teamsFolderCanonical cases.

dw_root() public wrapper re-exported (issue #53)

Several DW-Production sector scripts (carried forward from the v0.3
era) call dw_root() directly to derive the sector-folder anchor
for relative path resolution. dw_root() was never an exported entry
in the v0.4.x NAMESPACE — sector scripts that vendored v0.4.x copies
of the toolkit hit Error: could not find function "dw_root" the
first time they sourced the profile.

The internal helper is re-exported as a public wrapper in v0.4.6;
the existing implementation is unchanged. NAMESPACE gains an
export(dw_root) entry and man/dw_root.Rd is generated. The
helper joins Other io: in the family cross-references so it
surfaces in pkgdown alongside dw_save, dw_use, and friends.

Uniform .cso_require envelope on %>% standalone-source gate (issue #51)

v0.4.5's #46 fix added a local %>% binding gated by exists(). The
gate worked, but it raised a bare base-R error if magrittr itself
wasn't installed — without the [cso_toolkit.<func>] WHAT / Why / Fix envelope the rest of the toolkit follows.

v0.4.6 wraps the local-binding fallback in .cso_require("magrittr")
so the envelope shape is uniform. Consumers who source the file
standalone without magrittr installed now see the same actionable
three-part message as every other toolkit raise.

r/.gitattributes pins LF endings on the R subtree (issue #52)

On Windows checkouts under default git autocrlf settings, R source
files in the package subtree (*.R, *.Rd, NAMESPACE,
DESCRIPTION, *.yml, *.yaml, *.md) were rewritten with CRLF
endings on checkout. That made local working-tree SHA-256 hashes
diverge from the LF-computed Git blob hashes — a recurring source
of spurious "drift" complaints from Windows consumers comparing
working-tree hashes against manifest entries computed on Linux.

A new r/.gitattributes pins LF endings on the R subtree's source
files so Windows checkouts of the package subtree are byte-identical
to Linux/macOS. This is scoped to r/ — the rest of the repo
inherits the platform default. Per-file hash drift detection in
cso_toolkit_check() itself is not part of this release; today
the function only compares the pinned manifest version against the
upstream latest tag. The richer drift logic is planned for the
cso_toolkit_diff() / cso_toolkit_pull() work (stubbed in v0.4.6).

Docs: third role renamed INGESTOR → PUBLISHER (DBM / DBR / DBP)

The third data-warehouse role is now PUBLISHER (was INGESTOR),
aligning the role label with the verb the code already uses
(dw_publish(); there is no dw_ingest()). Docs-only — no code,
no exported-API change, and no mode-contract value changed: the
contract still exposes producer / reviewer, and wiring a
publisher mode remains future scope (issue
#15). The role
acronyms are now spelled out across the docs — DBM = Database
Manager (PRODUCER), DBR = Database Reviewer (REVIEWER), DBP =
Database Publisher (PUBLISHER). Touches docs/roles_and_workflow.md,
README.md, r/DESCRIPTION, templates/dbm_submission_template.md,
docs/git_workflow.md, docs/toolkit_strategy.md.