Compartir a través de


Proporcionar etiquetas de confidencialidad a Recall mediante UserActivityContentInfo

Windows Recall evalúa los metadatos JSON proporcionados a través de UserActivity.ContentInfo para decidir si capturar una ventana y cómo clasificar instantáneas bajo las directivas empresariales de prevención de pérdida de datos (DLP). Al proporcionar etiquetas de confidencialidad (cuando se conoce), Recall puede consultar al proveedor DLP para obtener decisiones de cumplimiento (por ejemplo, captura de bloques) y mostrar los metadatos adecuados para los usuarios.

Cuándo enviar metadatos

Enviar o actualizar un UserActivity cuando:

  • Cambios en el documento o elemento activo
  • Se agrega, quita o cambia una etiqueta de confidencialidad.
  • Transiciones de estados de indeterminado a conocido
  • La aplicación se inicia (para establecer un punto de referencia)

Modelo de sensibilidad

La aplicación puede notificar contenido en uno de los tres estados:

  1. Confidencial: incluir el informationProtection objeto con una labels matriz
  2. No confidencial: omita el informationProtection objeto por completo.
  3. Sin determinar: Incluir informationProtection.state = "undetermined" (Recall bloquea la captura hasta que se resuelve el estado)

La ausencia del informationProtection objeto significa que el contenido no es confidencial.

Estructura JSON

Campos de nivel superior recomendados:

  • @context: https://schema.org
  • @type: por ejemplo, "DocumentObject", "Event", "Article"
  • identifier: identificador único estable

Patrón de objeto de protección de la información (solo para datos confidenciales o no predeterminados) (json ilustrativo, no literal):

"informationProtection": {
  "@type": "SensitivityLabel",
  "state": "<state>",              // "sensitive" or "undetermined"
  "labels": [                       // include only when state == "sensitive"
    {
      "labelID": "<label GUID>",
      "organizationID": "<tenant GUID>"
    }
  ]
}

Reglas:

  • Reemplace por <state>sensitive o undetermined.
  • Incluya la labels matriz solo cuando el estado sea sensitive.
  • @type dentro del objeto es siempre SensitivityLabel.
  • Se permiten varias etiquetas; Recall aplica el valor más restrictivo devuelto por el proveedor DLP.

Ejemplos mínimos

Sensible (única):

{
  "@context": "https://schema.org",
  "@type": "DocumentObject",
  "identifier": "doc-123",
  "informationProtection": {
    "@type": "SensitivityLabel",
    "state": "sensitive",
    "labels": [
      {
        "labelID": "F96E0B19-8C3A-4D5A-8B9A-2E8CFC43247B",
        "organizationID": "D3FE4C20-9C77-45AB-A8E7-9870D3C9C856"
      }
    ]
  }
}

No confidencial

{
  "@context": "https://schema.org",
  "@type": "DocumentObject",
  "identifier": "doc-123"
}

Indeterminada

{
  "@context": "https://schema.org",
  "@type": "DocumentObject",
  "identifier": "doc-123",
  "informationProtection": {
    "@type": "SensitivityLabel",
    "state": "undetermined"
  }
}

Ejemplo de varias etiquetas

"informationProtection": {
  "@type": "SensitivityLabel",
  "state": "sensitive",
  "labels": [
    {
      "labelID": "F96E0B19-8C3A-4D5A-8B9A-2E8CFC43247B",
      "organizationID": "D3FE4C20-9C77-45AB-A8E7-9870D3C9C856"
    },
    {
      "labelID": "9A724CF8-E7D2-4B1C-8F4A-1D2E7B3A6C8D",
      "organizationID": "7C56AB24-9E32-44FA-B7D8-1E9F43C7A92B"
    }
  ]
}

Uso de API (C#)

Método auxiliar

El siguiente método auxiliar muestra cómo actualizar ContentInfo con etiquetas de sensibilidad:

private async Task UpdateContentInfoAsync(
    string contentId,
    string state, // "sensitive" | "undetermined" | "none"
    IEnumerable<(string LabelId, string OrgId)>? labels = null)
{
    var channel = UserActivityChannel.GetDefault();
    var activity = await channel.GetOrCreateUserActivityAsync(contentId);
    activity.ActivationUri = new Uri($"my-app://content/{contentId}");

    string json;
    if (state == "sensitive" && labels != null)
    {
        var labelItems = string.Join(",",
            labels.Select(l => $@"{{ \"labelID\": \"{l.LabelId}\", \"organizationID\": \"{l.OrgId}\" }}"));
        json = $@"{{
  \"@context\": \"https://schema.org\",
  \"@type\": \"DocumentObject\",
  \"identifier\": \"{contentId}\",
  \"informationProtection\": {{
    \"@type\": \"SensitivityLabel\",
    \"state\": \"sensitive\",
    \"labels\": [ {labelItems} ]
  }}
}}";
    }
    else if (state == "undetermined")
    {
        json = $@"{{
  \"@context\": \"https://schema.org\",
  \"@type\": \"DocumentObject\",
  \"identifier\": \"{contentId}\",
  \"informationProtection\": {{
    \"@type\": \"SensitivityLabel\",
    \"state\": \"undetermined\"
  }}
}}";
    }
    else
    {
        json = $@"{{
  \"@context\": \"https://schema.org\",
  \"@type\": \"DocumentObject\",
  \"identifier\": \"{contentId}\"
}}";
    }

    activity.ContentInfo = UserActivityContentInfo.FromJson(json);
    await activity.SaveAsync();
}

Controlador de arrastre

El siguiente manejador de extracción muestra cómo responder a solicitudes bajo demanda UserActivity :

private async void UserActivityRequested(
    UserActivityRequestManager sender,
    UserActivityRequestedEventArgs args)
{
    var deferral = args.GetDeferral();
    try
    {
        string id = GetCurrentContentId();
        var (state, labels) = GetCurrentSensitivity(); // app logic
        var channel = UserActivityChannel.GetDefault();
        var activity = await channel.GetOrCreateUserActivityAsync(id);
        activity.ActivationUri = new Uri($"my-app://content/{id}");
        string json = BuildContentInfoJson(id, state, labels);
        activity.ContentInfo = UserActivityContentInfo.FromJson(json);
        args.Request.SetUserActivity(activity);
    }
    finally
    {
        deferral.Complete();
    }
}

Empujar frente a jalar

Adoptar un enfoque híbrido:

  • La extracción inicial establece el punto de referencia
  • Aplicar actualizaciones inmediatamente tras los cambios

Ventajas: baja latencia, evita etiquetas obsoletas, reduce la sobrecarga de sondeo, admite una captura rápida a petición.