Skip to content

Commit

Permalink
Merge branch 'main' into mrjones-plip-patch-3
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjones-plip authored Aug 7, 2023
2 parents c1de82c + 91cedb2 commit fce1d26
Show file tree
Hide file tree
Showing 33 changed files with 346 additions and 201 deletions.
36 changes: 36 additions & 0 deletions .github/scripts/set_dns.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash

# At one point we had issues with the DNS server that GH CI Runners use,
# so this script was written to change Muffet to use Quad9. While Quad9 presumably
# will be a bit slower than local DNS to GH CI, it shouldn't matter as Muffet
# is run once a day and is not speed sensitive.
#
# More Info:
# - Issue: local-ip.medicmobile.org doesn't resolve on GH runners, causes
# link check errors (https://github.com/medic/cht-docs/issues/1106)
# - Quad9: 9.9.9.9 DNS Server being used (https://quad9.net)

echo
echo "------------------------"
echo "calling: resolvectl dns eth0"
resolvectl dns eth0

echo
echo "------------------------"
echo "calling: dig local-ip.medicmobile.org +short"
dig local-ip.medicmobile.org +short

echo
echo "------------------------"
echo "calling: sudo resolvectl dns eth0 9.9.9.9 149.112.112.112"
sudo resolvectl dns eth0 9.9.9.9 149.112.112.112

echo
echo "------------------------"
echo "calling: resolvectl dns eth0"
resolvectl dns eth0

echo
echo "------------------------"
echo "calling: dig local-ip.medicmobile.org +short"
dig local-ip.medicmobile.org +short
22 changes: 13 additions & 9 deletions .github/workflows/daily.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,44 +20,48 @@ jobs:
timeout-minutes: 15
steps:

- name: All Branches - Git checkout
- name: Git checkout cht-docs repos
uses: actions/checkout@v2
with:
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod

- name: All Branches - Install hugo extended v0.101.0
- name: Install hugo extended v0.101.0
uses: peaceiris/actions-hugo@v2
with:
hugo-version: "0.101.0"
extended: true

- name: All Branches - Install Node 12.x
- name: Install Node 12.x
uses: actions/setup-node@v1
with:
node-version: '12.x'

- name: All Branches - Install npm modules for Hugo
- name: Install npm modules for Hugo
run: npm install

- name: All Branches - Install Go v1.18
- name: Install Go v1.18
uses: actions/setup-go@v2
with:
go-version: '1.18'

- name: All Branches - Install Muffet v1.5.7
- name: Install Muffet v1.5.7
run: GO111MODULE=on go install github.com/raviqqe/[email protected]

# run in background so CI doesn't hang waiting for "ctrl + c". Sleep ensures server is ready in next step
- name: All Branches - Serve Hugo site
- name: Serve Hugo site
run: |
hugo server&
sleep 30
- name: All Branches - Run Muffet link checker
- name: Set DNS to 9.9.9.9
shell: bash
run: ./.github/scripts/set_dns.sh

- name: Run Muffet link checker
shell: bash
run: ./.github/scripts/muffet.sh

- name: Main Branch Only - Report errors to Slack, if any
- name: Report errors to Slack, if any
if: ${{ github.ref == 'refs/heads/main' && failure() }}
uses: rtCamp/[email protected]
env:
Expand Down
2 changes: 1 addition & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ anchor = "smart"
[services]
[services.googleAnalytics]
# Comment out the next line to disable GA tracking. Also disables the feature described in [params.ui.feedback].
id = "G-362515267"
id = "G-98W4V2NTPJ"

# Language configuration

Expand Down
38 changes: 20 additions & 18 deletions content/en/apps/concepts/interoperability.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,21 @@ title: Interoperability
linkTitle: "Interoperability"
weight: 8
description: >
Exchanging information between CHT Core and other systems
Exchanging information between the CHT Core and other health systems
keywords: interoperability integrations fhir icd openhie openhim
relatedContent: >
apps/features/integrations
---

# Introduction
## Introduction

Interoperability is the ability of health information systems to work together, even if they weren't specifically designed to work together. With interoperability, patient information can be seen, exchanged, and used across different platforms. This is different from _integration_ which requires custom development to connect two specific systems together.
Interoperability refers to the ability of different health information systems and applications to communicate with each other and exchange data seamlessly. With interoperability, patient information can be seen, exchanged, and used across different platforms. The information/data exchanged has to be understood across the different software for these systems to become interoperable. This is different from _integration_ which requires custom development to connect two specific systems together.

Interoperability is the best practice for health systems because it allows information from one system to be shared with one or more other systems with no additional development.
Interoperability is the best practice for health systems because it allows information from one system to be shared with one or more other systems with no additional development. Interoperability allows technical teams to scale in an efficient and repeatable manner due to the already predefined standards.

# Components
## CHT Interoperability

Useful components and reference information for interoperability include:

- [OpenHIE](https://ohie.org/) defines the architecture for an interoperability layer.
- [OpenHIM](http://openhim.org/) is a middleware component designed to ease interoperability between systems.
- [HL7 FHIR](https://www.hl7.org/fhir/index.html) is a messaging format to allow all systems to understand the format of the message.
- [ICD-11](https://www.who.int/standards/classifications/classification-of-diseases) and [LOINC](https://loinc.org/) are examples of classification systems.

# CHT

The structure of documents in the CHT database reflect the configuration of the system, and therefore do not map directly to a FHIR message format. To achieve interoperability you should use middleware to convert the CHT datastructure into a standardized form so the other systems can read it.
The native CHT database structure does not map directly to a [Fast Healthcare Interoperability Resources (FHIR)](http://www.hl7.org/fhir/) message format. To be compatible, we use a middleware to convert the CHT data structure into a standardized JSON format so the other systems can read it.

```mermaid
graph LR
Expand All @@ -41,9 +32,20 @@ mediator_a -- Request\nfa:fa-arrow-right --- openhim
mediator_b -- Channel\nfa:fa-arrow-left --- openhim
```

The recommended approach is to use OpenHIM as the middleware component with [Mediators](http://openhim.org/docs/configuration/mediators/) to do the conversion. [Outbound Push]({{< ref "apps/reference/app-settings/outbound" >}}) should be configured to make a request to the middleware when relevant documents are created or modified in the CHT. A Mediator then calls [CHT APIs]({{< ref "apps/reference/api" >}}) to gather any additional data required to create a FHIR resource which is then routed to OpenHIM. OpenHIM will then route the resource to any other configured systems.
## Standards & Components

- [OpenHIE](https://ohie.org/): OpenHIE is an open-source framework for building interoperable health information systems. OpenHIE provides a set of standards and protocols for enabling different health systems and applications to communicate with each other.

- [OpenHIM](http://openhim.org/): OpenHIM is an open-source middleware platform that provides a central point of control for managing health information exchange (HIE). OpenHIM enables healthcare providers to connect different health systems and applications and provides a common interface for managing data exchange and security.

- [FHIR](http://www.hl7.org/fhir): FHIR is a standard for exchanging healthcare data electronically. FHIR provides a modern, web-based approach to exchanging healthcare data and is rapidly becoming the preferred standard for healthcare interoperability.


Conversely to bring data in to the CHT, OpenHIM should be configured to route the updated resource to a Mediator, which then calls the relevant CHT APIs to update the document in the CHT database. This will then be replicated to users' devices as per usual.
A reference application for this pattern is available in the [CHIS Interoperability repository](https://github.com/medic/cht-interoperability).
This application implements a Loss to Follow Up (LTFU) workflow system for CHIS based on the [OpenHIE LTFU Guide](https://wiki.ohie.org/display/CP/Use+Case+Summary%3A+Request+Community+Based+Follow-Up).

A reference application for this pattern is available in the [CHIS Interoperability repository](https://github.com/medic/chis-interoperability).
## Important Links
- [cht-interoperability repository](https://github.com/medic/cht-interoperability): A reference application for the LTFU workflow
- [CHT Instance with LTFU configuration](https://interop-cht-test.dev.medicmobile.org/medic/login?redirect=https%3A%2F%2Finterop-cht-test.dev.medicmobile.org%2F)
- [OpenHIM Admin Console](https://interoperability.dev.medicmobile.org/#!/login)

2 changes: 1 addition & 1 deletion content/en/apps/features/supervision/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ The CHT can be configured to create [Tasks]({{< relref "apps/features/tasks" >}}
## User Management
Supervisors are able to set up users in the CHT without contacting a system administrator. They can **create** new CHW user accounts or **replace** CHWs on an existing device.

When _creating_ a new user account, Supervisors fill out the necessary details, including the CHW's phone number, from their own device. They can do this while offline, but must sync before the actual user account is created. Once the Supervisor syncs, the CHT will send an SMS to the new CHW with a link that enables them to start using the app.
When _creating_ a new user account, Supervisors fill out the necessary details, including the CHW's phone number, from their own device. They can do this while offline, but must sync before the actual user account is created. Once the Supervisor syncs, the CHT will send an SMS to the new CHW with a [magic link]({{< relref "apps/concepts/access#magic-links-for-logging-in-token-login" >}}) that enables them to login and start using the app.

When _replacing_ a CHW, Supervisors access the existing device and provide details about the new CHW. The new CHW can start using the app immediately, even while offline, and will see all of the existing household data. Once the new CHW syncs, the records on the server will be updated to reflect the new CHWs details.
This can be used to manage both CHW and CHW supervisor roles.
6 changes: 3 additions & 3 deletions content/en/apps/guides/forms/app-form-sms.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ relatedContent: >

## Triggering Calls and SMS

When a XForm is loaded on a phone you can start a phone call or trigger the sending of an SMS within the form itself. This can be useful if within a task or assessment you want to tell the user to contact a patient, or perhaps a health worker at a facility.
When an XForm is loaded on a phone you can start a phone call or trigger the sending of an SMS within the form itself. This can be useful if within a task or assessment, you want to tell the user to contact a patient, or perhaps a health worker at a facility.

To set up the call or SMS you'll need to create a link with `tel:` or `sms:` within a `note` field. To create the link, use the markdown link format, eg `[Call Patient](tel:+2547009875000)`. You can specify the content of the SMS by using the body parameter, eg `[Send SMS](sms://+25470098765000?body=Hello World!)`.

The phone number and message can be generated from fields within the XForm. For instance, if you have `patient_name`, `patient_phone` and `message` fields, you can generate the SMS as follows:
The phone number and message can be generated from fields within the XForm. For instance, if you have `patient_name`, `patient_phone`, and `message` fields, you can generate the SMS as follows:
- **XLSForm**
`[Send SMS to ${patient_name}](sms://${patient_phone}?body=${message})`

Expand Down Expand Up @@ -47,7 +47,7 @@ To get forms sent in this format, follow the [ODK documentation](https://getodk.

### Medic Custom SMS representation

To configure a form to send using Medic's custom SMS definition, the value of `xml2sms` from the form's CouchDB doc should be an string containing an [Angular expression](https://docs.angularjs.org/guide/expression).
To configure a form to send using Medic's custom SMS definition, the value of `xml2sms` from the form's CouchDB doc should be a string containing an [Angular expression](https://docs.angularjs.org/guide/expression).
This allows access to the `fields` property of the `data_record` doc created when saving the form submission to the database. Extra functions are also provided to make compiling a form submission more simple.

#### Special Functions
Expand Down
22 changes: 11 additions & 11 deletions content/en/apps/guides/hosting/3.x/app-developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,17 @@ If you still get stuck review the items below as possible issues you may find wo
If you're on macOS, or other OS without the `ip` utility, your IP address will always show as `127.0.0.1`. You can not connect to this IP from a mobile client on your LAN because it always references the host it's on, not a foreign host.
To work around this, you can find out your IP on your LAN and just replace the `127-0-0-1` part of the `https://127-0-0-1.my.local-ip.co:8443` URL to be your IP address. So if your local IP was `192.168.0.22` your URL would be `https://192-168-0-22.my.local-ip.co:8443`.
To work around this, you can find out your IP on your LAN and just replace the `127-0-0-1` part of the `https://127-0-0-1.local-ip.medicmobile.org:8443` URL to be your IP address. So if your local IP was `192.168.0.22` your URL would be `https://192-168-0-22.local-ip.medicmobile.org:8443`.
#### Booting with no connectivity
This script can work without connectivity after the initial boot. However, it needs connectivity to do DNS lookups for the *.my.local-ip.co URLs. To work around this, when you have no connectivity, add an entry in your `/etc/hosts` for the URL showing up in the script. For example, if you're seeing `https://127-0-0-1.my.local-ip.co:8443` as your IP, add this line to the top of your `/etc/hosts` file.
This script can work without connectivity after the initial boot. However, it needs connectivity to do DNS lookups for the `*.local-ip.medicmobile.org` URLs. To work around this, when you have no connectivity, add an entry in your `/etc/hosts` for the URL showing up in the script. For example, if you're seeing `https://127-0-0-1.local-ip.medicmobile.org:8443` as your IP, add this line to the top of your `/etc/hosts` file.

```shell script
127.0.0.1 127-0-0-1.my.local-ip.co
127.0.0.1 127-0-0-1.local-ip.medicmobile.org
```

_**NOTE**_ - You need connectivity on the initial boot of the VM to connect to `staging.dev.medicmobile.org` to download the base version of the CHT. As well, certificates for `*.my.local-ip.co` are downloaded. Subsequent boots do not require connectivity as long as you do not run `destroy`.
_**NOTE**_ - You need connectivity on the initial boot of the VM to connect to `staging.dev.medicmobile.org` to download the base version of the CHT. As well, certificates for `*.local-ip.medicmobile.org` are downloaded. Subsequent boots do not require connectivity as long as you do not run `destroy`.

#### Port conflicts

Expand Down Expand Up @@ -281,7 +281,7 @@ When you first call the script, a line is output with generic information about
| Name in log | Note | Example(s) |
| --------------- | --------------- | --------------- |
| `item` | which log item this is | `start` |
| `URL` | the full URL of the instance, with port | `https://192-168-68-17.my.local-ip.co:443` |
| `URL` | the full URL of the instance, with port | `https://192-168-68-17.local-ip.medicmobile.org:443` |
| `IP` | the IP address of the instance | `192.168.68.17` |
| `port_https` | port used for `https` | `443` or `8443` |
| `port_http` | port used for `http` | `80` or `8080` |
Expand All @@ -298,7 +298,7 @@ For each internal loop of the script, each one taking 1-5 seconds, a status line
| `CHT_count` | number of CHT contianers running for this project. Healthy is `2` | `2` |
| `port_stat` | Status of the `https` port. Healhty is `open` | `open` or `closed` |
| `http_code` | If the `https` port is open by the web server, what `HTTP` response code is returned for a `GET`. Healthy is `200`. If you see `000`, [see workarounds](#booting-with-no-connectivity). | `200` or `404` |
| `ssl_verify` | If the `https` port is open by the web server, is the valid `local-ip.co` certificate installed. Healthy is `yes` | `yes` or `no` |
| `ssl_verify` | If the `https` port is open by the web server, is the valid `local-ip.medicmobile.org` certificate installed. Healthy is `yes` | `yes` or `no` |
| `reboot_count` | How many times `docker restart` has been called. Max is `5` | `3` |
| `docker_call` | The docker action call to the script | `up` |
| `last_msg` | Last message the user was shown | `Running "down" then "up"` |
Expand All @@ -318,7 +318,7 @@ For each internal loop of the script, each one taking 1-5 seconds, a status line
#### Sample
```shell
Fri 15 Oct 2021 02:30:26 PM PDT pid="410066" count="1" item="start" URL="https://192-168-68-17.my.local-ip.co:443" IP="192.168.68.17" port_https="443" port_http="80" project_name="helper_test" total_containers="2"
Fri 15 Oct 2021 02:30:26 PM PDT pid="410066" count="1" item="start" URL="https://192-168-68-17.local-ip.medicmobile.org:443" IP="192.168.68.17" port_https="443" port_http="80" project_name="helper_test" total_containers="2"
Fri 15 Oct 2021 02:30:26 PM PDT pid="410066" count="1" item="docker_logs" container="helper_test_medic-os_1" processes="64" last_log="[2021/10/15 19:53:39] Info: Horticulturalist has already bootstrapped"
Fri 15 Oct 2021 02:30:26 PM PDT pid="410066" count="1" item="docker_logs" container="helper_test_haproxy_1" processes="4" last_log="Oct 15 21:30:20 576ca039cd88 haproxy[25]: 172.20.0.3,200,GET,/medic/_design/medic,-,medic,'-',21703,5,21402,'curl/7.68.0'"
Fri 15 Oct 2021 02:30:26 PM PDT pid="410066" count="1" item="status" CHT_count="2" port_stat="open" http_code="200" ssl_verify="yes" reboot_count="0" docker_call="up" last_msg="Initializing" load_now="2.66" helper_test_haproxy_1="true" helper_test_medic-os_1="true"
Expand All @@ -329,15 +329,15 @@ Fri 15 Oct 2021 02:30:28 PM PDT pid="410066" count="2" item="status" CHT_count="
## Cookie collisions
The CHT stores its cookies based on the domain. This means if you're running two concurrent instances on `https://192-168-68-40.my.local-ip.co:8443` and `https://192-168-68-40.my.local-ip.co:8440` (note different ports), the CHT would write the cookie under the same `192-168-68-40.my.local-ip.co` domain. When logging out of one instance, you would get logged out of both and other consistencies.
The CHT stores its cookies based on the domain. This means if you're running two concurrent instances on `https://192-168-68-40.local-ip.medicmobile.org:8443` and `https://192-168-68-40.local-ip.medicmobile.org:8440` (note different ports), the CHT would write the cookie under the same `192-168-68-40.local-ip.medicmobile.org` domain. When logging out of one instance, you would get logged out of both and other consistencies.
To avoid this collision of cookies, you can use different IP addresses to access the instances. This works because of two reasons:
1. the TLS certificate being used is valid for any subdomain of `*.my.local-ip.co`. Further, the URL always resolves to the IP passed in the `*` section, so you can use any IP
1. the TLS certificate being used is valid for any subdomain of `*.local-ip.medicmobile.org`. Further, the URL always resolves to the IP passed in the `*` section, so you can use any IP
2. the IPs that are available to reference your `localhost` are actually a `/8` netmask, meaning [there are 16 million addresses](https://en.wikipedia.org/wiki/Localhost#Name_resolution) to choose from!
Using the above two reasons, these URLs could work to avoid the cookie collision:
* `https://127-0-0-1.my.local-ip.co:8443`
* `https://127-0-0-2.my.local-ip.co:8440`
* `https://127-0-0-1.local-ip.medicmobile.org:8443`
* `https://127-0-0-2.local-ip.medicmobile.org:8440`
This would result in the domains being `127.0.0.1` and `127.0.0.2` from the CHT's perspective. When using a mobile device for testing, you're limited to use the LAN ip output in the helper and can not use the `127.x.x.x` IPs.
Loading

0 comments on commit fce1d26

Please sign in to comment.