Skip to content

Releases: winterop-com/dhis2w

v1.32.1

Choose a tag to compare

@mortenoh mortenoh released this 18 Oct 08:18
v1.32.1
69ef967

A combined patch release: every dhis2w package and pack moves to 1.32.1 together. The changes are in the dhis2w-fhir pack; this repository is unchanged.

v1.32.0

Choose a tag to compare

@mortenoh mortenoh released this 06 Oct 13:28
v1.32.0
2d8afda

A combined release: every dhis2w package and pack moves to 1.32.0 together. Its themes are DHIS2 2.43.2, a newer 2.44 preview build, and an upstream issue log organised for reporting.

DHIS2 2.43.2

  • v43 is pinned to 2.43.2.0. The generated v43 tree only gains fields: UpdatePasswordRequest, program label properties, SystemSettings.jobsRescheduleAnalyticsAfterMinutes and TrackerRelationship.deleted.
  • 2.43.2 refuses the OAuth2 scope ALL and requires PKCE, as 2.44 does. The v43 tree registers OAuth2 clients with the OpenID scopes (openid, email, profile, username), and --scope defaults to openid on v43.

DHIS2 2.44 preview

  • v44 is pinned to the 2.44-SNAPSHOT build of 2026-10-06 (revision c48aedc). It is still a preview until 2.44.0 ships.
  • The v44 tree gains GET /api/metadata/dependencies, the new ExternalMapLayer fields (description, descriptionUrl, image), MetadataExportParams.objectsExportWithDependencies and eight new error codes.

Seed dumps

  • Dumps follow the backup script of dhis2-server-tools: a plain pg_dump without owners, without the analytics fact tables, and without audit rows.
  • make dhis2-migrate-e2e-dump DHIS2_VERSION=v4N moves a committed dump to a new pin by restoring it into the new image and letting DHIS2 migrate it: about 42 seconds, against about 35 minutes for a full seed. The full make dhis2-build-e2e-dump is for seed changes.
  • The analytics sidecar reports a failed analytics run as a failure.

Upstream issues

  • DHIS2_ISSUES.md is the upstream issue log, organised so each group is one upstream report: a status table by release, then 29 groups. Each group has a summary written as the ticket description, the versions it affects, and its member issues with copy-pasteable repros.
  • It was re-run on 2.43.2 and on 2.44 c48aedc. #13 is fixed on 2.43.2, #134 covers 2.43.2, and #144 and #145 are new.
  • The docs page is Upstream DHIS2 issues.

v1.31.1

Choose a tag to compare

@mortenoh mortenoh released this 06 Oct 13:27
v1.31.1
724cdc8

A combined patch release: every dhis2w package and pack moves to 1.31.1 together. The changes are in the dhis2w-fhir pack, where the hostile_names = "substitute" posture words comparisons consistently in names and codes.

Upstream DHIS2 findings

  • Issues #138 to #142 reproduce on a local 2.43.1 stack, so they are recorded against v43 rather than v44. #142 holds on values written moments earlier, which points at the predictor engine rather than the seed.
  • #6 is restated: the 2026-09-11 admin refusal on 2.43.1 was E8023 (#41), and a superuser skips the open-future-periods check on 2.43.1 as on 2.44 (#139).

v1.31.0

Choose a tag to compare

@mortenoh mortenoh released this 01 Oct 09:45
6bb8e1f

A combined release: every dhis2w package and pack moves to 1.31.0 together. Its theme is DHIS2 2.44, which arrives as a preview, and generated models that no longer depend on which boot of DHIS2 they were captured from.

DHIS2 v44 (preview)

  • dhis2w_client.v44, dhis2w_core.v44 and dhis2w_client.generated.v44 join v41, v42 and v43. A client connected to a 2.44 server binds the v44 tree on its own; Dhis2.V44 pins it. v43 stays the default plugin tree.
  • 2.44.0 is not released yet, so the local stack runs one pinned build of the 2.44 development line (dhis2/core-dev, revision b732899, pinned by digest). It is re-pinned to 2.44.0.0 when that ships.
  • What 2.44 changes, and how the v44 tree meets it:
    • OAuth2 clients can register only the OpenID scopes (openid, email, profile, username) and must require PKCE. The v44 tree registers exactly that and logs in with openid; d2w profile ... --scope defaults to openid on v44.
    • TrackedEntityAttribute.confidential no longer exists; the v44 accessor, service and d2w metadata command take no --confidential.
    • A failed background job wipes its notification feed about a second after it ends. client.tasks.await_completion and every --watch read the job's recorded outcome when that happens, on every tree.
  • infra/scripts/clone_version_tree.py copies the hand-written trees to a new major and lists the lines to review, and docs/architecture/versioning.md has the steps for adding a major.

Generated models

  • d2w dev codegen fetch-openapi captures the live OpenAPI document, and make dhis2-codegen-all runs it, so both halves of a generated tree follow the pinned release.
  • DHIS2 builds its OpenAPI document and /api/schemas at startup, and one image answers differently on different boots. The codegen pins every shape seen to move, so any capture of a release emits the same models. Visible effect: CategoryOption.aggregationType is the AggregationType enum on every tree, and Page.items on v42 and v43 is untyped.
  • d2w dev codegen oas-flips lists what differs between captures of one release; infra/scripts/openapi_stability.sh samples several boots.

Fixes

  • d2w doctor bugs parses development versions such as 2.44-SNAPSHOT.

Upstream DHIS2 findings

BUGS.md carries a full retest of every entry on 2.44 (103 still reproduce, 11 are fixed there) and new entries #133 to #143, among them the boot-dependent OpenAPI document (#133), the 2.44 OAuth2 registration rules (#134), Gist-shaped list responses with an http:// next-page link (#136), and /api/audits/trackedEntity answering 500 on 2.42 to 2.44 (#137).

Dependencies

SQLAlchemy 2.1, httpx2 2.13, a refreshed lockfile; CI on setup-uv 10.2.0.

v1.30.1

Choose a tag to compare

@mortenoh mortenoh released this 29 Sep 18:53
v1.30.1
2ef8fca

A combined release: every dhis2w package and pack moves to 1.30.1 together. The host itself has no changes; the release carries the dhis2w-fhir 1.30.1 improvements to make update in FHIR projects.

v1.30.0

Choose a tag to compare

@mortenoh mortenoh released this 29 Sep 14:45
v1.30.0
35a86f6

FHIR is now a plugin pack in a repository of its own, dhis2w-fhir, with its history, the way the browser automation and the MCP server became packs in 1.29.0. The host is now the DHIS2 client, the core plugins and the d2w CLI.

Installing FHIR support

dhis2w-cli no longer installs FHIR by itself. Ask for it with the [fhir] extra, and add [serve] for the capture server:

uv tool install "dhis2w-cli[fhir]"
uv tool install "dhis2w-cli[fhir,serve]"

Without the pack, d2w fhir prints that install command instead of "No such command". d2w browser and d2w security do the same.

A FHIR project scaffolded by d2w fhir init lists dhis2w-fhir and dhis2w-fhir-serve among its own dependencies, so make update keeps working unchanged.

What moved

Package Repository Documentation
dhis2w-fhir, dhis2w-fhir-engine, dhis2w-fhir-serve dhis2w-fhir site

The package names, d2w fhir and its commands, the capture UI and the engine's API are unchanged. The FHIR pages redirect to the pack's site. The canonical OperationDefinition pages that FHIR artifacts cite stay published where they are.

dhis2w-fhir 1.30.0 releases from its own repository after this release. Until then, [fhir] installs 1.29.0.

v1.29.0

Choose a tag to compare

@mortenoh mortenoh released this 29 Sep 13:58
v1.29.0
cb3c1b8

The browser automation and the MCP server are now plugin packs in repositories of their own, the way d2w security already is. The host keeps the client, the core plugins, the CLI and FHIR, and every pack releases the same version after it.

What moved

Pack Repository Documentation PyPI
d2w browser dhis2w-browser site dhis2w-browser
MCP server, CLI bridge, router dhis2w-mcp site dhis2w-mcp, dhis2w-mcp-bridge, dhis2w-mcp-router

Both repositories carry their history with them. The package names, the d2w browser commands, the dhis2w-mcp / dhis2w-mcp-bridge / dhis2w-mcp-router entry points and every MCP tool name are unchanged, so an install that names the packages picks up the packs as they release 1.29.0.

Installing

  • Browser: uv tool install "dhis2w-cli[browser]" as before. The pack registers d2w browser through the dhis2w.plugins.v1 entry point.
  • MCP: install dhis2w-mcp (or dhis2w-mcp-bridge, dhis2w-mcp-router) as before. The pack's one mcp plugin registers the tools of every built-in plugin, calling the same core services the CLI does. Its documentation holds the tutorial, the bridge, the router and the tool reference.

In the host

  • dhis2w-core no longer depends on fastmcp, and core plugins contribute their CLI only.
  • user-group and user-role are no longer plugin names. Their commands were always d2w user group and d2w user role, which are unchanged.
  • The pages that moved redirect to the packs' sites.

v1.28.1

Choose a tag to compare

@mortenoh mortenoh released this 29 Sep 10:52
v1.28.1
096116d

A guide whose DHIS2 codes carry a < now generates under hostile_names = "substitute", and d2w fhir init can set the root organisation unit, so a registry package and the guide depending on it state the same selection.

A < in a code

A DHIS2 code becomes an identifier value, which the IG publisher writes into a table cell unescaped and then strict-parses, so a < in one aborts the build's last pass. Until now substitute rewrote a < in a name and a space in a code, but refused a code carrying <.

Under substitute such a code is now rewritten the way a name is: the comparison is reworded and then every space is hyphenated, as for any code carrying a space. ENTO - IRS < 6 Months publishes as ENTO---IRS-under-6-Months. The DHIS2 code is stated beside it as the dhis2-code property, so it stays joinable back to the instance, and generate raises a note for each rewrite. Under refuse, or with the key unset, the run is refused naming the object, as before. d2w fhir validate grades the code the same way: informational under substitute, an error under refuse.

d2w fhir init --org-unit-root

--org-unit-root <uid> seeds [generate.organisation_units] root, the top of the subtree a project publishes. The UID's shape is checked, and nothing is read from the instance.

d2w fhir init national --with-registry --id dhis2.fhir.national --org-unit-root ImspTQPwCqd --org-unit-max-level 5

Under --with-registry the root lands in both projects, as --org-unit-max-level does. A guide's forms may only be assigned to organisation units the registry package publishes. A guide whose [generate.organisation_units] table is left empty reads the whole instance, including any subtree kept for deactivated organisation units that the package's root leaves out, and d2w fhir check-artifacts then reports each such reference as build-aborting. Publish the registry as a package now states this rule, and Troubleshooting names the finding.

The depth flag beside it is now --org-unit-max-level, so both flags name what they select, the way --org-unit and --org-unit-group do elsewhere in d2w. A script passing --max-level needs the new name, and fhir.toml is unchanged: the keys are still root and max_level.

For a pair scaffolded on an earlier version, copy the registry's root and max_level into the guide's fhir.toml, then run make update and make generate.

v1.28.0

Choose a tag to compare

@mortenoh mortenoh released this 29 Sep 07:51
v1.28.0
8593e8a

A large registry or guide now builds on a machine that has room for it, rather than being killed by giving the publisher more heap than the machine can hold alongside everything else.

The publisher heap

A build holds more than its heap. The Java process keeps about 2 GB of its own around the heap, and Jekyll renders the site at the very end as a second process in the same container, taking about 4 GB on a registry of twenty thousand resources. Java also grows into whatever ceiling it is given, so a larger JAVA_HEAP is more memory held, not more room.

Measured on a registry package of 10,453 organisation units (20,906 resources), the publisher never used more than 7 GB of heap. At 8g the build held about 13.5 GB in total. At 16g it held about 21.5 GB, which a 24 GB Docker cannot hold with anything else running. Depth (seven levels instead of five) and organisation unit geometry each changed that by less than 0.3 GB. The number of resources is what matters.

  • The default JAVA_HEAP is now the memory Docker reports less 6 GB, capped at 8g and floored at 4g, and 8g when Docker cannot be asked. A 24 GB Docker now gets 8g, not 22g. A guide that really needs more stops with a Java OutOfMemoryError, which says so, and make build JAVA_HEAP=12g raises it.
  • Every build prints two peaks as it finishes. peak memory in use is what the machine has to hold: the heap, the Java process around it, and Jekyll. peak container memory is the container's own high-water mark, which also counts file cache the kernel takes back when memory runs short. Size Docker by the first.
  • When the build is killed for memory, the report now suggests lowering the ceiling (JAVA_HEAP=8g when it was above that) before giving Docker more memory.

Invisible characters in contact details

A DHIS2 phone number or email that carries an invisible format character (a zero-width space pasted in with the number, a byte-order mark, a direction mark) is now published without it. The IG publisher renders a phone contact as a tel: link, and a link with a zero-width space in it failed the build's QA with XHTML_URL_INVALID. Every digit and letter of the value is kept, and DHIS2 is not touched. Organisation unit phone numbers and emails, and the phone number nominated under [ips.identity], are covered, and generate raises a note naming each organisation unit whose DHIS2 value carried one.

d2w fhir validate now reports the same kind of character in names, form names, option names and codes (invisible-character). It reports only a stray one, touching nothing but visible ASCII, such as B. Hin​Tang or a code OU​2. Lao, Thai, Khmer and Myanmar mark word breaks with a zero-width space, so one inside such text is correct and is left alone. A code is a warning, because it reaches identifiers, resource ids and URLs. A name is informational and is published as DHIS2 holds it. The reports print the character as ​, so it can be seen, and the fix is to retype the value in DHIS2.

A project picks up the new Makefile with make update. A JAVA_HEAP set on the command line or in the environment is used as it stands.

The reference is Build and publish.

v1.27.0

Choose a tag to compare

@mortenoh mortenoh released this 27 Sep 16:36
v1.27.0
2e2849e

A guide can now publish its organisation units without their boundary polygons, or without any geometry.

How much geometry a Location carries

[generate.organisation_units] geometry takes one of three values:

  • full (the default) publishes each Location with its position and its boundary, as it did before.
  • position keeps Location.position (the DHIS2 point, or the centre of the boundary) and leaves out the location-boundary-geojson extension. Boundaries are most of a registry's size on an instance with detailed polygons, so this gives a much smaller guide that still places every organisation unit on a map.
  • none publishes neither, and the run leaves geometry out of its DHIS2 read.
[generate.organisation_units]
geometry = "position"

d2w fhir init --geometry position seeds the key in a new project. Under --with-registry it goes to the registry package, which is the project that publishes the Locations. A guide that depends on a registry package is refused any value other than full, with a message pointing at the package's fhir.toml. The registry page and the guide's home page say which setting the organisation units were published under.

The organisation units page

The capture server now tells the organisation units page which setting was used.

  • Under position, the map draws the organisation units as points and says the guide publishes no boundaries.
  • Under none, the page has no map: the hierarchy and the details share the screen.
  • The note shown when a selected organisation unit has no coordinates now blames the source it can be sure of. That is the DHIS2 instance when this project published the units, and the registry when another package did.

The reference is What goes in. A project picks up the new line in its fhir.example.toml with make update.