Controlar o acesso aos recursos FHIR na API Cloud Healthcare

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

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

  1. Crie um armazenamento de FHIR se ainda não tiver um.

  2. Defina os seguintes parâmetros ConsentConfig do armazenamento de FHIR para ativar a aplicação do consentimento:

    • version: especifica qual versão da aplicação de consentimento está sendo usada para o armazenamento de 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 recursos FHIR, os cabeçalhos de consentimento fornecidos serão verificados em relação às diretivas de consentimento dadas pelos consumidores.

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

Configurar um novo armazenamento 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/v1/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á tiver uma loja, use UpdateFhirStore para definir o ConsentConfig com a aplicação do consentimento version 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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID?update_mask=consentConfig"

As políticas são representadas pelo recurso Consentimento. A finalidade e o uso dos campos de recursos são descritos na documentação do modelo de dados.

Confira 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 seguintes recursos:

  • Um recurso Practitioner com o nome Jeffrey Brown
  • Um recurso de paciente com o nome Darcy Smith
  • Um recurso de observação que mostra a medição de hemoglobina de Darcy (LOINC718-7) coletada pelo Happy Hospital.
  • Um recurso de observação mostrando a medição de glicose de Darcy (LOINC15074-8).
  • Um consentimento de Darcy para permitir que Jeffrey Brown use o aplicativo App/123 para acessar os dados dela coletados pelo Happy Hospital
  • Um consentimento de Darcy para permitir que Jeffrey Brown acesse qualquer um dos dados dela para tratamento de emergência (ETREAT)
  • Um consentimento 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/v1/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/v1/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/v1/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/v1/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/v1/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/v1/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/v1/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/v1/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"
}

Confira mais exemplos do recurso de consentimento do 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 paciente f001 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 de saúde acesse os dados do paciente se eles atenderem todas as condições a seguir.

  • É um tipo Encounter com o ID Encounter/e001.
  • Ela vem da fonte http://somesystem.example.org/foo.
  • Ela atende a pelo menos uma das seguintes condições na tag (os recursos podem ser marcados definindo os campos system e code de 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)
  • Ele tem pelo menos um dos seguintes rótulos de segurança:
    • system = http://terminology.hl7.org/CodeSystem/v3-Confidentiality e code é um dos R, N, M, L, U.
    • system = http://terminology.hl7.org/CodeSystem/v3-ActCode e code = PSY.

Exemplo de diretiva de política de 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 uma política de administrador. O recurso "Consentimento" 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 de saúde acesse os dados do paciente se eles atenderem todas as seguintes condições:

  • É um tipo Encounter com o ID Encounter/e001.
  • Ela vem da fonte 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)
  • Ele tem pelo menos um dos seguintes rótulos de segurança:
    • system = http://terminology.hl7.org/CodeSystem/v3-Confidentiality e code é um dos R, N, M, L, U.
    • system = http://terminology.hl7.org/CodeSystem/v3-ActCode e code = PSY.

Exemplo de diretiva de política de cascata de 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 de política em cascata de administrador que concede 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 de saúde acesse os dados do compartimento de pacientes com a tag employee. Todos os critérios de recursos se aplicam apenas aos recursos básicos do compartimento, ou seja, o recurso "Paciente", já que ele controla quais recursos serão transmitidos.

Aplicar consentimentos de pacientes ou políticas de administrador

Aplicar os consentimentos do paciente usando 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/v1/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 `get` da operação](/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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"

Quando a operação for concluída, o servidor vai 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.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.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.v1.fhir.ApplyConsentsResponse",
    "consentApplySuccess": "2",
    "affectedResources": "5"
  }
}

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

Aplique a política de administrador 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/v1/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 `get` da operação](/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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"

Quando a operação for concluída, o servidor vai 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.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.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.v1.fhir.ApplyAdminConsentsResponse",
    "consentApplySuccess": "1",
    "affectedResources": "7"
  }
}

Essa resposta indica que o servidor processou uma política de administrador e atualizou o acesso consensual de sete recursos (um profissional de saúde, um paciente, duas observações, dois consentimentos de pacientes e uma política de administrador).

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

Os recursos do FHIR são indexados de forma assíncrona. Portanto, pode haver um pequeno atraso entre o momento em que ApplyConsents ou ApplyAdminConsents é concluído e quando o modelo de aplicação é refletido nos resultados da pesquisa. Esse atraso é esperado apenas para solicitações de pesquisa.

Se esta for a primeira vez que você configura a aplicação de consentimento na loja FHIR, aguarde a conclusão da operação de longa duração ApplyConsents ou ApplyAdminConsents antes de fazer solicitações com reconhecimento 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 cujos recursos de consentimento são atualizados durante um determinado período

Para chamar ApplyAdminConsents, forneça a lista completa de todas as políticas que você quer aplicar (não uma lista incremental). Como resultado, uma lista vazia vai 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 de FHIR estiver usando controle de versões, e um nome de recurso caso contrário.

Use operations.get para recuperar o ProgressCounter da operação. Ao concluir, há uma ApplyConsentsResponse incluída no Operation.response. Os contadores em ProgressCounter e ApplyConsentsResponse ou ApplyAdminConsentsResponse sã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 com sucesso.
failure consentApplyFailure O número de recursos de consentimento sem suporte ou inválidos. Você pode ver 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 detalhes do erro.
secondarySuccess affectedResources Quando validateOnly é false, ele representa o número de recursos FHIR que foram reindexados com sucesso devido ao efeito da mudança de consentimento.
secondaryFailure failedResources Quando validateOnly é false, ele representa o número de recursos do FHIR que podem ter uma mudança de consentimento, mas não foram reindexados. Isso pode afetar a pesquisa com contexto de consentimento, mas não outros métodos. Para conferir os detalhes do erro, veja os registros de erros no Cloud Logging.

Quando os recursos de consentimento do FHIR são processados, você pode 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 de administrador, CheckConsentEnforcementStatus só pode ser usado para verificar o status de aplicação de uma única política de administrador de consentimento. Como alternativa, use fhirStores.get para ver todas as políticas de administrador ativas aplicadas à loja.

O consent-enforcement-status pode ter qualquer um dos seguintes valores:

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

  • ENFORCEABLE: o estado em que o recurso "Consentimento" foi processado com sucesso.

  • INACTIVE: um estado inativo em que o recurso "Consentimento" é ignorado.

  • UNSUPPORTED: o estado de um recurso de consentimento que pode estar em conformidade com as especificações do FHIR, mas não pode ser aplicado. Isso ocorre devido à implementação limitada da aplicação de consentimento do FHIR com o nível atual de suporte a recursos.

  • ENFORCEMENT_LIMIT_EXCEEDED: o estado em que o formato do recurso de consentimento do FHIR e o nível de suporte para o recurso estão sem erros, mas uma ou mais das seguintes condições 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 foram consentidos.

  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/v1/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/v1/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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final"
        },
        {
          "relation": "first",
          "url": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final"
        },
        {
          "relation": "self",
          "url": "https://healthcare.googleapis.com/v1/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 do paciente 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/v1/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/v1/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/v1/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/v1/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 encadeada. Como o cenário de consentimento actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123 tem o acesso negado ao recurso Patient Darcy (identificado por Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2), o servidor FHIR não retorna nenhuma observação do paciente, como se ele 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 do paciente 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/v1/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/v1/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/v1/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/v1/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/v1/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/v1/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 observações com status=final para dois fins: 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/v1/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 do `X-Consent-Scope` na solicitação.

  9. Um administrador de TI de um hospital usa o bypass para pesquisar todos os profissionais da área médica 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/v1/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/v1/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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?"
        },
        {
          "relation": "first",
          "url": "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?"
        },
        {
          "relation": "self",
          "url": "https://healthcare.googleapis.com/v1/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 a obtenção 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 foram consentidos.

  1. O profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) usando o aplicativo App/123 lê a medição 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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"

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

    {
      "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 profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) usando o aplicativo desconhecido App/unknown lê a medição 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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"

    Como o acesso ao limite do solicitante (`App/unknown`) 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) faz uma pesquisa biomédica usando o aplicativo App/golden e 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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"

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

    {
      "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 profissional Jeffrey Brown (identificado por Practitioner/12942879-f89f-41ae-aa80-0b911b649833) solicita acesso de emergência não autorizado ao prontuário de um paciente usando o protocolo "break-the-glass". 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/v1/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 do consentimento é btg, o servidor ignora as verificações de consentimento. A resposta é o conteúdo do recurso "Observation".

    {
      "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 com a API Cloud Healthcare e como o acesso a recursos é aplicado quando você faz uma solicitação com reconhecimento de consentimento.

Ao fazer uma solicitação, seu 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 com base no consentimento aos dados em armazenamentos FHIR.

Uma solicitação FHIR pode oferecer suporte a 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 pode oferecer suporte a um dos seguintes: btg ou bypass.

Definir cabeçalhos HTTP para aplicativos confiáveis

Esta seção só será necessária se você estiver usando um servidor de autorização controlado pelo cliente. Nesse caso, também é necessário usar um SMARTproxy ou um 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 do consentimento sem a necessidade de um SMARTproxy ou outro proxy para converter entre servidores de autorização externos e Google Cloud.

Por exemplo, seu aplicativo pode estar registrado em um subconjunto de escopos, como um escopo environment do aplicativo, ou 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 revisões pós-auditoria.

A API Cloud Healthcare oferece suporte integrado para aplicação de consentimento do FHIR com base nos escopos de consentimento de entrada. Os administradores do armazenamento FHIR são responsáveis por criar e configurar um servidor de autorização fora da API Cloud Healthcare que conceda 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, você 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 com reconhecimento de consentimento.

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

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

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

  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 um servidor de autorização JWT de sua propriedade.

  3. O SMARTProxy lê os escopos do token com 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 à solicitação. A API Cloud Healthcare retorna uma resposta por meio do SMARTProxy para o cliente.

Configurar uma conta de serviço Google Cloud

Um proxy pode ter apenas uma Google Cloud conta de serviço. Se vários clientes usarem o mesmo proxy, eles usarão a mesma conta de serviço. 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 sua Conta do Google para autenticação, os registros de auditoria do Cloud vão registrar seu endereço de e-mail como o 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. 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 do acesso aos recursos muda.

ao máximo.

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

  • off: a configuração do repositório FHIR tem consentConfig.accessEnforced definido como false e não permite solicitações com reconhecimento 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 estava presente. Como resultado, os consentimentos foram avaliados e aplicados na solicitação.

  • btg: a solicitação FHIR tinha btg fornecido no cabeçalho de escopo de consentimento. Como resultado, as verificações de consentimento foram ignoradas. Essa solicitação é destinada a emergências e está sujeita apenas a revisão pós-auditoria.

  • bypass: a solicitação FHIR tinha apenas bypass fornecido no cabeçalho de 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, que é usado para verificações de governança de dados.

Opcionalmente, defina access_determination_log_config como VERBOSE para registrar mais informações sobre por que uma solicitação é concedida ou negada.

Acessar registros de auditoria de mudanças na aplicação de acesso

Quando o recurso base do compartimento muda (por exemplo, removendo uma 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 de compartimento reindexados e jsonPayload.lastUpdated é o carimbo de data/hora da atualização do recurso de paciente. Se a operação acabou de começar, jsonPayload.state="STATE_STARTED" e jsonPayload.affectedResources não estarão presentes.

Restrições e limitações

Esta seção mostra 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
  • Apenas um único Consent.provision é aceito. Provisionamentos múltiplos ou aninhados não são aceitos.
  • Pelo menos 1 Consent.provision.actor, 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á vazio e tem no máximo 13 caracteres.
  • No máximo 1 environment:
    • Consent.provision.extension.url precisa ser https://g.co/fhir/medicalrecords/Environment.
    • O comprimento combinado do sistema e do código precisa ser inferior a 15 caracteres.
  • Se você estiver filtrando por tipo de recurso, Consent.provision.class.system precisa ser http://hl7.org/fhir/resource-types.
  • Se você estiver filtrando por fonte de dados, Consent.provision.extension.url precisa ser https://g.co/fhir/medicalrecords/DataSource.
  • Se você estiver filtrando 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 até um nível, para descrever uma política que corresponde a recursos com todas as tags especificadas (interpretadas conjuntamente).
    • No máximo, cinco tags aninhadas são aceitas.
  • No máximo 100 valores para todos os atributos repetidos, a menos que descrito de outra forma nesta linha.
Modelo de restrição
  • Cada paciente pode ter até 200 recursos de consentimento active aplicados por vez.
  • Cada loja pode ter até 200 políticas de administrador active aplicadas por vez.
  • Um formato compacto especial para o conjunto de todas as diretivas de consentimento em 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 particularmente abundantes. Exemplo:
    • Centenas de consentimentos em uma fonte de dados e tags de dados exclusivas, cada uma muito longa, consomem muito espaço.
    • Um único paciente com 3.000 entradas de identificador de recurso Consent.provision.data.reference exclusivas em vários consentimentos ativos, cada um especificando um Consent.provision.actor exclusivo, usa o espaço de maneira mais agressiva do que provisionamentos que não especificam nenhuma restrição de referência de dados ou contêm muitas das mesmas strings de referência de ator.
  • Cada recurso pode ter até 1.000 diretivas de consentimento de todos os consentimentos aplicáveis a ele.
X-Consent-Scope
  • Mínimo de uma e máximo de três entradas de 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 comprimento do código precisa ser menor que 13.
  • Máximo de uma entrada env:
    • Cada entrada env precisa estar no formato system/code.
    • O comprimento do sistema e do código combinados precisa ser menor que 15.
  • btg exige pelo menos uma entrada actor.
  • bypass exige pelo menos uma entrada actor e uma entrada env.
Métodos aceitos
Desempenho
  • ApplyConsents e ApplyAdminConsents escalonam de maneira semelhante ou melhor que ImportResources.
  • Sobre solicitações com reconhecimento de consentimento:
    • Nosso modelo de consentimento foi otimizado para o desempenho da aplicação de operações CRUD, incluindo pesquisa em grande escala em vários recursos e pacientes.
    • A leitura de recursos individuais pode ter um impacto marginal na latência da solicitação, mas o desempenho da pesquisa varia de acordo com a consulta básica e o número de escopos de consentimento que levam a mais critérios de acesso ativos durante uma pesquisa.
    • Recomendamos que você execute seus próprios testes de desempenho em vários parâmetros de solicitação do 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 do FHIR.
    • Nossa solução mantém a ingestão e as atualizações de todos os recursos, incluindo os de consentimento, de forma leve para que a taxa de transferência durante a ingestão e outras formas de tráfego de gravação possam prosseguir com impacto mínimo.

Práticas recomendadas

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

Práticas recomendadas gerais

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

  • Não crie pesquisas personalizadas e chame ApplyConsents em paralelo. Recomendamos que você faça uma de cada vez.

  • Se os fluxos de trabalho exigirem a chamada de vários ApplyConsents em PatientScope desconexos, 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 modificações inesperadas de dados entre pacientes.

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

Excluir recurso de paciente

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

  1. Exclua todos os recursos de consentimento pertencentes ao recurso de paciente.

  2. Chame ApplyConsents com o filtro PatientScope.

Para configurar um repositório atual para acesso de consentimento, siga estas etapas:

  1. Use UpdateFhirStore para definir o ConsentConfig com a aplicação do consentimento version 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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID?update_mask=consentConfig"
  2. Processar consentimentos de pacientes ou políticas de administradores

    1. ApplyConsents para consentimentos de pacientes
    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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"
    1. ApplyAdminConsents para políticas de administrador e políticas de administrador em cascata.
    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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyAdminConsents"

Com que frequência executar ApplyConsents ou ApplyAdminConsents

  • Quando o campo ConsentConfig não está definido: o campo ConsentConfig não está definido quando um armazenamento FHIR é criado e quando o campo ConsentConfig é limpo. Depois que o campo ConsentConfig for desmarcado, repita o processo de configuração da loja para acesso de consentimento antes de fazer solicitações com reconhecimento 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, chame ApplyConsents ou ApplyAdminConsents para que as mudanças entrem em vigor.

    • Se você conseguir acompanhar as mudanças em "Pacientes com consentimento", recomendamos usar o filtro PatientScope para evitar o reprocessamento de toda a loja. 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 de mudanças de consentimento entre 0h UTC de 20/09/2022 e 0h UTC de 21/09/2022.

      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/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"

O leitor de consentimento do FHIR mostra políticas de controle de acesso. Ela fornece uma tabela com escopos de consentimento para representar regras de controle de acesso do FHIR.

Antes de usar o visualizador de consentimento do FHIR, verifique se:

Para acessar o visualizador de consentimento do FHIR, siga estas etapas:

A seguir