Skip to content

Working with Policies

Before you can send telemetry about how PII is used in your software systems, you must define the reasons that you use the data. Each reason should then suggest how long you must retain data items for when they are used for this reason, based on your business requirements. For example, if you sell goods on your website and use a payment method that supports chargebacks for up to 3 months, you should use a sales policy which is at least 3 months, although you may want to allow a small window of extra time to be able to recognise customers who checked out without creating an account. If you support a product returns policy, you should create a second policy for product returns which matches your business requirements for the duration of product returns. If you keep customer details for at least 30 days after a customer support request, you might have another policy for customer support, so that after each interaction, the customer data is kept for an additional 30 days and after that time, any cases are considered resolved and the customer data should expire.

We must create an instance of the PolicyManagementApi client to work with policies then call the putPolicy method which has the following signature: putPolicy(policySlug, policyData), where policyData must contain all of aging strategy, aging offset amount and aging offset unit when creating a policy.

create-policy.ts
import { AgingOffsetUnit, AgingStrategy, PolicyManagementApi, ServerConfiguration, createConfiguration } from "@privatedataservices/metronome-client";
import { explainError } from "./errors";
const clientConfig = createConfiguration( {
baseServer: new ServerConfiguration("https://the-flower-boutique.dev.eu-west-1.privatedataservices.com", {}),
authMethods: { ApiKeyAuth: process.env.METRONOME_API_KEY }
});
const pmApiClient = new PolicyManagementApi(clientConfig);
try {
const response = await pmApiClient.putPolicy("user-account-access", {agingStrategy: AgingStrategy.since_last_read_or_write, agingOffsetAmount: 2, agingOffsetUnit: AgingOffsetUnit.month});
console.log("Policy %s created successfully. Fields updated were: %s", response.policyId, response.fieldsModified.join(", "));
} catch (err) {
explainError(err);
}

Policies have 2 aging strategies:

  1. since-last-read-or-write
  2. since-first-read-or-write

Most policies will likely use the first strategy so that each interaction can extend the useful life of the PII being handled. The second aging strategy is most likely to be used for data on-boarding, so that data that was stored before Metronome was implemented can begin to be tracked. An on-boarding policy that uses since-first-read-or-write will only work once, but if the data has already been introduced to Metronome by another policy, the on-boarding policy will be skipped because the data is already known.

The aging offset amount must be a positive integer greater than 1.

Metronome supports 3 aging offset units:

  • day
  • month
  • year

In the example above, a policy named user-account-access is defined which causes PII handled with this policy to be retained for 2 months from the time of the observation.

The example below modifies the user-account-access policy to retain data for 1 year after being handled with this policy.

We again create an instance of the PolicyManagementApi client to work with policies then call the putPolicy but for modifications, policyData must contain at least 1 of aging strategy, aging offset amount or aging offset unit. You can change several attributes such as aging offset amount and aging offset unit at the same time.

modify-policy.ts
import { AgingOffsetUnit, PolicyManagementApi, ServerConfiguration, createConfiguration } from "@privatedataservices/metronome-client";
import { explainError } from "./errors";
const clientConfig = createConfiguration( {
baseServer: new ServerConfiguration("https://the-flower-boutique.dev.eu-west-1.privatedataservices.com", {}),
authMethods: { ApiKeyAuth: process.env.METRONOME_API_KEY }
});
const pmApiClient = new PolicyManagementApi(clientConfig);
try {
const response = await pmApiClient.putPolicy("user-account-access", {agingOffsetAmount: 1, agingOffsetUnit: AgingOffsetUnit.year});
console.log("Policy %s modified successfully. Fields updated were: %s", response.policyId, response.fieldsModified.join(", "));
} catch (err) {
explainError(err);
}

To read 1 specific policy, you call the PolicyManagementApi client’s getPolicy method with the only parameter being the slug of the policy you wish to read.

read-policy.ts
import { PolicyManagementApi, ServerConfiguration, createConfiguration } from "@privatedataservices/metronome-client";
import { explainError } from "./errors";
const clientConfig = createConfiguration( {
baseServer: new ServerConfiguration("https://the-flower-boutique.dev.eu-west-1.privatedataservices.com", {}),
authMethods: { ApiKeyAuth: process.env.METRONOME_API_KEY }
});
const pmApiClient = new PolicyManagementApi(clientConfig);
try {
const policy = await pmApiClient.getPolicy("user-account-access");
console.log("Policy ID is %s created at %s with aging strategy %s which ages by %s %s", policy.policyId, policy.createDate, policy.agingStrategy, policy.agingOffsetAmount, policy.agingOffsetUnit);
} catch (err) {
explainError(err);
}

The policy listing interface is pagenated. In the event that there are more than 1000 entries, the first call will receive 1000 items and a continuation token for your next call. The next call should specify the continuation token as the first parameter to the getManyPolicies method. The second parameter is a policy slug prefix, should you only wish to search for policies starting with a specific prefix. The third possible parameter specifies whether you wish to see the details of each policy (includeData) or whether you wish only to receive a list of the policies themselves.

The method signature for this method is getManyPolicies(nextContinuationToken, prefix, includeData). All parameters are optional.

list-policy.ts
import { PolicyData, PolicyListResponse, PolicyDataListResponse, PolicyManagementApi, ServerConfiguration, createConfiguration } from "@privatedataservices/metronome-client";
import { explainError } from "./errors";
const clientConfig = createConfiguration( {
baseServer: new ServerConfiguration("https://the-flower-boutique.dev.eu-west-1.privatedataservices.com", {}),
authMethods: { ApiKeyAuth: process.env.METRONOME_API_KEY }
});
const pmApiClient = new PolicyManagementApi(clientConfig);
const getManyPoliciesExample = async () => {
try {
const response = await pmApiClient.getManyPolicies() as PolicyListResponse;
console.log("All known policies are: %s", response.result.join(", "));
} catch (err) {
explainError(err);
}
}
const getManyPolicyDefinitionsNoFilterExample = async () => {
try {
const response = await pmApiClient.getManyPolicies(undefined, undefined, true) as PolicyDataListResponse;
console.log("There are %d policy definitions:", response.result.length);
response.result.forEach((policy: PolicyData, index: number) => {
console.log("Policy %d has ID %s created at %s with aging strategy %s which ages by %s %s", index+1, policy.policyId, policy.createDate, policy.agingStrategy, policy.agingOffsetAmount, policy.agingOffsetUnit);
});
} catch (err) {
explainError(err);
}
}
const getManyPolicyDefinitionsWithFilterExample = async () => {
try {
const response = await pmApiClient.getManyPolicies("user-", undefined, true) as PolicyDataListResponse;
console.log("There are %d policy definitions that match the filter prefix 'user-'.", response.result.length);
response.result.forEach((policy: PolicyData, index: number) => {
console.log("Policy %d has ID %s created at %s with aging strategy %s which ages by %s %s", index+1, policy.policyId, policy.createDate, policy.agingStrategy, policy.agingOffsetAmount, policy.agingOffsetUnit);
});
} catch (err) {
explainError(err);
}
}