Skip to content

Commit 2dc5bc6

Browse files
authored
Merge branch 'develop' into ocrvs-10760
2 parents 223f1cf + 611cc0c commit 2dc5bc6

File tree

174 files changed

+5394
-1566
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+5394
-1566
lines changed

.github/workflows/publish-toolkit-to-npm.yml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ on:
1717
push:
1818
branches:
1919
- '*'
20+
tags:
21+
- '*'
2022

2123
jobs:
2224
publish:
@@ -35,14 +37,26 @@ jobs:
3537
id: check-version
3638
run: |
3739
PACKAGE_VERSION=$(node -p "require('../../package.json').version")
38-
TOOLKIT_VERSION=$PACKAGE_VERSION-rc.$(git rev-parse --short=7 HEAD)
40+
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
41+
TAG_NAME="$GITHUB_REF_NAME"
42+
if [[ "$TAG_NAME" =~ ([0-9]+)\.([0-9]+)\.([0-9]+)([-+][A-Za-z0-9.-]+)?$ ]]; then
43+
TOOLKIT_VERSION="${BASH_REMATCH[0]}"
44+
echo "✅ Using semantic version: $TOOLKIT_VERSION"
45+
else
46+
echo "❌ Tag '$TAG_NAME' is not a valid semantic version (expected something like 1.2.3 or v1.2.3)"
47+
exit 1
48+
fi
49+
else
50+
TOOLKIT_VERSION="$PACKAGE_VERSION-rc.$(git rev-parse --short=7 HEAD)"
51+
fi
3952
if npm view @opencrvs/toolkit@$TOOLKIT_VERSION > /dev/null 2>&1; then
4053
echo "Version $TOOLKIT_VERSION already exists on npm."
4154
echo "version-exists=true" >> $GITHUB_OUTPUT
4255
else
4356
echo "Version $TOOLKIT_VERSION does not exist on npm."
4457
echo "version-exists=false" >> $GITHUB_OUTPUT
4558
fi
59+
echo "toolkit-version=$TOOLKIT_VERSION" >> $GITHUB_OUTPUT
4660
working-directory: packages/toolkit
4761

4862
- name: Install dependencies
@@ -63,8 +77,7 @@ jobs:
6377
- name: Update package.json version
6478
if: steps.check-version.outputs.version-exists == 'false'
6579
run: |
66-
PACKAGE_VERSION=$(node -p "require('../../package.json').version")
67-
TOOLKIT_VERSION=$PACKAGE_VERSION-rc.$(git rev-parse --short=7 HEAD)
80+
TOOLKIT_VERSION="${{ steps.check-version.outputs.toolkit-version }}"
6881
jq --arg version "$TOOLKIT_VERSION" '.version = $version' package.json > tmp.$$.json && mv tmp.$$.json package.json
6982
working-directory: packages/toolkit
7083

CHANGELOG.md

Lines changed: 296 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,304 @@
11
# Changelog
22

3-
## 1.9.0 Release candidate
3+
## 1.9.1 Release Candidate
4+
5+
### Breaking changes
6+
7+
- `QUERY_PARAM_READER` now returns picked params under a `data` object.
8+
For example, `code` and `state` are now accessed via `data.code` and `data.state`.
9+
10+
Previously:
11+
field(<page>.query-params).get('code')
12+
Now:
13+
field(<page>.query-params).get('data.code')
14+
15+
- **Removed support for following scopes**
16+
- `NATLSYSADMIN`
17+
- `DECLARE`
18+
- `VALIDATE`
19+
- `CERTIFY`
20+
- `PERFORMANCE`
21+
- `SYSADMIN`
22+
- `TEAMS`
23+
- `CONFIG`
24+
- `RECORD_EXPORT_RECORDS`
25+
- `RECORD_DECLARATION_PRINT`
26+
- `RECORD_PRINT_RECORDS_SUPPORTING_DOCUMENTS`
27+
- `RECORD_REGISTRATION_PRINT`
28+
- `RECORD_PRINT_CERTIFIED_COPIES`
29+
- `RECORD_REGISTRATION_VERIFY_CERTIFIED_COPIES`
30+
- `PROFILE_UPDATE`
31+
32+
## [1.9.0](https://github.com/opencrvs/opencrvs-core/compare/v1.8.1...v1.9.0)
33+
34+
### Breaking changes
35+
36+
* Dashboard configuration through **Metabase** has been fully migrated to **countryconfig**, and the standalone dashboard package has been removed.
37+
For details on configuring dashboards and information about the latest updates, refer to the [ANALYTICS.md](https://github.com/opencrvs/opencrvs-countryconfig/blob/v1.9.0/ANALYTICS.md) documentation.
438

539
### New features
640

41+
#### Events V2
42+
43+
We are excited to announce a major overhaul of our events system: **Events V2**.
44+
This is a complete rewrite that introduces a new level of flexibility and configurability to how life events are defined and managed across the system.
45+
46+
The new Events V2 architecture is built around a set of core concepts designed to make event management more powerful and customizable.
47+
48+
##### Events
49+
50+
An **Event** represents a life event (or any kind of event), such as a birth or a marriage.
51+
Each event is defined by a configuration that specifies the sequence of **Actions** required to register it.
52+
53+
##### Actions
54+
55+
###### Declaration Actions
56+
57+
Declaration actions are used to modify an event’s declaration.
58+
These actions must be executed in a defined order and cannot be skipped.
59+
60+
1. **DECLARE**
61+
2. **VALIDATE**
62+
3. **REGISTER**
63+
64+
Each action must be accepted by **countryconfig** before the next one can be performed.
65+
66+
67+
###### Rejecting and Archiving
68+
69+
After declaration, instead of proceeding with registration, an event may be either **rejected** or **archived**.
70+
71+
If **deduplication** is enabled for an action, performing that action may trigger a **DUPLICATE_DETECTED** action if duplicates are found.
72+
When this occurs, two additional actions become available:
73+
74+
* **MARK_AS_DUPLICATE** – archives the event.
75+
* **MARK_AS_NOT_DUPLICATE** – resumes the normal action flow.
76+
77+
If an event is rejected by a user, the preceding action must be repeated before continuing.
78+
79+
80+
###### Actions Before Declaration
81+
82+
1. **NOTIFY** – a partial version of the `DECLARE` action.
83+
2. **DELETE** – an event can be deleted only if no declaration action has yet been performed.
84+
85+
86+
###### Actions After Registration
87+
88+
Once an event has been registered, a certificate may be printed.
89+
If a correction is required due to an error in the registered declaration, a correction workflow must be initiated.
90+
91+
1. **PRINT_CERTIFICATE**
92+
2. **REQUEST_CORRECTION**
93+
3. **REJECT_CORRECTION**
94+
4. **APPROVE_CORRECTION**
95+
96+
97+
###### General / Meta Actions
98+
99+
1. **READ** – appended to the action trail whenever a complete event record is retrieved.
100+
2. **ASSIGN** – required before any action can be performed. By default, the user is automatically unassigned after completing an action.
101+
3. **UNASSIGN** – triggered either automatically by the system or manually by a user (if the record is assigned to themselves or if the user has the appropriate permission).
102+
103+
##### Forms, Pages, and Fields
104+
105+
Event data is collected through **Forms**, which come in two types:
106+
107+
* **Declaration Form** – collects data about the event itself
108+
* **Action Form** – collects data specific to a particular action, also known as annotation data in the system
109+
110+
Forms are composed of **Pages**, and pages are composed of **Fields**.
111+
Fields can be shown, hidden, or enabled dynamically based on the values of other fields, allowing for a responsive and intuitive user experience.
112+
113+
To simplify configuration, we’ve introduced a set of helper functions:
114+
115+
```ts
116+
defineDeclarationForm()
117+
defineActionForm()
118+
definePage()
119+
defineFormPage()
120+
```
121+
122+
All of these are available in a **type-safe** manner via the new `@opencrvs/toolkit` npm package.
123+
124+
##### Conditionals & Validation
125+
126+
Validation has been significantly improved through the adoption of **AJV** and **JSON Schema**, providing standardized, robust, and extensible validation.
127+
128+
The `field` function (exported from `@opencrvs/toolkit`) includes a set of helpers for defining complex validation rules and conditional logic.
129+
130+
##### Available helpers include:
131+
132+
* **Boolean connectors**: `and`, `or`, `not`
133+
* **Basic conditions**: `alwaysTrue`, `never`
134+
* **Comparisons**: `isAfter`, `isBefore`, `isGreaterThan`, `isLessThan`, `isBetween`, `isEqualTo`
135+
* **Field state checks**: `isFalsy`, `isUndefined`, `inArray`, `matches` (regex patterns)
136+
* **Age-specific helpers**: `asAge`, `asDob` (to compare age or date of birth)
137+
* **Nested fields**:
138+
139+
```ts
140+
field('parent.field.name').get('nested.field').isTruthy()
141+
```
142+
143+
The `user` object, also exported from `@opencrvs/toolkit`, includes helpers for user-based conditions such as:
144+
145+
```ts
146+
user.hasScope()
147+
user.hasRole()
148+
user.isOnline()
149+
```
150+
151+
These conditions can control:
152+
153+
* `SHOW` – whether a component is visible
154+
* `ENABLE` – whether a component is interactive
155+
* `DISPLAY_ON_REVIEW` – whether a field appears on review pages
156+
157+
They can also be used to validate form data dynamically based on the current form state or user context.
158+
159+
#### Drafts
160+
161+
The new **Drafts** feature allows users to save progress on an event that has not yet been registered.
162+
Drafts act as temporary storage for an action and are visible only to the user who created them.
163+
164+
#### Advanced Search
165+
166+
Advanced search is now configurable through the `EventConfig.advancedSearch` property, allowing different sections of an advanced search form to be defined.
167+
168+
You can search across:
169+
170+
* **Declaration Fields** – using the same `field` function from declaration forms with helpers such as `range`, `exact`, `fuzzy`, and `within`
171+
* **Event Metadata** – using the `event` function to search against metadata such as:
172+
173+
* `trackingId`
174+
* `status`
175+
* `legalStatuses.REGISTERED.acceptedAt`
176+
* `legalStatuses.REGISTERED.createdAtLocation`
177+
* `updatedAt`
178+
179+
More details about the metadata fields are available in `packages/commons/src/events/EventMetadata.ts`.
180+
181+
#### Deduplication
182+
183+
Event deduplication is now configurable **per action** via the `EventConfig.actions[].deduplication` property.
184+
Helpers for defining deduplication logic—such as `and`, `or`, `not`, and `field`—are available from `@opencrvs/toolkit/events/deduplication`.
185+
186+
The `field` helper can reference declaration form fields and be combined with:
187+
188+
```ts
189+
strictMatches()
190+
fuzzyMatches()
191+
dateRangeMatches()
192+
```
193+
194+
to define precise deduplication rules.
195+
196+
#### Greater Control over Actions
197+
198+
Each action now progresses through three possible states: **`requested`**, **`accepted`**, and **`rejected`**.
199+
When a user performs an action, it is first marked as **`requested`** and forwarded to **countryconfig** via the `/trigger/events/{event}/actions/{action}` route, with the complete event details included in the payload.
200+
201+
Countryconfig has full control over how the action is processed and may choose to **accept** or **reject** the action either **synchronously** or **asynchronously**.
202+
203+
By hooking into these action trigger routes, countryconfig can also:
204+
205+
* Send customized **Notifications**
206+
* Access the full event data at the time an action is performed
207+
208+
#### Configurable Workqueues
209+
210+
Workqueues can now be configured from countryconfig using the `defineWorkqueues` function from `@opencrvs/toolkit/events`.
211+
This enables the creation of role- or workflow-specific queues without requiring code changes in core.
212+
213+
* The **`actions`** property is used to define the default actions displayed for records within a workqueue.
214+
* The **`query`** property is used to determine which events are included in the workqueue.
215+
* The **`workqueue[id=workqueue-one|workqueue-two]`** scope is used to control the visibility of workqueues for particular roles.
216+
217+
Details on the available configuration options can be found in the `WorkqueueConfig.ts` file.
218+
219+
220+
#### Event Overview
221+
222+
The configuration of the event overview page (formerly known as *Record Audit*) has been made customizable through the `EventConfig.summary` property.
223+
The record details displayed on this page can be referenced directly from the declaration form or defined as custom fields that combine multiple form values. If some value contains PII data, they can optionally be hidden via the `secured` flag so that the data will only be visible once the record is assigned to the user.
224+
225+
226+
#### Quick Search
227+
228+
The dropdown previously available in the search bar has been removed.
229+
Any search performed through the **Quick Search** bar is now executed against common record properties such as names, tracking ID, and registration number by default, providing a more streamlined and consistent search experience.
230+
231+
#### Certificate Template Variables
232+
233+
The following variables are available for use within certificate templates:
234+
235+
* **`$declaration`** – Contains the latest raw declaration form data. Typically used with the `$lookup` Handlebars helper to resolve values into human-readable text.
236+
* **`$metadata`** – Contains the `EventMetadata` object. Commonly used with the `$lookup` helper for resolving metadata fields into readable values.
237+
* **`$review`** – A boolean flag indicating whether the certificate is being rendered in review mode.
238+
* **`$references`** – Contains reference data for locations and users, accessible via `{{ $references.locations }}` and `{{ $references.users }}`.
239+
This is useful when manually resolving values from `$declaration`, `$metadata` or `action`.
240+
241+
##### Handlebars Helpers
242+
243+
The following helpers are supported within certificate templates:
244+
245+
* **`$lookup`** – Resolves values from `$declaration`, `$metadata`, or `action` data into a human-readable format.
246+
* **`$intl`** – Dynamically constructs a translation key by joining multiple string parts.
247+
Example:
248+
249+
```hbs
250+
{{ $intl 'constants.greeting' (lookup $declaration "child.name") }}
251+
```
252+
* **`$intlWithParams`** – Enables dynamic translations with parameters.
253+
Takes a translation ID as the first argument, followed by parameter name–value pairs.
254+
Example:
255+
256+
```hbs
257+
{{ $intlWithParams 'constants.greeting' 'name' (lookup $declaration "child.name") }}
258+
```
259+
* **`$actions`** – Resolves all actions for a specified action type.
260+
Example:
261+
262+
```hbs
263+
{{ $actions "PRINT_CERTIFICATE" }}
264+
```
265+
* **`$action`** – Retrieves the latest action data for a specific action type.
266+
Example:
267+
268+
```hbs
269+
{{ $action "PRINT_CERTIFICATE" }}
270+
```
271+
* **`ifCond`** – Compares two values (`v1` and `v2`) using the specified operator and conditionally renders a block based on the result.
272+
**Supported operators:**
273+
274+
* `'==='` – strict equality
275+
* `'!=='` – strict inequality
276+
* `'<'`, `'<='`, `'>'`, `'>='` – numeric or string comparisons
277+
* `'&&'` – both values must be truthy
278+
* `'||'` – at least one value must be truthy
279+
280+
**Usage example:**
281+
282+
```hbs
283+
{{#ifCond value1 '===' value2}}
284+
...
285+
{{/ifCond}}
286+
```
287+
* **`$or`** – Returns the first truthy value among the provided arguments.
288+
* **`$json`** – Converts any value to its JSON string representation (useful for debugging).
289+
290+
Besides the ones introduced above, all built-in [Handlebars helpers](https://handlebarsjs.com/guide/builtin-helpers.html) are available.
291+
292+
Custom helpers can also be added by exposing functions from this [file](https://github.com/opencrvs/opencrvs-countryconfig/blob/develop/src/form/common/certificate/handlebars/helpers.ts#L0-L1).
293+
294+
---
295+
296+
To see Events V2 in action, check out the example configurations in the **countryconfig** repository.
297+
298+
---
299+
300+
301+
7302
- **Redis password support with authorization and authentication** [#9338](https://github.com/opencrvs/opencrvs-core/pull/9338). By default password is disabled for local development environment and enabled on server environments.
8303
- **Switch back to default redis image** [#10173](https://github.com/opencrvs/opencrvs-core/issues/10173)
9304
- **Certificate Template Conditionals**: Certificate template conditionals allow dynamic template selection based on print history using the template conditional helpers.. [#7585](https://github.com/opencrvs/opencrvs-core/issues/7585)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"description": "OpenCRVS core workspace",
33
"license": "MPL-2.0",
4-
"version": "1.8.1",
4+
"version": "1.9.0",
55
"private": true,
66
"os": [
77
"darwin",

packages/api-docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opencrvs/api-docs",
3-
"version": "1.8.0",
3+
"version": "1.9.0",
44
"description": "OpenCRVS API documentation",
55
"license": "MPL-2.0",
66
"scripts": {

packages/auth/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opencrvs/auth",
3-
"version": "1.8.1",
3+
"version": "1.9.0",
44
"description": "OpenCRVS authentication service",
55
"license": "MPL-2.0",
66
"private": true,
@@ -20,7 +20,7 @@
2020
"dependencies": {
2121
"@hapi/boom": "^9.1.1",
2222
"@hapi/hapi": "^20.0.1",
23-
"@opencrvs/commons": "^1.7.0",
23+
"@opencrvs/commons": "^1.9.0",
2424
"app-module-path": "^2.2.0",
2525
"dotenv": "^6.1.0",
2626
"envalid": "^8.0.0",

0 commit comments

Comments
 (0)