Controlar o acesso aos recursos FHIR na API Cloud Healthcare

Nesta página, descrevemos como usar recursos de consentimento FHIR para determinar o acesso a dados de armazenamentos FHIR na API Cloud Healthcare.

Para configurar um armazenamento FHIR com a aplicação de consentimento, siga estas etapas:

  1. Crie um armazenamento FHIR, caso ainda não tenha um.

  2. Defina os parâmetros ConsentConfig do repositório FHIR a seguir para ativar a aplicação do consentimento:

    • version: especifica qual versão de aplicação do consentimento está sendo usada para o armazenamento FHIR. Esse valor só pode ser definido uma vez por CreateFhirStore ou UpdateFhirStore. Depois de definir, chame ApplyConsents ou ApplyAdminConsents para mudar a versão.

    • access_enforced: se definido como true, ao acessar os recursos FHIR, os cabeçalhos de consentimento fornecidos vão ser verificados em relação às diretivas de consentimento fornecidas pelos consumidores.

    • consent_header_handling: se definido como PERMIT_EMPTY_SCOPE (padrão), o servidor permitirá solicitações sem o cabeçalho X-Consent-Scope (ou vazio). Se definido como REQUIRED_ON_READ e access_enforced = true, o servidor rejeitará todas as solicitações sem o cabeçalho X-Consent-Scope (ou vazio).

Configurar um novo repositório FHIR com ConsentConfig

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json" \
    --data "{
      'version': 'R4',
      'enableUpdateCreate': true,
      'consentConfig': {
        'version': 'V1',
        'accessEnforced': true
      }
    }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores?fhirStoreId=FHIR_STORE_ID"

Você receberá uma resposta JSON semelhante a esta:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID",
  "version": "R4",
  "enableUpdateCreate": true,
  "consentConfig": {
    "version": "V1"
  }
}

Se você já tem um armazenamento, use UpdateFhirStore para definir o ConsentConfig com o version da aplicação de consentimento como V1 e defina accessEnforced como true.

curl -X PATCH \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json" \
    --data "{
      'consentConfig': {
        'version': 'V1',
        'accessEnforced': true
      }
    }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID?update_mask=consentConfig"

As políticas são representadas pelo recurso de consentimento. A finalidade e o uso dos campos de recurso são descritos nos Documentos de modelo de dados.

Veja um exemplo de todos os recursos que podem ser criados para este exemplo específico.

Criar recursos FHIR

O exemplo a seguir mostra como executar um [pacote FHIR](/healthcare-api/docs/how-tos/fhir-bundles) para preencher os recursos a seguir:

  • Um recurso para profissionais com o nome Jeffrey Brown
  • Um recurso de paciente chamado Darcy Smith
  • Um recurso de observação que mostra a medição da hemoglobina de Darcy (LOINC718-7) que foi coletada pelo Happy Hospital
  • Um recurso de observação mostrando a medição de glicose de Darcy (LOINC15074-8).
  • Uma autorização da Darcy para permitir que Jeffrey Brown use o aplicativo App/123 para acessar os dados coletados pelo Happy Hospital
  • O consentimento de Darcy para permitir que Jeffrey Brown acesse os dados dela para tratamento de emergência (ETREAT)
  • Uma autorização do Happy Hospital para permitir que Jeffrey Brown acesse todos os dados ao fazer pesquisas biomédicas (BIORCH) com o aplicativo App/golden

cat > bundle.json << 'EOF'
{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "request": {"method": "PUT", "url": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"},
      "resource": {
        "active": true,
        "birthDate": "1970-05-23",
        "gender": "male",
        "id": "12942879-f89f-41ae-aa80-0b911b649833",
        "name": [{
            "family": "Brown",
            "given": ["Jeffrey"],
            "use": "official"
        }],
        "resourceType": "Practitioner"
      }
    },
    {
      "request": {"method": "PUT", "url": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"},
      "resource": {
        "active": true,
        "birthDate": "1990-01-01",
        "gender": "female",
        "id": "3c6aa096-c054-4c22-b2b4-1e4a4d203de2",
        "name": [{
            "family": "Smith",
            "given": ["Darcy"],
            "use": "official"
        }],
        "meta": {
          "tag": [{
            "system": "http://terminology.hl7.org/CodeSystem/common-tags",
            "code": "employee"
          }]
        },
        "resourceType": "Patient"
      }
    },
    {
      "request": {"method": "PUT", "url": "Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"},
      "resource": {
        "id": "7473784b-46a8-470c-b9a6-fe38a01025aa",
        "meta": {"source": "http://example.com/HappyHospital"},
        "code": {
          "coding": [{
            "code": "718-7",
            "system": "http://loinc.org",
            "display": "Hemoglobin [Mass/volume] in Blood"
          }]
        },
        "effectivePeriod": {"start": "2021-12-10T05:30:10+01:00"},
        "issued": "2021-12-10T13:30:10+01:00",
        "resourceType": "Observation",
        "status": "final",
        "subject": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"},
        "valueQuantity": {
          "code": "g/dL",
          "system": "http://unitsofmeasure.org",
          "unit": "g/dl",
          "value": 7.2
        }
      }
    },
    {
      "request": {"method": "PUT", "url": "Observation/68583624-9921-4158-8754-2a306c689abd"},
      "resource": {
        "id": "68583624-9921-4158-8754-2a306c689abd",
        "code": {
          "coding": [{
            "code": "15074-8",
            "system": "http://loinc.org",
            "display": "Glucose [Moles/volume] in Blood"
          }]
        },
        "effectivePeriod": {"start": "2021-12-01T05:30:10+01:00"},
        "issued": "2021-12-01T13:30:10+01:00",
        "resourceType": "Observation",
        "status": "final",
        "subject": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"},
        "valueQuantity": {
          "code": "mmol/L",
          "system": "http://unitsofmeasure.org",
          "unit": "mmol/l",
          "value": 6.3
        }
      }
    },
    {
      "request": {"method": "PUT", "url": "Consent/10998b60-a252-405f-aa47-0702554ddc8e"},
      "resource": {
        "category": [{
          "coding": [{
            "code": "59284-0",
            "system": "http://terminology.hl7.org/CodeSystem/consentcategorycodes"
          }]
        }],
        "id": "10998b60-a252-405f-aa47-0702554ddc8e",
        "patient": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"},
        "policyRule": {
          "coding": [{
            "code": "OPTIN",
            "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
          }]
        },
        "provision": {
          "actor": [
            {
              "reference": {"reference": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"},
              "role": {
                "coding": [{
                  "code": "GRANTEE",
                  "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode"
                }]
              }
            }
          ],
          "extension": [
            {
              "url": "https://g.co/fhir/medicalrecords/Environment",
              "valueCodeableConcept": {
                "coding": [{
                  "code": "123",
                  "system": "App"
                }]
              }
            },
            {
              "url": "https://g.co/fhir/medicalrecords/DataSource",
              "valueUri": "http://example.com/HappyHospital"
            }
          ],
          "type": "permit"
        },
        "resourceType": "Consent",
        "scope": {
          "coding": [{
            "code": "patient-privacy",
            "system": "http://terminology.hl7.org/CodeSystem/consentscope"
          }]
        },
        "status": "active"
      }
    },
    {
      "request": {"method": "PUT", "url": "Consent/73c54e8d-2789-403b-9dee-13085c5d5e34"},
      "resource": {
        "category": [{
          "coding": [{
            "code": "59284-0",
            "system": "http://terminology.hl7.org/CodeSystem/consentcategorycodes"
          }]
        }],
        "id": "73c54e8d-2789-403b-9dee-13085c5d5e34",
        "patient": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"},
        "policyRule": {
          "coding": [{
            "code": "OPTIN",
            "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
          }]
        },
        "provision": {
          "actor": [
            {
              "reference": {"reference": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"},
              "role": {
                "coding": [{
                  "code": "GRANTEE",
                  "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode"
                }]
              }
            }
          ],
          "purpose": [{
            "code": "ETREAT",
            "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason"
          }],
          "type": "permit"
        },
        "resourceType": "Consent",
        "scope": {
          "coding": [{
            "code": "patient-privacy",
            "system": "http://terminology.hl7.org/CodeSystem/consentscope"
          }]
        },
        "status": "active"
      }
    },
    {
      "request": {"method": "PUT", "url": "Consent/5c8e3f8a-9fd5-480d-a08e-f29b89feccde"},
      "resource": {
        "category": [{
          "coding": [{
            "code": "57017-6",
            "system": "http://loinc.org"
          }]
        }],
        "id": "5c8e3f8a-9fd5-480d-a08e-f29b89feccde",
        "patient": {},
        "extension": [{
          "url": "https://g.co/fhir/medicalrecords/ConsentAdminPolicy"
        }],
        "policyRule": {
          "coding": [{
            "code": "OPTIN",
            "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
          }]
        },
        "provision": {
          "actor": [
            {
              "reference": {"reference": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"},
              "role": {
                "coding": [{
                  "code": "GRANTEE",
                  "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode"
                }]
              }
            }
          ],
          "purpose": [{
            "code": "BIORCH",
            "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason"
          }],
          "extension": [
            {
              "url": "https://g.co/fhir/medicalrecords/Environment",
              "valueCodeableConcept": {
                "coding": [{
                  "code": "golden",
                  "system": "App"
                }]
              }
            }
          ],
          "type": "permit"
        },
        "resourceType": "Consent",
        "scope": {},
        "status": "active"
      }
    }
  ]
}
EOF
curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/fhir+json; charset=utf-8" \
    --data @bundle.json \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir"

Você receberá uma resposta JSON semelhante a esta:

{
  "entry": [
    {
      "response": {
        "etag": "W/\"VERSION_ID\"",
        "lastModified": "2022-09-01T17:31:40.423469+00:00",
        "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/12942879-f89f-41ae-aa80-0b911b649833/_history/VERSION_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "W/\"VERSION_ID\"",
        "lastModified": "2022-09-01T17:31:40.423469+00:00",
        "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2/_history/VERSION_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "W/\"VERSION_ID\"",
        "lastModified": "2022-09-01T17:31:40.423469+00:00",
        "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa/_history/VERSION_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "W/\"VERSION_ID\"",
        "lastModified": "2022-09-01T17:31:40.423469+00:00",
        "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/68583624-9921-4158-8754-2a306c689abd/_history/VERSION_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "W/\"VERSION_ID\"",
        "lastModified": "2022-09-01T17:31:40.423469+00:00",
        "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/10998b60-a252-405f-aa47-0702554ddc8e/_history/VERSION_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "W/\"VERSION_ID\"",
        "lastModified": "2022-09-01T17:31:40.423469+00:00",
        "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/73c54e8d-2789-403b-9dee-13085c5d5e34/_history/VERSION_ID",
        "status": "201 Created"
      }
    },
    {
      "response": {
        "etag": "W/\"VERSION_ID\"",
        "lastModified": "2022-09-01T17:31:40.423469+00:00",
        "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/5c8e3f8a-9fd5-480d-a08e-f29b89feccde/_history/VERSION_ID",
        "status": "201 Created"
      }
    }
  ],
  "resourceType": "Bundle",
  "type": "transaction-response"
}

Veja a seguir mais exemplos do recurso de consentimento R4 que demonstram como políticas complexas podem ser representadas.

{
  "resourceType": "Consent",
  "id": "patient-consent-example",
  "patient": {
    "reference": "Patient/f001"
  },
  "category": [
    {
      "coding": [
        {
          "system": "http://loinc.org",
          "code": "59284-0"
        }
      ]
    }
  ],
  "scope": {
    "coding": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/consentscope",
        "code": "patient-privacy"
      }
    ]
  },
  "policyRule": {
    "coding": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "OPTIN"
      }
    ]
  },
  "status": "active",
  "provision": {
    "type": "permit",
    "actor": [
      {
        "reference": {
          "reference": "Practitioner/f002"
        },
        "role": {
          "coding": [
            {
              "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode",
              "code": "GRANTEE"
            }
          ]
        }
      }
    ],
    "purpose": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason",
        "code": "TREAT"
      }
    ],
    "class": [
      {
        "system": "http://hl7.org/fhir/resource-types",
        "code": "Encounter"
      }
    ],
    "data": [
      {
        "meaning": "instance",
        "reference": {
          "reference": "Encounter/e001"
        }
      }
    ],
    "extension": [
      {
        "url": "https://g.co/fhir/medicalrecords/Environment",
        "valueCodeableConcept": {
          "coding": [
            {
              "system": "iso3166-1",
              "code": "CA"
            }
          ]
        }
      },
      {
        "url": "https://g.co/fhir/medicalrecords/DataTag",
        "valueCoding": {
          "system": "http://terminology.hl7.org/CodeSystem/common-tags",
          "code": "actionable"
        }
      },
      {
        "url": "https://g.co/fhir/medicalrecords/DataTag",
        "extension": [
          {
            "url": "https://g.co/fhir/medicalrecords/DataTag",
            "valueCoding": {
              "system": "http://example.com/custom-tags",
              "code": "archived"
            }
          },
          {
            "url": "https://g.co/fhir/medicalrecords/DataTag",
            "valueCoding": {
              "system": "http://example.com/custom-tags",
              "code": "insensitive"
            }
          }
        ]
      },
      {
        "url": "https://g.co/fhir/medicalrecords/DataSource",
        "valueUri": "http://somesystem.example.org/foo"
      }
    ],
    "securityLabel": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-Confidentiality",
        "code": "R"
      },
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "PSY"
      }
    ]
  }
}

O exemplo anterior representa um recurso de consentimento do paciente em que um f001 de paciente dá permissão a um profissional f002 com o objetivo de fornecer tratamento regular representado por TREAT. O profissional é da geolocalização iso3166-1/CA. Esse recurso de consentimento permite que o profissional acesse os dados do paciente se eles atenderem a todas as condições a seguir.

  • É um tipo de Encounter com o ID Encounter/e001.
  • Ele vem da origem http://somesystem.example.org/foo.
  • Ela atende a pelo menos uma das condições a seguir na tag (os recursos podem ser marcados com a configuração dos campos system e code das Meta.tags):
    • Tem a tag (system = http://terminology.hl7.org/CodeSystem/common-tags e code = actionable)
    • Tem as duas tags (system = http://example.com/custom-tags e code = archived) e (system = http://example.com/custom-tags e code = insensitive)
  • Tem pelo menos um dos seguintes marcadores de segurança
    • system = http://terminology.hl7.org/CodeSystem/v3-Confidentiality e code é uma destas opções: R, N, M, L ou U.
    • system = http://terminology.hl7.org/CodeSystem/v3-ActCode e code = PSY

Exemplo de diretiva de política do administrador

{
  "resourceType": "Consent",
  "id": "admin-policy-example",
  "patient": {},
  "extension": [{
    "url": "https://g.co/fhir/medicalrecords/ConsentAdminPolicy"
  }],
  "category": [
    {
      "coding": [
        {
          "system": "http://loinc.org",
          "code": "57017-6"
        }
      ]
    }
  ],
  "scope": {},
  "policyRule": {
    "coding": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "OPTIN"
      }
    ]
  },
  "status": "active",
  "provision": {
    "type": "permit",
    "actor": [
      {
        "reference": {
          "reference": "Practitioner/f002"
        },
        "role": {
          "coding": [
            {
              "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode",
              "code": "GRANTEE"
            }
          ]
        }
      }
    ],
    "purpose": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason",
        "code": "TREAT"
      }
    ],
    "class": [
      {
        "system": "http://hl7.org/fhir/resource-types",
        "code": "Encounter"
      }
    ],
    "data": [
      {
        "meaning": "instance",
        "reference": {
          "reference": "Encounter/e001"
        }
      }
    ],
    "extension": [
      {
        "url": "https://g.co/fhir/medicalrecords/Environment",
        "valueCodeableConcept": {
          "coding": [
            {
              "system": "iso3166-1",
              "code": "CA"
            }
          ]
        }
      },
      {
        "url": "https://g.co/fhir/medicalrecords/DataTag",
        "valueCoding": {
          "system": "http://terminology.hl7.org/CodeSystem/common-tags",
          "code": "actionable"
        }
      },
      {
        "url": "https://g.co/fhir/medicalrecords/DataTag",
        "extension": [
          {
            "url": "https://g.co/fhir/medicalrecords/DataTag",
            "valueCoding": {
              "system": "http://example.com/custom-tags",
              "code": "archived"
            }
          },
          {
            "url": "https://g.co/fhir/medicalrecords/DataTag",
            "valueCoding": {
              "system": "http://example.com/custom-tags",
              "code": "insensitive"
            }
          }
        ]
      },
      {
        "url": "https://g.co/fhir/medicalrecords/DataSource",
        "valueUri": "http://somesystem.example.org/foo"
      }
    ],
    "securityLabel": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-Confidentiality",
        "code": "R"
      },
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "PSY"
      }
    ]
  }
}

O exemplo anterior representa um recurso de consentimento da política de administrador que dá permissão a um f002 profissional com o objetivo de oferecer tratamento regular representado por TREAT. O profissional é da geolocalização iso3166-1/CA. Esse recurso de consentimento permite que o profissional acesse os dados do paciente se eles atenderem a todas as condições a seguir:

  • É um tipo de Encounter com o ID Encounter/e001.
  • Ele vem da origem http://somesystem.example.org/foo.
  • Ela atende a pelo menos uma das seguintes condições na tag:
    • Tem a tag (system = http://terminology.hl7.org/CodeSystem/common-tags e code = actionable)
    • Tem as duas tags (system = http://example.com/custom-tags e code = archived) e (system = http://example.com/custom-tags e code = insensitive)
  • Tem pelo menos um dos seguintes marcadores de segurança
    • system = http://terminology.hl7.org/CodeSystem/v3-Confidentiality e code é uma destas opções: R, N, M, L ou U.
    • system = http://terminology.hl7.org/CodeSystem/v3-ActCode e code = PSY

Exemplo de diretiva de política em cascata do administrador

{
  "resourceType": "Consent",
  "id": "admin-cascading-policy-example",
  "patient": {},
  "extension": [
    { "url": "https://g.co/fhir/medicalrecords/ConsentAdminPolicy" },
    { "url": "https://g.co/fhir/medicalrecords/CascadingPolicy" }
  ],
  "category": [
    {
      "coding": [
        {
          "system": "http://loinc.org",
          "code": "57017-6"
        }
      ]
    }
  ],
  "scope": {},
  "policyRule": {
    "coding": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "OPTIN"
      }
    ]
  },
  "status": "active",
  "provision": {
    "type": "permit",
    "actor": [
      {
        "reference": {
          "reference": "Practitioner/f002"
        },
        "role": {
          "coding": [
            {
              "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode",
              "code": "GRANTEE"
            }
          ]
        }
      }
    ],
    "purpose": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason",
        "code": "TREAT"
      }
    ],
    "class": [
      {
        "system": "http://hl7.org/fhir/resource-types",
        "code": "Patient"
      }
    ],
    "extension": [
      {
        "url": "https://g.co/fhir/medicalrecords/Environment",
        "valueCodeableConcept": {
          "coding": [
            {
              "system": "iso3166-1",
              "code": "CA"
            }
          ]
        }
      },
      {
        "url": "https://g.co/fhir/medicalrecords/DataTag",
        "valueCoding": {
          "system": "http://terminology.hl7.org/CodeSystem/common-tags",
          "code": "employee"
        }
      }
    ]
  }
}

O exemplo anterior representa um recurso de consentimento da política em cascata do administrador que concede permissão a um f002 profissional com o objetivo de fornecer tratamento regular representado por TREAT. O profissional é da geolocalização iso3166-1/CA. Esse recurso de consentimento permite que o profissional acesse os dados dos compartimentos de pacientes com a tag employee. Todos os critérios de recursos se aplicam apenas aos recursos base do compartimento, ou seja, o recurso "Paciente", que controla de quais recursos ocorrerão em cascata.

Aplicar o consentimento dos pacientes ou as políticas administrativas

Aplique os consentimentos dos pacientes até ApplyConsents

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json" \
    --data "{'validateOnly': false}" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"

Você receberá uma resposta JSON semelhante a esta:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

A resposta contém um nome de operação. Para rastrear o status da operação, use o método [Operation `get`](/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.operations/get):

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"

Quando a operação for concluída, o servidor retornará uma resposta com o status da operação no formato JSON:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1beta1.fhir.FhirStoreService.ApplyConsents",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/query/CLOUD_LOGGING_URL",
    "counter": {
      "success": "2",
      "secondarySuccess": "5"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.fhir.ApplyConsentsResponse",
    "consentApplySuccess": "2",
    "affectedResources": "5"
  }
}

Essa resposta indicou que o servidor processou com sucesso dois consentimentos e atualizou o acesso consensual de cinco recursos (1 paciente, dois consentimentos, duas observações).

Aplique a política do administrador até ApplyAdminConsents

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json" \
    --data "{
      'validateOnly': false,
      'newConsentsList': {
        'names': ['projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/5c8e3f8a-9fd5-480d-a08e-f29b89feccde/_history/VERSION_ID']
      }
    }" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyAdminConsents"

Você receberá uma resposta JSON semelhante a esta:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

A resposta contém um nome de operação. Para rastrear o status da operação, use o método [Operation `get`](/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.operations/get):

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"

Quando a operação for concluída, o servidor retornará uma resposta com o status da operação no formato JSON:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1beta1.fhir.FhirStoreService.ApplyAdminConsents",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/query/CLOUD_LOGGING_URL",
    "counter": {
      "success": "1",
      "secondarySuccess": "7"
    }
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.fhir.ApplyAdminConsentsResponse",
    "consentApplySuccess": "1",
    "affectedResources": "7"
  }
}

Essa resposta indicou que o servidor processou com êxito uma política administrativa e atualizou o acesso consensual de sete recursos (1 profissional, 1 paciente, 2 observações, 2 consentimentos de pacientes e 1 política administrativa).

A aplicação de consentimentos armazenados em um armazenamento FHIR não entra em vigor até que ApplyConsents (para consentimentos de pacientes) ou ApplyAdminConsents (para políticas de administrador e políticas em cascata do administrador) seja chamada e concluída com sucesso. Se você adicionar, modificar ou remover consentimentos depois de executar ApplyConsents ou ApplyAdminConsents, será necessário executá-los novamente para que eles sejam incluídos no modelo de aplicação.

Como os recursos FHIR são indexados de modo assíncrono, pode haver um pequeno atraso entre a conclusão de ApplyConsents ou ApplyAdminConsents e a exibição do modelo de aplicação nos resultados da pesquisa. Esse atraso é esperado apenas para solicitações de pesquisa.

Se esta é a primeira vez que você está configurando a aplicação de consentimento no armazenamento FHIR, aguarde a conclusão da operação de longa duração ApplyConsents ou ApplyAdminConsents antes de fazer solicitações de consentimento.

Para chamar ApplyConsents em um subconjunto de pacientes, use os seguintes filtros:

  • PatientScope: para executar ApplyConsents em uma lista de IDs de pacientes com até 10.000 pacientes.

  • TimeRange: para executar ApplyConsent em uma lista de IDs de recursos de pacientes com recursos de consentimento atualizados durante um determinado período.

Para chamar ApplyAdminConsents: você precisa fornecer a lista completa de todas as políticas que quer aplicar (não uma lista incremental). Como resultado, uma lista vazia anulará a aplicação de todas as políticas de administrador da loja. Cada política precisa ser um nome de versão de recurso se o armazenamento FHIR tiver controle de versão. Caso contrário, será um nome de recurso.

É possível usar operations.get para recuperar o ProgressCounter da operação. Após a conclusão, há um ApplyConsentsResponse que é incluído no Operation.response. Os contadores em ProgressCounter e ApplyConsentsResponse ou ApplyAdminConsentsResponse estão descritos na tabela a seguir.

ProgressCounter ApplyConsentsResponse ou ApplyAdminConsentsResponse Descrição
success consentApplySuccess O número de recursos de consentimento que a operação processou.
failure consentApplyFailure O número de recursos de consentimento incompatíveis ou inválidos. É possível acessar os registros de erros no Cloud Logging ou, quando validateOnly for false, verificar o status da aplicação do consentimento usando CheckConsentEnforcementStatus ou CheckPatientConsentEnforcementStatus para recuperar os detalhes do erro.
secondarySuccess affectedResources Quando validateOnly for false, ele representa o número de recursos FHIR que foram reindexados com sucesso devido ao efeito da alteração do consentimento.
secondaryFailure failedResources Quando validateOnly for false, ele representa o número de recursos FHIR que podem ter o consentimento alterado, mas não foram indexados novamente. Isso pode afetar a pesquisa com contexto de consentimento, mas não outros métodos. Para ver os detalhes do erro, consulte os registros de erros no Cloud Logging.

Quando os recursos de consentimento do FHIR são processados, é possível usar as seguintes APIs para verificar o status da aplicação de um único consentimento ou de todos os consentimentos de um paciente:

Para a política administrativa, CheckConsentEnforcementStatus só pode ser usado para verificar o status de aplicação de uma única política de administrador de consentimento. Como alternativa, você pode usar fhirStores.get para ver todas as políticas de administrador ativas aplicadas ao armazenamento.

O consent-enforcement-status pode ter qualquer um destes valores:

  • OFF: representa o status de aplicação padrão de um novo recurso de consentimento em que nunca foi processado.

  • ENFORCEABLE: o estado em que o recurso de consentimento foi processado.

  • INACTIVE: um estado inativo em que o recurso de consentimento é ignorado.

  • UNSUPPORTED: o estado de um recurso de consentimento que pode estar em conformidade com as especificações FHIR, mas não é executável. Isso se deve à implementação limitada da aplicação de consentimento do FHIR com o nível atual de suporte ao recurso.

  • ENFORCEMENT_LIMIT_EXCEEDED: o estado em que o formato do recurso de consentimento FHIR e o nível de suporte para o recurso estão livres de erros. No entanto, uma ou mais das condições a seguir são verdadeiras:

    • O paciente tem um grande conjunto de recursos de consentimento.

    • O tamanho das diretivas de consentimento em todos os consentimentos ativos é maior que o tamanho máximo permitido para que um servidor FHIR as aplique.

A API Cloud Healthcare é compatível com pesquisas de recursos FHIR em um determinado armazenamento FHIR com actor, purpose e environment como parâmetros de consulta. A resposta contém apenas os recursos que receberam consentimento.

  1. O profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) usando um aplicativo confiável App/123 pesquisa todas as observações com status=final.
  2. curl -X GET \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?status=final"
    

    Você receberá uma resposta JSON semelhante a esta:

    {
      "entry": [
        {
          "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION_ID/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa",
          "resource": {
            "code": {
              "coding": [
                {
                  "code": "718-7",
                  "display": "Hemoglobin [Mass/volume] in Blood",
                  "system": "http://loinc.org"
                }
              ]
            },
            "effectivePeriod": {
              "start": "2021-12-10T05:30:10+01:00"
            },
            "id": "7473784b-46a8-470c-b9a6-fe38a01025aa",
            "issued": "2021-12-10T13:30:10+01:00",
            "meta": {
              "lastUpdated": "2022-09-01T17:31:40.423469+00:00",
              "source": "http://example.com/HappyHospital",
              "versionId": "VERSION_ID"
            },
            "resourceType": "Observation",
            "status": "final",
            "subject": {
              "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"
            },
            "valueQuantity": {
              "code": "g/dL",
              "system": "http://unitsofmeasure.org",
              "unit": "g/dl",
              "value": 7.2
            }
          },
          "search": {
            "mode": "match"
          }
        }
      ],
      "link": [
        {
          "relation": "search",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final"
        },
        {
          "relation": "first",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final"
        },
        {
          "relation": "self",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final"
        }
      ],
      "resourceType": "Bundle",
      "total": 1,
      "type": "searchset"
    }
    
  3. O profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) usando o aplicativo App/123 pesquisa todas as observações da Patient Darcy.
  4. curl -X GET \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?subject:Patient.name=Darcy"
    

    Você receberá uma resposta JSON semelhante a esta:

    {
      "link": [
        {
          "relation": "search",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject%3APatient.name=Darcy"
        },
        {
          "relation": "first",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject%3APatient.name=Darcy"
        },
        {
          "relation": "self",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject%3APatient.name=Darcy"
        }
      ],
      "resourceType": "Bundle",
      "total": 0,
      "type": "searchset"
    }
    

    A consulta anterior é uma pesquisa em cadeia. Como o cenário de consentimento actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123 não tem acesso ao recurso Paient Darcy (identificado por Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2), o servidor FHIR não retorna nenhuma observação do paciente como se o paciente não existisse.

  5. O profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) usando o aplicativo App/123 pesquisa todas as observações da Patient Darcy para fins de tratamento de emergência.
  6. curl -X GET \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 purp/v3/ETREAT env/App/123" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?subject:Patient.name=Darcy"
    

    Você receberá uma resposta JSON semelhante a esta:

    {
      "entry": [
        {
          "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/68583624-9921-4158-8754-2a306c689abd",
          "resource": {
            "code": {
              "coding": [
                {
                  "code": "15074-8",
                  "display": "Glucose [Moles/volume] in Blood",
                  "system": "http://loinc.org"
                }
              ]
            },
            "effectivePeriod": {
              "start": "2021-12-01T05:30:10+01:00"
            },
            "id": "68583624-9921-4158-8754-2a306c689abd",
            "issued": "2021-12-01T13:30:10+01:00",
            "meta": {
              "lastUpdated": "2022-09-01T17:31:40.423469+00:00",
              "versionId": "VERSION_ID"
            },
            "resourceType": "Observation",
            "status": "final",
            "subject": {
              "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"
            },
            "valueQuantity": {
              "code": "mmol/L",
              "system": "http://unitsofmeasure.org",
              "unit": "mmol/l",
              "value": 6.3
            }
          },
          "search": {
            "mode": "match"
          }
        },
        {
          "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa",
          "resource": {
            "code": {
              "coding": [
                {
                  "code": "718-7",
                  "display": "Hemoglobin [Mass/volume] in Blood",
                  "system": "http://loinc.org"
                }
              ]
            },
            "effectivePeriod": {
              "start": "2021-12-10T05:30:10+01:00"
            },
            "id": "7473784b-46a8-470c-b9a6-fe38a01025aa",
            "issued": "2021-12-10T13:30:10+01:00",
            "meta": {
              "lastUpdated": "2022-09-01T17:31:40.423469+00:00",
              "source": "http://example.com/HappyHospital",
              "versionId": "VERSION_ID"
            },
            "resourceType": "Observation",
            "status": "final",
            "subject": {
              "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"
            },
            "valueQuantity": {
              "code": "g/dL",
              "system": "http://unitsofmeasure.org",
              "unit": "g/dl",
              "value": 7.2
            }
          },
          "search": {
            "mode": "match"
          }
        }
      ],
      "link": [
        {
          "relation": "search",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject:Patient.name=Darcy"
        },
        {
          "relation": "first",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject:Patient.name=Darcy"
        },
        {
          "relation": "self",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject:Patient.name=Darcy"
        }
      ],
      "resourceType": "Bundle",
      "total": 2,
      "type": "searchset"
    }
    
  7. O profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) pesquisa a seção "Observações" com status=final para dois objetivos: tratamento e pesquisa
  8. curl -X GET \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 purp/v3/TREAT purp/v3/HRESCH" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?status=final"
    

    Você receberá uma resposta JSON semelhante a esta:

    {
      "issue": [
        {
          "code": "security",
          "details": {
            "text": "permission_denied"
          },
          "diagnostics": "the maximum number of allowed consent purpose scopes is 1, got 2",
          "severity": "error"
        }
      ],
      "resourceType": "OperationOutcome"
    }
    

    Nesse caso, o profissional Jeffrey Brown precisa remover uma finalidade desnecessária de "X-Consent-Scope" na solicitação.

  9. Um administrador de TI do hospital usa o bypass para pesquisar todos os profissionais do hospital.
  10. curl -X GET \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "X-Consent-Scope: bypass actor/Admin/ef0592c9-6724-467e-878d-f879e537cd15 env/net/HappyNet" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner?"
    

    Como bypass foi fornecido, as verificações de consentimento foram ignoradas. Você vai receber uma resposta JSON semelhante a esta:

    {
      "entry": [
        {
          "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/12942879-f89f-41ae-aa80-0b911b649833",
          "resource": {
            "active": true,
            "birthDate": "1970-05-23",
            "gender": "male",
            "id": "12942879-f89f-41ae-aa80-0b911b649833",
            "meta": {
              "lastUpdated": "2022-09-01T17:31:40.423469+00:00",
              "versionId": "VERSION_ID"
            },
            "name": [
              {
                "family": "Brown",
                "given": [
                  "Jeffrey"
                ],
                "use": "official"
              }
            ],
            "resourceType": "Practitioner"
          },
          "search": {
            "mode": "match"
          }
        }
      ],
      "link": [
        {
          "relation": "search",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?"
        },
        {
          "relation": "first",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?"
        },
        {
          "relation": "self",
          "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?"
        }
      ],
      "resourceType": "Bundle",
      "total": 1,
      "type": "searchset"
    }
    

A API Cloud Healthcare é compatível com o recurso "get FHIR" em um determinado armazenamento FHIR com actor, purpose e environment como parâmetros de consulta. A resposta contém apenas os recursos que receberam consentimento.

  1. O profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) usando o aplicativo App/123 lê a medida de hemoglobina do paciente (neste exemplo, Observation/7473784b-46a8-470c-b9a6-fe38a01025aa).
  2. curl -X GET \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"
    

    Como o solicitante recebeu o consentimento, a resposta é o conteúdo do recurso "Observação".

    {
      "code": {
        "coding": [
          {
            "code": "718-7",
            "display": "Hemoglobin [Mass/volume] in Blood",
            "system": "http://loinc.org"
          }
        ]
      },
      "effectivePeriod": {
        "start": "2021-12-10T05:30:10+01:00"
      },
      "id": "7473784b-46a8-470c-b9a6-fe38a01025aa",
      "issued": "2021-12-10T13:30:10+01:00",
      "meta": {
        "lastUpdated": "2022-09-01T17:31:40.423469+00:00",
        "source": "http://example.com/HappyHospital",
        "versionId": "VERSION_ID"
      },
      "resourceType": "Observation",
      "status": "final",
      "subject": {
        "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"
      },
      "valueQuantity": {
        "code": "g/dL",
        "system": "http://unitsofmeasure.org",
        "unit": "g/dl",
        "value": 7.2
      }
    }
    
  3. O médico Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) com o aplicativo desconhecido App/unknown lê a medida de hemoglobina do paciente (neste exemplo, Observation/7473784b-46a8-470c-b9a6-fe38a01025aa).
  4. curl -X GET \
      -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
      -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/unknown" \
      "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"
    

    Como o limite de acesso do solicitante ("App/desconhecido") não é permitido pelo consentimento do paciente, a solicitação é negada.

    {
      "issue": [
        {
          "code": "security",
          "details": {
            "text": "permission_denied"
          },
          "diagnostics": "Consent access denied or the resource being accessed does not exist",
          "severity": "error"
        }
      ],
      "resourceType": "OperationOutcome"
    }
    
  5. O profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) fazendo pesquisas biomédicas usando o aplicativo App/golden lê a data de nascimento de Darcy (neste exemplo, Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2).
  6. curl -X GET \
      -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
      -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 purp/v3/BIORCH env/App/golden" \
      "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"
    

    Como o solicitante recebeu o consentimento, a resposta é o conteúdo do recurso Paciente.

    {
      "active": true,
      "birthDate": "1990-01-01",
      "gender": "female",
      "id": "3c6aa096-c054-4c22-b2b4-1e4a4d203de2",
      "meta": {
        "lastUpdated": "2022-09-01T17:31:40.423469+00:00",
        "versionId": "VERSION_ID",
        "tag": [{
          "system": "http://terminology.hl7.org/CodeSystem/common-tags",
          "code": "employee"
        }]
      },
      "name": [
        {
          "family": "Smith",
          "given": [
            "Darcy"
          ],
          "use": "official"
        }
      ],
      "resourceType": "Patient"
    }
    
  7. O médico Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) solicita acesso emergencial não autorizado ao histórico de um paciente usando o protocolo de emergência. Neste exemplo, Observation/7473784b-46a8-470c-b9a6-fe38a01025aa.
  8. curl -X GET \
      -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
      -H "X-Consent-Scope: btg actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833" \
      "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"
    

    Como o método de autorização de consentimento é btg, o servidor ignora as verificações de consentimento. A resposta é o conteúdo do recurso Observação.

    {
      "code": {
        "coding": [
          {
            "code": "718-7",
            "display": "Hemoglobin [Mass/volume] in Blood",
            "system": "http://loinc.org"
          }
        ]
      },
      "effectivePeriod": {
        "start": "2021-12-10T05:30:10+01:00"
      },
      "id": "7473784b-46a8-470c-b9a6-fe38a01025aa",
      "issued": "2021-12-10T13:30:10+01:00",
      "meta": {
        "lastUpdated": "2022-09-01T17:31:40.423469+00:00",
        "source": "http://example.com/HappyHospital",
        "versionId": "VERSION_ID"
      },
      "resourceType": "Observation",
      "status": "final",
      "subject": {
        "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"
      },
      "valueQuantity": {
        "code": "g/dL",
        "system": "http://unitsofmeasure.org",
        "unit": "g/dl",
        "value": 7.2
      }
    }
    

As seções a seguir descrevem os métodos de aplicação de consentimento compatíveis na API Cloud Healthcare e como o acesso aos recursos é aplicado quando você faz uma solicitação com reconhecimento de consentimento.

Ao fazer uma solicitação, o servidor de autorização é responsável por gerar tokens de acesso com o escopo de consentimento relevante.

Definir cabeçalho HTTP

Os escopos de consentimento são transmitidos para a API Cloud Healthcare usando o cabeçalho HTTP X-Consent-Scope. A API Cloud Healthcare usa esse cabeçalho para impor o controle de acesso baseado em consentimento nos dados em armazenamentos FHIR.

Uma solicitação FHIR é compatível com um número limitado de escopos de entrada de consentimento. É possível incluir até três entradas de actor, uma de purp e uma de env em uma determinada solicitação FHIR.

Para escopos especiais, uma solicitação FHIR é compatível com btg ou bypass.

Definir cabeçalhos HTTP para aplicativos confiáveis

Esta seção só é necessária se você estiver usando um servidor de autorização controlado pelo cliente. Nesse caso, você também precisa usar um SMARTproxy ou proxy semelhante.

Alguns aplicativos confiáveis podem fazer chamadas diretamente para a API Cloud Healthcare com os escopos de consentimento no cabeçalho HTTP especificado. Isso permite a aplicação direta de consentimento sem a necessidade de um SMARTproxy ou outro proxy para converter entre servidores de autorização externos e o Google Cloud.

Por exemplo, seu aplicativo pode ser registrado para um subconjunto de escopos, como um escopo environment de aplicativo, ou o aplicativo pode apresentar um widget de seleção para definir algumas entradas de escopo, como o purpose do acessador.

Um usuário ou aplicativo confiável também pode usar as entradas de escopo btg ou bypass, que estão sujeitas a avaliações pós-auditoria.

A API Cloud Healthcare oferece suporte integrado para a aplicação de consentimento FHIR com base nos escopos de consentimento de entrada. Os administradores de armazenamento FHIR são responsáveis por criar e configurar um servidor de autorização fora da API Cloud Healthcare que concede escopos de consentimento.

Exemplo de token de acesso

Veja na amostra a seguir um token de acesso codificado em base64:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJjb25zZW50LnRva2VuLm9yZyIsImlhdCI6MTYxMjg4NDA4NSwiZXhwIjoxNjQ0NDIwMDg1LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJkb2N0b3IuZ2FicmllbGFAZXhhbXBsZS5jb20iLCJzY29wZSI6Im9pZGMgYWN0b3IvUHJhY3RpdGlvbmVyLzEyMyBhY3Rvci9Hcm91cC85OTkgcHVycC92My9UUkVBVCBlbnYvQXBwL2FiYyJ9.fC7ljkVUUx8fwUOrJuONcrqA-WKC-k_Bclzlgds0Cq6H_gEe3nUjPlSOCTQsIdYB

Depois de decodificar o token de acesso, é possível ver que ele contém o seguinte payload:

{
  "iss": "consent.token.org",
  "iat": 1612884085,
  "exp": 1644420085,
  "aud": "www.example.com",
  "sub": "doctor.gabriela@example.com",
  "scope": "oidc actor/Practitioner/123 actor/Group/999 purp/v3/TREAT env/App/abc"
}

Configurar o SMARTProxy

O SMARTProxy é um proxy de código aberto do Google que oferece os seguintes recursos:

  • Permite que o servidor FHIR da API Cloud Healthcare aceite e valide tokens de acesso baseado no consentimento.

  • Permite que a implementação FHIR na API Cloud Healthcare inclua tokens de acesso baseado no consentimento como parte do modelo de permissões e gerenciamento da API Cloud Healthcare.

  • Também aceita recursos de token para SMART no suporte FHIR.

Quando você faz uma solicitação para recuperar dados da API Cloud Healthcare pelo SMARTProxy, ocorre o seguinte:

  1. O SMARTProxy aceita uma solicitação de um cliente que contém um token com reconhecimento de consentimento.

  2. O SMARTProxy valida o token com reconhecimento de consentimento por meio de um servidor de autorização JWT de sua propriedade.

  3. O SMARTProxy lê os escopos do token de reconhecimento de consentimento e os transmite para a API Cloud Healthcare pelo cabeçalho HTTP.

  4. A API Cloud Healthcare recebe os cabeçalhos e os valida para aplicar diretivas de consentimento na solicitação. A API Cloud Healthcare retorna uma resposta por meio do SMARTProxy para o cliente.

Configurar uma conta de serviço do Google Cloud

Um proxy pode ter apenas uma conta de serviço do Google Cloud. Se vários clientes usarem o mesmo proxy, a mesma conta de serviço será usada. Tenha cuidado ao compartilhar uma conta de serviço com vários clientes pelos seguintes motivos:

Por exemplo, se você chamar a API Cloud Healthcare diretamente usando a Conta do Google para autenticação, os Registros de auditoria do Cloud registrarão seu endereço de e-mail como o endereço de e-mail principal. Quando você usa um proxy para chamar a API Cloud Healthcare, o proxy usa a própria conta de serviço, e o endereço de e-mail principal é o endereço de e-mail da conta de serviço e a conta original não é definida.

Registros de auditoria

Os registros de auditoria são gerados quando há uma solicitação de acesso ou quando a aplicação de acesso dos recursos é alterada.

ao máximo.

Se os registros de auditoria estiverem ativados no armazenamento FHIR, um campo de metadados consentMode será incluído nos registros de auditoria disponíveis no Cloud Logging. O consentMode pode ter um destes valores:

  • off: a configuração do armazenamento FHIR tem consentConfig.accessEnforced definido como false e não permite solicitações no modo de consentimento.

  • emptyScope: o armazenamento FHIR tem consentConfig.accessEnforced definido como true, mas um cabeçalho de escopo de consentimento não foi incluído. Como resultado, os consentimentos não foram aplicados.

  • enforced: o armazenamento FHIR tem consentConfig.accessEnforced definido como true, e o cabeçalho do escopo de consentimento está presente. Como resultado, os consentimentos foram avaliados e aplicados na solicitação.

  • btg: a solicitação FHIR tinha btg fornecido no cabeçalho do escopo de consentimento. Por isso, as verificações de consentimento foram ignoradas. Essa solicitação é para ser usada em emergências e está sujeita apenas à revisão pós-auditoria.

  • bypass: a solicitação FHIR tinha apenas bypass fornecido no cabeçalho do escopo de consentimento. Por isso, as verificações de consentimento foram ignoradas. Essa solicitação deve ser usada por um fluxo de trabalho confiável, como um administrador ou um aplicativo confiável em vez de usuários finais, para que esse registro de auditoria seja diferente do btg, usado para verificações de governança de dados.

Opcionalmente, defina access_determination_log_config como VERBOSE para registrar mais informações sobre o motivo de uma solicitação ser concedida ou negada.

Registros de auditoria de alteração da aplicação de acesso

Quando o recurso base do compartimento muda (por exemplo, remover a tag employee de um paciente): o controle de acesso no recurso alterado e no compartimento dele pode mudar devido à política de cascata do administrador. Isso vai acionar a reindexação em todos os recursos do compartimento. O progresso da reindexação de cada atualização de recurso base do compartimento pode ser rastreado no Cloud Logging com o filtro jsonPayload.@type="type.googleapis.com/google.cloud.healthcare.logging.FhirConsentCascadeLogEntry".

Exemplo de registro de progresso da reindexação em cascata

{
  "insertId": "tz2gtza8",
  "jsonPayload": {
    "@type": "type.googleapis.com/google.cloud.healthcare.logging.FhirConsentCascadeLogEntry",
    "state": "STATE_FINISHED",
    "affectedResources": "2",
    "lastUpdated": "YYYY-MM-DDTHH:MM:SS+ZZ:ZZ",
    "compartmentBaseResourceName": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_RESOURCE_ID/_history/PATIENT_RESOURCE_VERSION"
  },
  "resource": {
    "type": "healthcare_fhir_store",
    "labels": {
      "location": "LOCATION",
      "dataset_id": "DATASET_ID",
      "fhir_store_id": "FHIR_STORE_ID",
      "project_id": "PROJECT_ID"
    }
  },
  "timestamp": "YYYY-MM-DDTHH:MM:SS+ZZ:ZZ",
  "severity": "INFO",
  "logName": "projects/PROJECT_ID/logs/healthcare.googleapis.com%2Fconsent_cascading_fhir",
  "receiveTimestamp": "YYYY-MM-DDTHH:MM:SS+ZZ:ZZ"
}

jsonPayload.state é o estado da operação de reindexação, jsonPayload.affectedResources é o número de recursos do compartimento reindexados, e jsonPayload.lastUpdated é o carimbo de data/hora da atualização do recurso do paciente. Se a operação acabou de ser iniciada, jsonPayload.state="STATE_STARTED" e jsonPayload.affectedResources não estarão presentes.

Limitações e limitações

Nesta seção, mostramos as restrições e os limites do FHIR R4, mas as mesmas restrições e limites se aplicam ao FHIR STU3.

Tipo Restrições e limites
Recurso de consentimento único
  • Só é possível usar um único Consent.provision. Várias provisões ou uma provisão aninhada não são aceitas.
  • No mínimo 1 Consent.provision.actor e no máximo 25:
    • Consent.provision.actor.role precisa ser http://terminology.hl7.org/CodeSystem/v3-RoleCode.
    • Consent.provision.actor.code precisa ser GRANTEE ou HPOWATT.
  • No máximo 1 Consent.provision.purpose:
    • Consent.provision.purpose.system precisa ser http://terminology.hl7.org/CodeSystem/v3-ActReason.
    • Consent.provision.purpose.code não está em branco e tem no máximo 13 caracteres.
  • No máximo 1 environment:
    • Consent.provision.extension.url precisa ser https://g.co/fhir/medicalrecords/Environment.
    • A combinação do sistema e do código deve ter menos de 15 caracteres.
  • Se estiver filtrando por tipo de recurso, Consent.provision.class.system precisará ser http://hl7.org/fhir/resource-types.
  • Se você filtrar por fonte de dados, Consent.provision.extension.url precisará ser https://g.co/fhir/medicalrecords/DataSource.
  • Ao filtrar por tag de dados, Consent.provision.extension.url precisa ser https://g.co/fhir/medicalrecords/DataTag.
    • A tag de dados pode ser uma extensão complexa, aninhada em um nível, para descrever uma política que associa recursos a todas as tags especificadas (interpretadas em conjunto).
    • No máximo, cinco tags aninhadas são compatíveis.
  • No máximo 100 valores para todos os atributos repetidos, a menos que haja uma descrição diferente nesta linha.
Modelo de aplicação
  • Cada paciente pode ter até 200 recursos de consentimento do active aplicados por vez.
  • Cada loja pode ter até 200 políticas de administrador do active aplicadas de uma vez.
  • Um formato compacto especial para o conjunto de todas as Diretivas de consentimento de todos os consentimentos ativos de um determinado paciente não pode exceder um limite de tamanho definido. Normalmente, há capacidade suficiente para codificar milhares de diretivas de consentimento, a menos que strings de recursos muito longas sejam abundantes. Exemplo:
    • Centenas de consentimentos em fontes de dados e tags de dados exclusivas, cada uma sendo muito longa consome muito espaço.
    • Um único paciente com 3.000 entradas exclusivas de identificador de recurso Consent.provision.data.reference em vários consentimentos ativos, cada um especificando um Consent.provision.actor exclusivo, usa um espaço de forma mais agressiva do que as disposições que não especificam nenhuma restrição de referência de dados ou contêm muitas das mesmas strings de referência do ator.
  • Cada recurso pode ter até mil diretivas de consentimento de todos os consentimentos aplicáveis.
X-Consent-Scope
  • Mínimo de uma e máximo de três entradas actor.
  • Máximo de uma entrada purp:
    • Cada entrada purp precisa estar no formato system/code (v3 é o sistema registrado para http://terminology.hl7.org/CodeSystem/v3-ActReason).
    • O código deve ter no máximo 13.
  • Máximo de uma entrada env:
    • Cada entrada env precisa estar no formato system/code.
    • A combinação do sistema e do código precisa ser inferior a 15.
  • btg requer no mínimo uma entrada actor.
  • bypass requer no mínimo uma entrada actor e uma entrada env.
Métodos aceitos
Desempenho
  • ApplyConsents e ApplyAdminConsents escalonam de maneira semelhante ou melhor do que ImportResources.
  • Sobre as solicitações com base no consentimento:
    • Nosso modelo de consentimento foi otimizado para garantir o desempenho da aplicação das operações CRUD, incluindo a pesquisa em escala em muitos recursos e muitos pacientes.
    • A leitura de recursos individuais pode ter um impacto marginal na latência da solicitação. No entanto, o desempenho da pesquisa varia de acordo com a consulta base e o número de escopos de consentimento que fazem com que mais critérios de acesso fiquem ativos durante a pesquisa.
    • Recomendamos executar seus próprios testes de desempenho em vários parâmetros de solicitação FHIR representativos para determinar as características de desempenho dos seus casos de uso com base nas características dos seus dados, como quantos recursos de um determinado tipo de recurso de pesquisa estão no armazenamento FHIR.
    • Nossa solução mantém a ingestão e as atualizações de todos os recursos, incluindo os de consentimento, leves para que a capacidade durante a ingestão e outras formas de tráfego de gravação prossigam com impacto mínimo.

Práticas recomendadas

As seções a seguir descrevem as práticas recomendadas ao usar o controle de acesso FHIR.

Práticas recomendadas gerais

  • Não import recursos FHIR e chame ApplyConsents ou ApplyAdminConsents em paralelo. Recomendamos que você primeiro importe os recursos FHIR e depois chame ApplyConsents ou ApplyAdminConsents. No entanto, se os recursos a serem importados não incluírem recursos "Paciência" ou "Consentimento", o modelo de aplicação não será afetado e o processamento de consentimentos ou políticas administrativas não é necessário.

  • Não crie pesquisas personalizadas e chame ApplyConsents em paralelo. Recomendamos que você as execute uma após a outra.

  • Se os fluxos de trabalho exigirem chamar vários ApplyConsents em PatientScope separados, eles poderão ser chamados em paralelo.

  • ApplyAdminConsents pode ser executado em paralelo com qualquer número de ApplyConsents, mas não com outro ApplyAdminConsents.

  • Ao configurar o proxy, restrinja a conta de serviço do IAM com permissões somente leitura para evitar gravar os dados de um paciente nos registros de outro.

  • Não use o proxy de consentimento ao criar ou atualizar registros.

  • Valide todas as solicitações de gravação para evitar a modificação inesperada de dados de pacientes diferentes.

  • Quando os consentimentos em cascata são aplicados, os recursos base compartimento precisam ser importados primeiro, seguidos pelos recursos compartimentos restantes. Como alternativa, todos os recursos do compartimento podem ser agrupados em um único pacote e ingeridos usando fhir.executeBundle.

Excluir recurso de paciente

Ao excluir um recurso de paciente, se você também quiser remover a aplicação de consentimento desse paciente (especialmente quando FhirStore.disableReferentialIntegrity for verdadeiro), recomendamos seguir esta ordem de operações:

  1. Exclua todos os recursos de consentimento do recurso Paciente.

  2. Chame ApplyConsents com o filtro PatientScope.

Para configurar o acesso de consentimento a uma loja, siga estas etapas:

  1. Use UpdateFhirStore para definir o ConsentConfig com o version da aplicação de consentimento como V1 e defina accessEnforced como true.

    curl -X PATCH \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "Content-Type: application/json" \
        --data "{
          'consentConfig': {
            'version': 'V1',
            'accessEnforced': true
          }
        }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID?update_mask=consentConfig"
    
  2. Processar o consentimento dos pacientes ou as políticas administrativas

    1. ApplyConsents para o consentimento do paciente
    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "Content-Type: application/json" \
        --data "{'validateOnly': false}" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"
    
    1. ApplyAdminConsents para políticas administrativas e políticas em cascata do administrador.
    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "Content-Type: application/json" \
        --data "{
          'newConsentsList': {
              'names': [
              'projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/RESOURCE_ID_1/_history/VERSION_ID_1',
              ...
              'projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/RESOURCE_ID_N/_history/VERSION_ID_N'
              ]
          },
          'validateOnly': false
        }" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyAdminConsents"
    

Frequência de execução de ApplyConsents ou ApplyAdminConsents

  • Quando o campo ConsentConfig não está definido: o campo ConsentConfig é desativado quando um armazenamento FHIR é criado pela primeira vez e quando o campo ConsentConfig é apagado. Quando o campo ConsentConfig não estiver definido, será necessário repetir a configuração do armazenamento para o acesso de consentimento antes de fazer solicitações no modo de consentimento para evitar a avaliação de políticas de aplicação de consentimento desatualizadas.

  • Quando o modelo de aplicação muda: quando um recurso de consentimento é criado, atualizado ou excluído, o modelo de aplicação muda. Nesses casos, é necessário chamar ApplyConsents ou ApplyAdminConsents para que as mudanças entrem em vigor.

    • Se você consegue acompanhar as alterações de pacientes com consentimento, recomendamos usar o filtro PatientScope para evitar o reprocessamento de todo o armazenamento. Esse filtro é útil para atualizar imediatamente a aplicação de um pequeno conjunto de pacientes.

    • Também é possível executar ApplyConsents periodicamente usando o filtro TimeRange. Esse filtro é útil quando a atualização imediata não é essencial. Por exemplo, a solicitação a seguir atualiza a aplicação das mudanças de consentimento entre UTC 0AM 2022-09-20 e UTC 0AM 2022-09-21.

      curl -X POST \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -H "Content-Type: application/json" \
        --data "{
           'validateOnly': false,
           'timeRange': {
             'start': '2022-09-20T00:00:00Z',
             'end': '2022-09-21T00:00:00Z',
           }
          }" \
        "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"
      

A seguir