This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Discover

About Protegrity’s Discover.

Discover is Protegrity’s enterprise data intelligence layer. It comprises of two integrated services, Traverse and Classify.

Traverse maintains an updated catalog of an organization’s entire data estate. It continuously scans and indexes datastores, object stores, knowledge graphs, and identity directories (IDP/AD). It in turn maps every data source, schema, principal, and access path across the organization. This service directly supports the Sources views in the front-end of the application.

Classify runs across everything Traverse catalogs and can be used independently in User defined pipelines. It detects and classifies sensitive data, such as, PII, PHI, financial data, credentials, custom types at the field, file, and content level, including unstructured documents and live AI workflow content.

Together, Discover builds and maintains the foundational intelligence that powers the rest of the Protegrity platform.

1 - Architecture

General Architecture.

The following diagram illustrates the various components of the Discover architecture and how they work together.

Discover Architecture

The following are the important components in Discover:

  • Web UI: A unified user interface that hosts all product components, including Discover, and gives users one place to access and navigate the products they are licensed to use.

  • Traverse UI: The Discover interface in the Shell, where users manage scans, review the catalog, configure connections to their systems, and monitor results.

  • Catalog: The central repository for results, containing a map of the customer’s data such as databases, tables, and files along with the sensitive-data classifications identified during scans.

  • Worker Mapper: A component in the Traverse architecture that maps data from one format to another.

  • Worker Detector: A component in the Traverse architecture that detects sensitive data and sends the results to the Classification service.

  • Regex Dictionary Provider (RDP): A classification provider built by the DDX team that adds regex and dictionary-based detection to Discover. Ships as a separate Helm chart.

  • Classification Service (CS): The primary Classify entry point for text-based content, including plain text, tabular data, XML, and JSON. It analyzes content and returns any sensitive data it detects, with its capabilities extended by the providers listed here.

  • File Classification Service (FCS): The Classify entry point for files. It accepts files of various formats and returns the classifications of their contents by using the Classification Service.

  • Pattern Provider and Context Provider: The two built-in classification providers. They analyze the content and return a detailed list of the sensitive data found based on data patterns and surrounding context.

  • Customer Environment: The customer’s own environment, containing the databases, files, and identity providers (principals) that need to be scanned for sensitive data.

2 - Install

Instructions for installing Classify and Traverse.

Instructions for installing Classify and Traverse are provided here.

2.1 - Prerequisites

Following are the prerequisites for using Discover.
  • Platform and Access

    • PPC cluster version 1.2 or later.
    • Kubernetes access to the target cluster.
    • kubectl configured for the target cluster context.
    • Cluster permissions for the connected user .
    • Helm 3.x with OCI support enabled.
  • Container Registry Access

    • Ensure access and valid authentication to the container registry hosting the Classify and Traverse Helm charts.
    • For PCR, obtain valid registry credentials through your My.Protegrity account before installation. For more information about creating an account, refer to the documentation Obtaining Credentials.
    • For PCR or a private registry, ensure that the registry URL, username, and password/access token are available.
    • Log in to the container registry before proceeding with the installation:
      helm registry login <registry-url> \
        --username <username> \
        --password <password/token>
      
  • Registry Authentication

    • Access to the registry that hosts Classify and Traverse Helm charts. Ensure that the required authentication to the container registry path is available.
    • For Protegrity Container Registry (PCR), use helm registry login with credentials from My.Protegrity account creation.
  • Cluster Dependencies

    • Karpenter operator available in the cluster that is provided by PPC.
  • Required Inputs

    • Container registry path for Discover that includes Classify and Traverse installation: registry.protegrity.com:9443 for PCR, or a local registry endpoint.

2.2 - Installing Discover

Steps to install Classify and Traverse.

Installing Classify

Classify can be installed as a standalone service or as a service on Traverse.

Run the following command to install Classify as a standalone service.

helm upgrade --install data-discovery \
  oci://<Container_Registry_Path>/data-discovery/classification/helm/data-discovery \
  --version 2.2.0-487.gd29bc9f8 \
  -n data-discovery --create-namespace \
  --reset-then-reuse-values

Run the following command to install Classify as a service on Traverse.

helm upgrade --install data-discovery \
  oci://<Container_Registry_Path>/data-discovery/classification/helm/data-discovery \
  --version 2.2.0-487.gd29bc9f8 \
  -n data-discovery --create-namespace \
  --reset-then-reuse-values \
  --set 'classificationAppConfig.providers[0].name=Pattern' \
  --set 'classificationAppConfig.providers[0].address=http://pattern-provider-service:8051' \
  --set 'classificationAppConfig.providers[1].name=Context' \
  --set 'classificationAppConfig.providers[1].address=http://context-provider-service:8052' \
  --set 'classificationAppConfig.providers[2].name=RegexDictionary' \
  --set 'classificationAppConfig.providers[2].address=http://regex-provider:8053'

Note: The parameter --reset-then-reuse-values ensures that the release uses the existing values except for the ones explicitly overridden. For more information on the parameter, refer to the Helm documentation here.

Verifying the Installation

After installing Classify, run the following command to verify the installation:

kubectl get pods -n data-discovery

The status of all the pods must be Running.

Note: On AWS, the CPU node image is selected automatically from the cluster’s region. Secure nodes, such FIPS nodes, are used in the US, Canada, and GovCloud. Outside the US, Canada, and GovCloud, AWS nodes no longer run secure host cryptography. No region-specific configuration is required.

Installing Traverse

Traverse can be installed using the following steps.

Installation Steps

  1. Run this command to install the Regex Dictionary provider.

    helm upgrade --install regex-provider \
      oci://<Container_Registry_Path>/discover/traverse/helm/regex-provider \
      --version 1.4.0-275.ged3100bb \
      -n data-discovery --create-namespace \
      --reset-then-reuse-values
    
  2. Traverse includes the Kubernetes Event-driven Autoscaling (KEDA) operator. Helm installs its custom resource definitions (CRDs) only on a first install. Apply them before every install or upgrade.

    helm show crds oci://<Container_Registry_Path>/discover/traverse/helm/discoverx-scanner \
      --version 1.4.0-3871.ga855eeb9 \
      | kubectl apply --server-side --force-conflicts -f -
    

    Note: If the cluster already has KEDA installed, skip this step. Install Traverse with --set keda.enabled=false.

  3. Install or upgrade Traverse using the following command:

    helm upgrade --install discoverx \
      oci://<Container_Registry_Path>/discover/traverse/helm/discoverx-scanner \
      --version 1.4.0-3871.ga855eeb9 \
      -n discoverx --create-namespace \
      --reset-then-reuse-values \
      --set scannerAppConfig.classificationServiceUrl="http://classification-service.data-discovery:8050" \
      --set scannerAppConfig.fileClassificationServiceUrl="http://file-classification-service.data-discovery:8053" \
      --set keda.global.image.registry=<Container_Registry_Path> \
      --set keda.imagePullSecrets[0].name=harbor-secret
    

Verifying the Installation

Verify the installation using the following steps.

  1. Run the following command to verify whether the status of all the pods are Running.

    kubectl get pods -n data-discovery
    kubectl get pods -n discoverx
    

    The expected output must return the following snippet.

    kubectl get pods -n data-discovery
    NAME                                             READY   STATUS    RESTARTS   AGE
    classification-deployment-76bb665c59-9w7tk       1/1     Running   0          13h
    context-provider-deployment-ddcb99fd4-ndvmm      1/1     Running   0          27h
    data-discovery-nvidia-device-plugin-7fd6t        1/1     Running   0          27h
    file-classification-deployment-886497bbd-nklkq   1/1     Running   0          13h
    pattern-provider-deployment-dfd8998c8-pk58c      1/1     Running   0          13h
    regex-provider-6fc966fbdf-gsd6x                  1/1     Running   0          13h
    regex-provider-postgresql-0                      1/1     Running   0          27h
    
    kubectl get pods -n discoverx
    NAME                                               READY   STATUS    RESTARTS        AGE
    ddx-api-f8d495955-f54z7                            2/2     Running   2 (7h41m ago)   7h50m
    ddx-detector-5df7dd4479-wsrj9                      1/1     Running   6 (7h41m ago)   7h50m
    ddx-mapper-7bcbccf658-c5bk2                        1/1     Running   6 (7h41m ago)   7h50m
    discoverx-postgresql-0                             1/1     Running   0               7h50m
    keda-admission-webhooks-5f5b4f887c-hfx26           1/1     Running   0               7h50m
    keda-operator-54c48d5dc9-r4cnd                     1/1     Running   0               7h50m
    keda-operator-metrics-apiserver-586f69f945-p2hd5   1/1     Running   0               7h50m
    
  2. Run the following command to check the Traverse images.

    kubectl -n discoverx get deploy ddx-api \
      -o jsonpath='{range .spec.template.spec.containers[*]}{.image}{"\n"}{end}'
    

    The expected output must return the following snippet.

    <Container_Registry_Path>/discover/traverse/containers/scanner:1.4.0.3858.cd2d73af
    <Container_Registry_Path>/uiux-shell/shell-discover/<version>/shell-discover:1.4.0-18-bc02d78
    
  3. Run the following command to check the status of the Classify service.

    kubectl -n data-discovery exec deploy/classification-deployment -- \
      python3 -c 'import urllib.request as u;print(u.urlopen("http://localhost:8050/pty/data-discovery/v2/entities").status)'
    

    The expected output must return a 200 response.

  4. Run the following command to check that Traverse reads the entity types.

    kubectl -n discoverx exec deploy/ddx-api -c scanner -- \
      python3 -c 'import json,urllib.request as u;print(len(json.load(u.urlopen("http://localhost:8000/pty/discoverx/v1/entity-types"))["items"]))'
    

    The expected output must return 30 or more entities.

  5. Open Traverse on the Web Browser.

    1. Log in to PPC UI with the administrator credentials.
    2. Click Discover on the left pane.

3 - Uninstalling Discover

Steps to uninstall Classify and Traverse.

Traverse stores scan results and datastore credentials in a volume that remains after the release is uninstalled. The keys that protect these credentials are stored in a secret that Helm deletes with the release. Therefore, Traverse can be uninstalled either while retaining the database for a later reinstall or completely.

Important: It is recommended to not remove the volume or the keys independently. Removing only one of them, or removing them separately, results in data loss.

Uninstalling while retaining the database

To retain the database for a later reinstall, complete the following steps.

Uninstall Traverse and retain the database

  1. Run the following commands to save the generated encryption key and database password. Helm deletes both values when it removes the release.

    kubectl get secret discoverx-scanner-secret -n discoverx \
      -o jsonpath='{.data.DISCOVERX_ENCRYPTION_KEY}' | base64 -d > discoverx-key
    kubectl get secret discoverx-scanner-secret -n discoverx \
      -o jsonpath='{.data.DB_PASSWORD}' | base64 -d > discoverx-db-password
    

    Important: Store both files securely, as they are credentials. Without the encryption key, the datastore credentials in the retained database cannot be decrypted.

  2. Run the following command to back up the database.

    kubectl exec -n discoverx discoverx-postgresql-0 -c postgresql -- \
      pg_dump -U discoverx -d discoverx > discoverx-backup.sql
    

    Note: The backup contains the datastore credentials in their encrypted form. It can be used only with the saved encryption key.

  3. Run the following command to remove the autoscaler configuration. Run it before uninstalling the release that owns the autoscaler, so that the release can finish deleting it.

    kubectl delete scaledobject,triggerauthentication --all -n discoverx
    
  4. Run the following commands to uninstall the Traverse and Regex Dictionary provider releases.

    helm uninstall discoverx -n discoverx
    helm uninstall regex-provider -n data-discovery
    

Reinstall Traverse with the Retained Database

To install Traverse again with the retained database, complete the following steps.

  1. Add the following parameters to the Traverse install command and run it.

    --set secret.encryptionKey="$(cat discoverx-key)" \
    --set postgresql.auth.password="$(cat discoverx-db-password)"
    
  2. Optional: Run the following command to restore the backup into an empty database.

    kubectl exec -i -n discoverx discoverx-postgresql-0 -c postgresql -- \
      psql -U discoverx -d discoverx < discoverx-backup.sql
    

    Note: The restore fails if the target database already contains the tables that Traverse creates at startup.

Uninstalling Discover Completely

To remove Traverse completely, complete the following steps.

Important: Deleting the volumes permanently destroys every scan result and datastore definition. This action cannot be undone.

  1. Complete steps 3 and 4 of Uninstall Traverse and retain the database.

  2. Run the following commands to delete the persistent volume claims.

    kubectl delete pvc data-discoverx-postgresql-0 -n discoverx
    kubectl delete pvc data-regex-provider-postgresql-0 -n data-discovery
    
  3. Run the following commands to delete the persistent volumes. The volumes remain after their claims are deleted and continue to incur costs until they are removed.

    kubectl get pv | grep -E 'discoverx|data-discovery'
    kubectl delete pv <name>
    
  4. Optional: Run the following command to delete the autoscaler definitions that were applied during the Traverse installation. These definitions are cluster-wide and remain after any uninstall.

    kubectl delete crd scaledobjects.keda.sh scaledjobs.keda.sh \
      triggerauthentications.keda.sh clustertriggerauthentications.keda.sh \
      cloudeventsources.eventing.keda.sh clustercloudeventsources.eventing.keda.sh
    

    Important: Run this command only if no other component on the cluster uses KEDA. Deleting the definitions deletes every autoscaler object on the cluster.

  5. Run the following command to delete the namespaces.

    kubectl delete namespace discoverx data-discovery
    

Note: If Traverse is uninstalled without saving the encryption key and the database password, the database is retained, but a reinstall generates a new password and a new encryption key. This results in the following:

  • The pods fail with the error password authentication failed for user "discoverx".
  • Any datastore credential stored before the uninstall can no longer be decrypted.

To recover, perform one of the following actions:

  • Restore a database backup that was taken before the uninstall.
  • Start with an empty database and register the data sources again.

4 - Using Traverse

Connecting all the entities in Traverse.

The following is the order that a user can follow to map or detect data in Traverse. The order is not strict, but it is recommended to follow this order to ensure that all entities are connected properly.

  1. Create a Source.
  2. Create a Data Store. This is a container for the data that is detected from the Source. The Data Store can be a database, a file system, or any other type of storage that Traverse supports.
  3. Perform a Scan on the Data Store to detect the data.

4.1 - Sources

Connecting all the entities in Traverse.

Sources is the main front end entry point for Protegrity’s enterprise data catalog service, the system of record for an organization’s entire data estate. It connects to and scans datastores, object stores, knowledge graphs, and identity providers and Active Directory integrations. It maintains a continuously updated inventory of every data source, schema, table, column, file structure, graph entity, principal, role, group, and access path across the organization. Every scan logs not just what exists, but who can reach it and how. It thus maps the relationship between data and the identities that have access to it.

The catalog that Sources maintains is the intelligence foundation for the rest of the Protegrity platform. A scan is a job that runs against the configured sources to discover and classify data at scale. When a scan executes, it checks connectivity, traverses the source structure, and identifies sensitive content. It produces a set of findings that are surfaced in the Source Details for review and action.

Scans can be run on demand or on a schedule. Over time, operational control increases and measurable risk decreases. Coverage can be tracked, newly introduced sensitive data can be detected before it becomes a liability. Timestamped evidence can be generated for governance, compliance reporting, and remediation workflows.

Creating a Scan

A scan is a job that runs against the configured sources to discover and classify data at scale. When a scan executes, it checks connectivity, traverses the source structure, and identifies sensitive content. It produces a set of findings that are surfaced in the Source Details for review and action.

Scans can be run on demand or on a schedule. Over time, operational control increases and measurable risk decreases. Coverage can be tracked, newly introduced sensitive data can be detected before it becomes a liability. Timestamped evidence can be generated for governance, compliance reporting, and remediation workflows.

  1. On the UI, click New Scan to create a scan.
  2. Enter the scan name and description in the Name and Description fields respectively.
  3. From the Select Datastore drop-down list, select the datastore to be scanned. If a new datastore needs to be created, click Add new Datastore to create a new datastore.
  4. Select the scan type from the Scan Type drop-down list. The following options are available:
    • Full Scan. If this option is selected, the entire datastore will be scanned for PII data.
    • Map Only Scan. If this option is selected, only the structure will be scanned. PII data will not be classified.
  5. Under Classification, set the minimum confidence score for the classification results by sliding the Score Threshold slider. The default value is 50%. Any classification with a score below this threshold will be excluded from the scan results.
  6. Enter a value in the Sample Size field to set the maximum number of rows per table.
  7. Click Save to create the scan.

Adding a Source

On the UI, click New Data Source to create a data source. The following data sources are supported:

The following object stores are supported:

The following graph databases are supported:

The following identity providers are supported:

Creating a PostgreSQL Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the PostgreSQL from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Host - Hostname
    • Port - Port number
    • Database Name - Name for the database
    • Username - username to connect to the database
    • SSL mode - Select the SSL mode from the drop-down list. The following options are available:
      • disable
      • allow
      • prefer
      • require
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • Username and Password. If this option is selected, enter the password in the Password field.
    • No credentials
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating a Databricks Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the Databricks from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Workspace URL - URL of the Databricks workspace.
    • HTTP Path - HTTP path.
    • Catalog - Name of the catalog.
    • Schema - Enter the username.
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • Personal Access Token. If this option is selected, enter the token in the Personal Access Token field.
    • Username and Password. If this option is selected, enter the username and password in the Username and Password fields respectively.
    • No credentials.
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating an Apache Hive Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the Apache Hive from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Metastore URI - URI of the Hive metastore.
    • Database - Name of the database.
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • Username and Password. If this option is selected, enter the username and password in the Username and Password fields respectively.
    • No credentials.
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating an Amazon Redshift Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the Amazon Redshift from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Host - Hostname of the Amazon Redshift cluster.
    • Port - Port number.
    • Database - Name of the database.
    • Schema - Name of the schema.
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • IAM Access Key. If this option is selected, enter the IAM Access Key ID in the Access Key ID field and the IAM Secret Access Key in the Secret Access Key field.
    • Username and Password. If this option is selected, enter the username and password in the Username and Password fields respectively.
    • No credentials.
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating an Oracle Database Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the Oracle Database from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Driver - Oracle JDBC driver class name. For example, oracle.jdbc.OracleDriver.
    • Port - Port number.
    • Database - Name of the database.
    • Schema - Name of the schema.
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • Username and Password. If this option is selected, enter the username and password in the Username and Password fields respectively.
    • No credentials.
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating an Amazon S3 Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the Amazon S3 from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Region - AWS region where the bucket is located.
    • Bucket - Name of the S3 bucket.
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • IAM Role. If this option is selected, enter the IAM role ARN in the Role ARN field.
    • Access Key ID. If this option is selected, enter the AWS access key ID in the Access Key ID field and the AWS secret access key in the Secret Access Key field.
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating a TigerGraph Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the TigerGraph from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Host - Hostname of the TigerGraph server.
    • Graph Name - Name of the graph.
    • REST++Port - Port number.
    • GS Port - Port number.
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • Username and Password. If this option is selected, enter the username and password in the Username and Password fields respectively.
    • GSQL Secret. If this option is selected, enter the GSQL secret in the GSQL Secret field.
    • No credentials
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating a Neo4j Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the Neo4j from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Host/URI - Hostname or the URL of the Neo4j server
    • Database - Name of the database
  4. Under Authentication, select the authentication method from the drop-down list. The following options are available:
    • Username and Password. If this option is selected, enter the username and password in the Username and Password fields respectively.
    • No credentials
  5. Click Test Connection to verify the connection to the database.
  6. After the connection is successful, click Save to create the source.

Creating a OIDC/Okta Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the OIDC/Okta from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Issuer URL - The URL of the OIDC/Okta issuer
    • Client ID - The client ID for the OIDC/Okta application
    • Client Secret - The client secret for the OIDC/Okta application
    • Token URL - The URL to obtain the access token
  4. Click Test Connection to verify the connection to the OIDC/Okta provider.
  5. After the connection is successful, click Save to create the source.

Creating a LDAP/Active Directory Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the LDAP/Active Directory from the Data Source type drop-down list.
  3. Under Connection, enter data in the following fields:
    • Host - The URL of the LDAP/Active Directory server
    • Port - The port of the LDAP/Active Directory server
    • Base DN - The base distinguished name for LDAP/Active Directory searches
  4. Under Authentication, enter the username and password in the Username and Password fields respectively.
  5. Click Test Connection to verify the connection to the LDAP/Active Directory server.
  6. After the connection is successful, click Save to create the source.

Creating an SCIM 2.0 Source

  1. Enter the source name and description in the Name and Description fields respectively.
  2. Select the SCIM 2.0 from the Data Source type drop-down list.
  3. Under Connection, enter the URL of the SCIM 2.0 server in the Base URL field.
  4. Under Authentication, enter the bearer token for the SCIM 2.0 server in the Bearer Token
  5. Click Test Connection to verify the connection to the SCIM 2.0 server.
  6. After the connection is successful, click Save to create the source.

Reviewing a Scan

Reviewing scan details is where users turn discoveries into decisions. The Schema tab shows object-level results, exposing classifications at each discovered asset level: datasource, schema, table, column, and node or path for hierarchical sources. The value is traceable evidence and faster action. Teams can verify coverage, compare drift over time, confirm whether sensitive data increased or moved, prioritize remediation by risk and location. They can then provide defensible audit and compliance reporting based on exact findings rather than assumptions.

To investigate the metadata or classification history for any object, click the representative row to open the Source Detail Panel. The panel displays object metadata at the top, followed by the classification response and an activity log showing changes to that row over time.

The Scanners tab displays all configured scanners. For recurring scanners, click into a scanner item to see its individual jobs, such as currently running, scheduled, and past. Each job shows when it ran or is scheduled to run, its scope, status, and duration, along with how findings changed across executions.

4.2 - Classifications

About the Classifications.

Classifications allow a user to define and manage the custom detection logic required by an organization. Any classification created and marked as Active is applied by Discover during scanning, alongside Protegrity-provided classifications. The resulting outputs, both Protegrity-provided and custom, are written directly to the catalog and enrich each discovered entity with protection conditions, data type labels, and compliance framework tags. This enriched metadata drives downstream capabilities such as policy alignment, risk prioritization, reporting, and remediation workflows.

Note: Classifications marked as available are available anytime Classify as a Service is run using the same Classify container service.

Creating a Classification

  1. On the left pane of the UI, navigate to Classifiers.
  2. Click New Classification to create a classifier.
  3. Enter the classifier name and description in the Name and Description fields respectively.
  4. Under Classification, enter data in the following fields:
    • Entity Type - The PII identity that the classifier classifies. For example, Email, Phone Number, Credit Card Number, and so on.
    • Categories - The categories that the classifier can be grouped into. Following are the three categories:
    • PII
    • PHI
    • PCI
  5. Under Detection, enter data in the following fields:
    • Score Adjustment - The confidence score for the classifier.
    • Data Qualifier Regex - Values that match the regex pattern are classified.
    • Schema Keywords - Column names that boost the confidence score when the regex is matched. Click Add Keyword to add more keywords.
  6. Under Try It, enter a sample pattern and click Test.
  7. Click Create to create the classifier.

5 - API Reference

API reference and supporting information.

The APIs for the Classification service and the File Classification service are listed here

5.1 - Classify

APIs for the Classification Service.

The following APIs are exposed for the Classification Service.

  • Text
  • Tabular
  • JSON
  • XML

Classify Text

This API endpoint classifies plain text unstructured data.

POST http://<Host Address>/pty/discover/v2/classify/text

  • Content type must be a plain text and in an UTF-8 format.

Important:

  • Length of the body is limited to 10 KB. If the body exceeds this limit, it is recommended to use the File Classification Text API. For more information about this File Classification, refer to the File Classification API.
  • Non-Latin text is not supported. If the input contains a non-Latin text, the text is rejected with a 422 error code.

Query Parameters

score_threshold

  • Type: float
  • Description: Optional. Exclude results with a score lower than this threshold.
  • Values: Minimum 0, Maximum 1.0
  • Default: 0.7

Sample Request

curl -X POST "http://<Host_address>/pty/data-discovery/v2/classify/text?score_threshold=0.85" \
     -H "Content-Type: text/plain" \
     --data "You can reach Dave Elliot by phone 203-555-1286"
import requests

url = "http://<Host_address>/pty/data-discovery/v2/classify/text"
params = {"score_threshold": 0.85}
headers = {"Content-Type": "text/plain"}
data = "You can reach Dave Elliot by phone 203-555-1286"

response = requests.post(url, params=params, headers=headers, data=data, verify=False)

print("Status code:", response.status_code)
print("Response JSON:", response.json())
URL: POST `http://<Host_address>/pty/data-discovery/v2/classify/text`
Query Parameters:
-score_threshold (optional), float between 0.0 and 1.0, default: 0.7
Headers:
-Content-Type: text/plain
Body:
-You can reach Dave Elliot by phone 203-555-1286

Classify Tabular Data

This API endpoint classifies structured Tabular data.

POST http://<Host Address>/pty/discover/v2/classify/tabular

  • Content type must be text/csv and UTF-8 encoded.

Query Parameters

score_threshold

  • Type: float
  • Description: Optional. Exclude results with a score lower than this threshold.
  • Values: Minimum 0, Maximum 1.0
  • Default: 0.7

has_headers

  • Type: boolean
  • Description: Optional. Indicates whether the first row represents the column header.
  • Values: true/false
  • Default: true

column_delimiter

  • Type: char
  • Description: Optional. Delimiter to separate the columns.
  • Default: ,

quote_char

  • Type: char
  • Description: Optional. Character to quote fields containing special characters, such as, the column_delimiter or new-line characters.
  • Default: "

Body

  • Content type should be text/csv and in UTF-8 format.

  • Body size is limited to 10K Bytes

Sample Request

curl -X POST "http://<Host_address>/pty/data-discovery/v2/classify/tabular?score_threshold=0.85" \
--header 'Content-Type: text/csv' \
--data-raw 'Social Security Number,Credit Card Number,IBAN,Phone Number
589-25-1068,349384370543801,FR43 9255 4858 47BG 3EBG U4OK O18,(483) 9440301
636-36-3077,4041594844904,AL50 8947 4215 KAEY GAPM NLYC FNZG,(113) 5143119
748-82-2375,3558175715821800,AT34 4082 9269 0841 5702,(763) 5136237
516-62-9861,560221027976015000,FR22 0068 7181 11FB UG8H ECEM 306,(726) 6031636
121-49-9409,374283320982549,DK37 5687 8459 8060 79,(624) 9205200
838-73-3299,5558216060144900,CR54 8952 8144 6403 4765 0,(356) 9479541
439-11-5310,5048376143641900,RS76 6213 4824 0184 8983 74,(544) 5623326
564-06-8466,3543299511845640,EE51 6882 3443 7863 4703,(702) 6093849
518-54-5443,3543019452249540,IT65 D000 3874 2801 Z15I LNLL OOX,(584) 8618371'
import requests

url = "http://<Host_address>/pty/data-discovery/v2/classify/tabular"
params = {"score_threshold": 0.85}
headers = {"Content-Type": "text/csv"}
data = """Social Security Number,Credit Card Number,IBAN,Phone Number
589-25-1068,349384370543801,FR43 9255 4858 47BG 3EBG U4OK O18,(483) 9440301
636-36-3077,4041594844904,AL50 8947 4215 KAEY GAPM NLYC FNZG,(113) 5143119
748-82-2375,3558175715821800,AT34 4082 9269 0841 5702,(763) 5136237
516-62-9861,560221027976015000,FR22 0068 7181 11FB UG8H ECEM 306,(726) 6031636
121-49-9409,374283320982549,DK37 5687 8459 8060 79,(624) 9205200
838-73-3299,5558216060144900,CR54 8952 8144 6403 4765 0,(356) 9479541
439-11-5310,5048376143641900,RS76 6213 4824 0184 8983 74,(544) 5623326
564-06-8466,3543299511845640,EE51 6882 3443 7863 4703,(702) 6093849
518-54-5443,3543019452249540,IT65 D000 3874 2801 Z15I LNLL OOX,(584) 8618371
"""

response = requests.post(url, params=params, headers=headers, data=data, verify=False)

print("Status code:", response.status_code)
try:
    print("Response JSON:", response.json())
except ValueError:
    print("Response Text:", response.text)
URL: POST `http://<Host_address>/pty/data-discovery/v2/classify/tabular`
   Query Parameters:
   -score_threshold (optional), float between 0.0 and 1.0, default: 0.
   -has_headers (optional), Indicates whether the first row represents the column header.
   -column_delimiter (optional), Delimiter to separate the columns.
   -quote_char (optional), Character to quote fields containing special characters, such as, the column_delimiter or new-line characters.
   Headers:
   -Content-Type: text/csv
   Body:
   -Social Security Number,Credit Card Number,IBAN,Phone Number
  589-25-1068,349384370543801,FR43 9255 4858 47BG 3EBG U4OK O18,(483) 9440301
  636-36-3077,4041594844904,AL50 8947 4215 KAEY GAPM NLYC FNZG,(113) 5143119
  748-82-2375,3558175715821800,AT34 4082 9269 0841 5702,(763) 5136237
  516-62-9861,560221027976015000,FR22 0068 7181 11FB UG8H ECEM 306,(726) 6031636
  121-49-9409,374283320982549,DK37 5687 8459 8060 79,(624) 9205200
  838-73-3299,5558216060144900,CR54 8952 8144 6403 4765 0,(356) 9479541
  439-11-5310,5048376143641900,RS76 6213 4824 0184 8983 74,(544) 5623326
  564-06-8466,3543299511845640,EE51 6882 3443 7863 4703,(702) 6093849
  518-54-5443,3543019452249540,IT65 D000 3874 2801 Z15I LNLL OOX,(584) 8618371

Classify JSON Data

This API endpoint classifies structured JSON data.

POST http://<Host Address>/pty/discover/v2/classify/json

Query Parameters

score_threshold

  • Type: float
  • Description: Optional. Exclude results with a score lower than this threshold.
  • Values: Minimum 0, Maximum 1.0
  • Default: 0.7

Body

  • Content type must be application/json and encoded in UTF-8 format.

  • Length of the body is limited to 10K Bytes.

Sample Request

curl --location '<Host_address>/pty/data-discovery/v2/classify/json' \
--header 'Content-Type: application/json' \
--data '{
    "address": "64.219.62.68"
}'
import requests
import json

url = "http://<Host_address>/pty/data-discovery/v2/classify/json"
params = {"score_threshold": 0.85}
headers = {"Content-Type": "application/json"}
data = json.dumps({
  "address": "64.219.62.68"
})

response = requests.post(url, params=params, headers=headers, data=data, verify=False)

print("Status code:", response.status_code)
try:
    print("Response JSON:", response.json())
except ValueError:
    print("Response Text:", response.text)
URL: POST `http://<Host_address>/pty/data-discovery/v2/classify/json`
Query Parameters:
-score_threshold (optional), float between 0.0 and 1.0, default: 0.7
Headers:
-Content-Type: application/json
Body:
-{"address": "64.219.62.68"}

Classify XML Data

This API endpoint classifies structured XML data.

POST https://<Host Address>/pty/data-discovery/v2/classify/xml

Query Parameters

score_threshold

  • Type: float
  • Description: Optional. Exclude results with a score lower than this threshold.
  • Values: Minimum 0, Maximum 1.0
  • Default: 0.7

Body

  • Content type must be application/xml and encoded in UTF-8 format.

  • Length of the body is limited to 10K Bytes.

Sample Request

curl --location '<Host_address>/pty/data-discovery/v2/classify/xml' \
--header 'Content-Type: application/xml' \
--data '<address>64.219.62.68</address>'
import requests

url = "http://<Host_address>/pty/data-discovery/v2/classify/xml"
params = {"score_threshold": 0.85}
headers = {"Content-Type": "application/xml"}
data = "<address>64.219.62.68</address>"

response = requests.post(url, params=params, headers=headers, data=data, verify=False)

print("Status code:", response.status_code)
try:
    print("Response JSON:", response.json())
except ValueError:
    print("Error", response.text)
URL: POST `http://<Host_address>/pty/data-discovery/v2/classify/xml`
Query Parameters:
-score_threshold (optional), float between 0.0 and 1.0, default: 0.7
Headers:
-Content-Type: application/xml
Body:
-<address>64.219.62.68</address>

5.2 - File Classification

APIs for the File Classification Service.

The following APIs are exposed for the File Classification Service.

  • Text
  • JSON
  • XML

Detect Text

This API classifies sensitive entities in plain text unstructured data.

POST http://<Host Address>/pty/data-discovery/detection/v2/detect/text

  • Content type must be a plain text and in an UTF-8 format.

score_threshold

  • Type: float
  • Description: Optional. Exclude results with a score lower than this threshold.
  • Values: Must be greater than 0.
  • Default: 0.7

Body

  • Content type must be multipart/form-data.

  • The content field contains the plain text to scan.

  • Length of the content is limited to 5 MB.

Sample Request

curl -X POST "http://localhost:8053/pty/data-discovery/detection/v2/detect/text" \
  -F "file=@customer_data.txt"
import os
import json
import requests

# Path to the text file to submit
INPUT_FILEPATH = os.path.join(os.path.dirname(__file__), "fixtures", "example.txt")
#INPUT_FILEPATH = os.path.abspath("/opt/workspaces/discover/classification/deployment_qa/tests/features/common/detection/fixtures/xml_data/5mb_with_pii.xml")

# Detection service endpoint
url = "http://localhost:8053/pty/data-discovery/detection/v2/detect/text"

with open(INPUT_FILEPATH, "rb") as input_file:
    
    response = requests.post(
        url, 
        files={
            "file": (
                os.path.basename(INPUT_FILEPATH), 
                input_file
            )
        }
    )

print("Status Code:", response.status_code)

try:
    print("Response:", json.dumps(response.json(), indent=2))
except ValueError:
    
    print("Response is not valid JSON:", response.text)
URL: POST `http://<Host_address>/pty/data-discovery/detection/v2/detect/text`
Query Parameters:
-score_threshold (optional), float greater than 0 and up to 1.0, default: 0.7
Headers:
-Content-Type: multipart/form-data
Body (form-data):
-content: You can reach Dave Elliot by phone 203-555-1286

Classify JSON Files API

Query Parameters

score_threshold

  • Type: float
  • Description: Optional. Exclude results with a score lower than this threshold.
  • Values: Must be greater than 0.
  • Default: 0.7

Body

  • Content type must be multipart/form-data.

  • The content field contains the JSON text to scan.

  • Length of the content is limited to 5 MB.

Sample Request

curl -X POST "http://localhost:8053/pty/data-discovery/detection/v2/detect/json" \
  -F "file=@customer_data.json"
import os
import json
import requests

# Path to the text file to submit
INPUT_FILEPATH = os.path.join(os.path.dirname(__file__), "fixtures", "complex_hr.json")
# Detection service endpoint
url = "http://localhost:8053/pty/data-discovery/detection/v2/detect/json"

with open(INPUT_FILEPATH, "rb") as input_file:
    
    response = requests.post(
        url, 
        files={
            "file": (
                os.path.basename(INPUT_FILEPATH), 
                input_file
            )
        }
    )

print("Status Code:", response.status_code)

try:
    print("Response:", json.dumps(response.json(), indent=2))
except ValueError:
    
    print("Response is not valid JSON:", response.text)
URL: POST `http://<Host_address>/pty/data-discovery/detection/v2/detect/json`
Query Parameters:
-score_threshold (optional), float greater than 0 and up to 1.0, default: 0.7
Headers:
-Content-Type: multipart/form-data
Body (form-data):
-content: You can reach Dave Elliot by phone 203-555-1286

Classify XML Files API

POST http://<Host Address>/pty/data-discovery/detection/v2/detect/xml

score_threshold

  • Type: float
  • Description: Optional. Exclude results with a score lower than this threshold.
  • Values: Must be greater than 0.
  • Default: 0.7

Body

  • Content type must be multipart/form-data.

  • The content field contains the XML text to scan.

  • Length of the content is limited to 5 MB.

Sample Request

curl -X POST \
  "http://localhost:8053/pty/data-discovery/detection/v2/detect/xml" \
  -F "file=@/path/to/fixtures/complex_hr.xml"
import os
import json
import requests

# Path to the text file to submit
INPUT_FILEPATH = os.path.join(os.path.dirname(__file__), "fixtures", "complex_hr.xml")
# Detection service endpoint
url = "http://localhost:8053/pty/data-discovery/detection/v2/detect/xml"

with open(INPUT_FILEPATH, "rb") as input_file:
    
    response = requests.post(
        url, 
        files={
            "file": (
                os.path.basename(INPUT_FILEPATH), 
                input_file
            )
        }
    )

print("Status Code:", response.status_code)

try:
    print("Response:", json.dumps(response.json(), indent=2))
except ValueError:
    
    print("Response is not valid JSON:", response.text)
URL: POST `http://<Host_address>/pty/data-discovery/detection/v2/detect/xml`
Query Parameters:
-score_threshold (optional), float greater than 0 and up to 1.0, default: 0.7
Headers:
-Content-Type: multipart/form-data
Body (form-data):
-content: You can reach Dave Elliot by phone 203-555-1286

Response Codes

Response CodeDescription
200Successful Response.
206Partial Content. Some classifications succeeded; others failed.
400Bad Request. Invalid input parameters or content.
413Payload too large.
422Validation Error.
500Internal server error. Check server logs.
502Bad Gateway. More than half of the classification calls failed.

5.3 - Transform

Identify, classify & transform sensitive data.

Identify and classify plain-text sensitive data. Replace the sensitive data with labels of the classified data types, such as, <CREDIT_CARD> and so on.

POST http://<Host Address>/pty/data-discovery/v2/transform/label

Query Parameters

score_threshold

  • Type: float
  • Description: Optional. Label results where the score is greater than this threshold.
  • Values: Minimum 0, Maximum 1.0
  • Default: 0.7

include_providers

  • Type: binary
  • Description: Optional. Include details of the service providers in the response.
  • Values: Yes / No
  • Default: No

include_classification_details

  • Type: binary
  • Description: Optional. Include classification details in the response.
  • Values: Yes / No
  • Default: No

Body

  • Content type must be text/plain and in UTF-8 format.

  • Body size is limited to 10K Bytes

Sample Request

curl -X POST "http://<Host_address>/pty/data-discovery/v2/transform/label?score_threshold=0.85" \
          -H "Content-Type: text/plain" \
          --data "Jake lives at 15 Main st, Hamden 06517, Connecticut."
import requests
    
    url = "http://<Host_address>/pty/data-discovery/v2/transform/label"
    params = {"score_threshold": 0.85}
    headers = {"Content-Type": "text/plain"}
    data = "Jake lives at 15 Main st, Hamden 06517, Connecticut."
    
    response = requests.post(url, params=params, headers=headers, data=data, verify=False)
    
    print("Status code:", response.status_code)
    print("Response JSON:", response.json())
URL: POST `http://<Host_address>/pty/data-discovery/v2/transform/label`
   Query Parameters:
   -score_threshold (optional), float between 0.0 and 1.0, default: 0.
   Headers:
   -Content-Type: text/plain
   Body:
   -Jake lives at 15 Main st, Hamden 06517, Connecticut.

5.4 - Common APIs

Standard operational endpoints available on the service.

These endpoints provide operational capabilities such as retrieving the API specification, managing log levels, checking version information, and monitoring service health.

Version API

View runtime version information.

GET http://<Host Address>/version

Sample Request

curl -X GET "http://<Host_address>/version"
     
import requests
    
    url = "http://<Host_address>/version"
    response = requests.get(url, verify=False)
    
    print("Status code:", response.status_code)
    try:
        print("Response JSON:", response.json())
    except ValueError:
        print("Response Text:", response.text)
    
URL: GET `http: //<Host_address>/version`

Response Codes

CodeDescription
200Version information retrieved successfully.

Readiness Probe

This is used by Kubernetes as a readiness probe.

GET http://<Host Address>/ready

Sample Request

curl -X GET "http://<Host_address>/ready"
     
import requests
    
    url = "http://<Host_address>/ready"
    response = requests.get(url, verify=False)
    
    print("Status code:", response.status_code)
    

The file /docs/discover/restapi/commonapis/output/postman.json was not found.

Response Codes

CodeDescription
204Service is fully initialized and can handle requests.
503Service is not yet ready to serve requests.

Liveness Probe

Used by Kubernetes as a liveness probe.

GET http://<Host Address>/live

Used by Kubernetes as a liveness probe.

Sample Request

curl -X GET "http://<Host_address>/live"
     
import requests
    
    url = "http://<Host_address>/live"
    response = requests.get(url, verify=False)
    
    print("Status code:", response.status_code)
    
URL: GET `http: //<Host_address>/live`

Response Codes

CodeDescription
204Service can handle requests.

Health Check

Returns service health status including individual component-level checks.

GET http://<Host Address>/health

Sample Request

curl -X GET "http://<Host_address>/health"
     
import requests
    
    url = "http://<Host_address>/health"
    response = requests.get(url, verify=False)
    
    print("Status code:", response.status_code)
    try:
        print("Response JSON:", response.json())
    except ValueError:
        print("Response Text:", response.text)
    
URL: GET `http: //<Host_address>/health`

Response Codes

CodeDescription
200Service is running normally.
503Service is unhealthy. Its components may be initializing or may need a restart.

Retrieve Logs

GET http://<Host Address>/log

Returns the current runtime logging level.

Sample Request

curl -X GET "http://<Host_address>/log"
     
import requests
    
    url = "http://<Host_address>/log"
    response = requests.get(url, verify=False)
    
    print("Status code:", response.status_code)
    try:
        print("Response JSON:", response.json())
    except ValueError:
        print("Response Text:", response.text)
    
URL: GET `http://<Host_address>/log`

Update the Logging Level

Updates the runtime logging level.

POST http://<Host Address>/log

Request Body

NameTypeRequiredDescription
levelstringYesThe log level to set. Possible values: debug, info, warn.

Sample Request

curl -X POST "http://<Host_address>/log" \
       -H "Content-Type: application/json" \
       -d '{"level": "debug"}'
     
import requests
    
    url = "http://<Host_address>/log"
    payload = {"level": "debug"}
    headers = {"Content-Type": "application/json"}
    response = requests.post(url, json=payload, headers=headers, verify=False)
    
    print("Status code:", response.status_code)
    try:
        print("Response JSON:", response.json())
    except ValueError:
        print("Response Text:", response.text)
    
URL: POST `http: //<Host_address>/log`
   Body (JSON): {
       "level": "debug"
   }

Response Codes

CodeDescription
200Log level updated successfully.
500An error occurred (e.g., invalid log level specified).

Note: The service currently returns 500 for invalid log level values. The OpenAPI spec defines 400 for this case — this is a known discrepancy to be addressed in a future release.

Supported Entities

List the entities supported by Classify.

GET http://<Host Address>/pty/data-discovery/v2/entities

Query Parameters

None

Sample Request

curl -X GET "http://<Host_address>/entities"
     
import requests
    
    url = "http://<Host_address>/entities"
    response = requests.get(url, verify=False)
    
    print("Status code:", response.status_code)
    try:
        print("Response JSON:", response.json())
    except ValueError:
        print("Response Text:", response.text)
    
URL: GET `http://<Host_address>/entities`
CodeDescription
200Entities retrieved successfully.
502Bad Gateway. The service has no entity list it can serve.
598Internal Server Error. Check server logs.

API Specification

Returns the OpenAPI specification for the Classify API.

GET http://<Host Address>/doc

Sample Request

curl -X GET "http://<Host_address>/doc"
     
import requests
    
    url = "http://<Host_address>/doc"
    response = requests.get(url, verify=False)
    
    print("Status code:", response.status_code)
    print("Response YAML:", response.text)
    
URL: GET `http: //<Host_address>/doc`

Response Codes

CodeDescription
200The OpenAPI specification is returned in YAML format.

6 - Additional Information

Additional information about Protegrity’s Discover.

Discover is Protegrity’s enterprise data intelligence layer. It comprises of two integrated services, Traverse and Classify.

Traverse maintains an updated catalog of an organization’s entire data estate. It continuously scans and indexes datastores, object stores, knowledge graphs, and identity directories (IDP/AD). It in turn maps every data source, schema, principal, and access path across the organization. This service directly supports the Sources views in the front-end of the application.

Classify runs across everything Traverse catalogs and can be used independently in User defined pipelines. It detects and classifies sensitive data, such as, PII, PHI, financial data, credentials, custom types at the field, file, and content level, including unstructured documents and live AI workflow content.

Together, Discover builds and maintains the foundational intelligence that powers the rest of the Protegrity platform.

6.1 - Handling Overlapping Conflicts

Resolving conflicts between entities that label sensitive data.

While classifying data, the providers may label an identical text under two different entities. This distinction arises from the detection strategies the classifiers adopt. Classify handles these conflicts by applying certain rules on these conflicting entities.

The rules for handling the conflicting entities are as follows:

  • No overlap: If the two entities do not conflict, retain the results in the original form.

    For example, Jake Filbert lives in Connecticut. If only Jake Filbert is identified, the result will be labeled as [NAME] lives in Connecticut.

  • Full overlap: If both the entities overlap, the following logic will be applied:

    • Select the entity with a higher confidence score.
    • If both the entities contain the same confidence score, select the first entity.

    For example, Jake Filbert lives in Connecticut. Here, the name is recognized as [USER] with a score 0.7 and [NAME] with a score 0.9. As [NAME] has a higher score, the result will be labeled as [NAME] lives in Connecticut.

  • One entity contained in other: If one entity is completely contained in the other, select the entity with the longer text.

    For example, jake@email.com. Here, the classifiers may recognize the text as [NAME] and [EMAIL]. As [EMAIL] is the longer text, the result will be labeled as [EMAIL].

  • Partial intersection. If the two entities overlap partially, the result will be a combination of both.

    For example, 092-33445. Here, the classifiers may recognize the text as [PHONE_NUMBER] and [SSN]. The result will be labeled as [PHONE_NUMBER&SSN].

6.2 - Input Validation

Rejecting unsanitized data.

The Classification service in Classify offers an input validation security feature that rejects invalid input data. Data that is malformed, non-normalized, containing homoglyphs, hieroglyphs, mixed Unicode variants, or control characters is considered as unsanitized or invalid data. These are rejected and will not be classified.

The following are few examples of data that will be rejected:

  • Ⅷ
  • 𝓉𝑒𝓍𝓉
  • Pep

Before invoking the Classification endpoint, ensure that the input text is normalized. Replace invalid characters by their corresponding normalized plaintext characters. If the input text contains any invalid character, a status code of 422 and a message Untrusted input is returned.

For security purposes, the application rejects unsanitized data by default. It is recommended that this feature remains enabled. However, to override this feature, perform the following steps.

6.3 - Harmonization

Aggregate responses under a similar category.

Based on the detection logic, the Pattern and Context classification providers might classify the same data in different labels. The classification service standardizes provider outputs into a unified response.

Consider the example, You can visit our office located in New York City.

  • Context provider might categorize New York City as CITY.
  • Pattern provider might categorize New York City as LOCATION.

This can cause an inconsistency in the outputs generated across the providers.

Classify ensures standardization of responses by aggregating similar outputs of the providers under a common classification name. In the example shown, the classification service will categorize New York City under the category LOCATION.

Harmonization Process

The following pointers illustrate the harmonization process in detail.

Providers Mapping Entities

Each provider is responsible for mapping its identified entities to harmonized classification entities that are consistent with those used by other providers. This ensures that the classification service can accurately aggregate and interpret responses across multiple providers. When a provider’s classification is harmonized, the response must include the originally identified entity alongside the harmonized classification.

The following snippet shows how the Context classification provider initially classified the entity as CITY, which was then harmonized into the category LOCATION.

{
  "providers": "...",
  "classifications": {
    "LOCATION": [
      {
        "score": 0.9222000122070313,
        "location": {
          "start_index": 36,
          "end_index": 49
        },
        "classifiers": [
          {
            "provider_index": 0,
            "name": "SpacyRecognizer",
            "score": 0.85,
            "original_entity": "LOCATION",
            "details": {}
          },
          {
            "provider_index": 1,
            "name": "context",
            "score": 0.9944000244140625,
            "original_entity": "CITY",
            "details": {}
          }
        ]
      }
    ]
  }
}

Grouping by Matching Indexes

The entities are grouped together only if the responses shared by the providers contain the same start_index, end_index, and similar classification entity. If the start_index and end_index differ, the entities will not be grouped together.

As shown in the following snippet, the Context and Pattern providers classify the data as IT_IDENTITY_CARD and ID_CARD respectively. These are then grouped under the NATIONAL_ID category by the classification service:

{
  "providers": ...,
  "classifications": {
    "NATIONAL_ID": [
      {
        "score": 0.9236000061035157,
        "location": {
          "start_index": 14,
          "end_index": 25
        },
        "classifiers": [
          {
            "provider_index": 0,
            "name": "pattern_classification",
            "score": 0.85,
            "original_entity": "IT_IDENTITY_CARD" 
          }, {
            "provider_index": 1,
            "name": "context_classification",
            "score": 0.9972000122070312,
            "original_entity": "ID_CARD" 
          }
        ]
      }
    ]
  }
}

Non-Matching Indexes

If the responses for start_index and end_index differ, the entities will not be grouped together. However, the entities will appear under a common classification name.

The following table illustrates a common classification name for multiple providers.

ProviderOriginal Entity LabelsCommon Classification Name
Pattern ProviderLOCATIONLOCATION
Context ProviderCITY, STATE, COUNTRY, COUNTY, ZIP_CODE, STREET, BUILDING, GEO_COORDINATELOCATION

The following snippet illustrates the sample:

{
  "providers": "...",
  "classifications": {
    "LOCATION": [
      {
        "score": 0.9236000061035157,
        "location": {
          "start_index": 0,
          "end_index": 35
        },
        "classifiers": [
          {
            "provider_index": 0,
            "name": "pattern_provider",
            "score": 0.85,
            "original_entity": "LOCATION"
          }
        ]
      },
      {
        "score": 0.9236000061035157,
        "location": {
          "start_index": 0,
          "end_index": 17
        },
        "classifiers": [
          {
            "provider_index": 1,
            "name": "context_provider",
            "score": 0.9972000122070312,
            "original_entity": "STREET"
          }
        ]
      },
      {
        "score": 0.9236000061035157,
        "location": {
          "start_index": 20,
          "end_index": 22
        },
        "classifiers": [
          {
            "provider_index": 1,
            "name": "context_provider",
            "score": 0.9972000122070312,
            "original_entity": "BUILDING"
          }
        ]
      },
      {
        "score": 0.9236000061035157,
        "location": {
          "start_index": 25,
          "end_index": 31
        },
        "classifiers": [
          {
            "provider_index": 1,
            "name": "context_provider",
            "score": 0.9972000122070312,
            "original_entity": "ZIP_CODE"
          }
        ]
      }
    ]
  }
}