Skip to main content

Policies

What is a policy?

Policies define the conditions under which approval actions are granted, denied, or flagged for manual review.

  • They help ensure that approvals align with business rules, security requirements, and compliance policies.
  • By leveraging metadata, policies can evaluate real-time information to make approval decisions.

How policies are evaluated

When an action is triggered, nullplatform builds a context object containing the relevant metadata for that action — the user, scope, build, application, and so on. The policy's conditions are then evaluated against that context.

The evaluation returns one of three outcomes:

OutcomeMeaning
approveAll conditions passed. The action is auto-approved.
denyOne or more conditions failed. The action is auto-denied.
manualThe result is inconclusive and requires a human reviewer.

Which outcome is ultimately applied depends on the on_policy_success and on_policy_fail settings on the approval action linked to the policy. For example, an action with "on_policy_success": "approve" and "on_policy_fail": "manual" will auto-approve passing requests and send failing ones to a reviewer.

Using metadata in policies

Policies can leverage metadata from different entities in the catalog based on the action being evaluated. This allows for precise, context-aware approval decisions. For example, you can enforce approvals based on:

  • Code coverage in a build process.
  • The security status of a deployment.
  • Whether a resource supports auto-scaling.
  • And more.

By using metadata, policies dynamically adapt to specific requirements.

For more details, see the Catalog entity docs.

Available entities for policy configuration

The following table shows which entities provide metadata for different approval actions:

Approval actionsEntities whose metadata is available for policy configuration
deployment:createdeployment, user, scope, release, build, application, namespace, account, organization
scope:createscope, user, application, namespace, account, organization
scope:recreatescope, user, application, namespace, account, organization
scope:writescope, user, application, namespace, account, organization
scope:deletescope, user, application, namespace, account, organization
scope:stopscope, user, application, namespace, account, organization
parameter:read-secretsparameter, user, application, namespace, account, organization
service:actionuser, application, namespace, account

This means that once you've defined a policy using metadata, you can associate it with an approval action based on the entities it references.

For example, if your policy relies on scope metadata, you can link it to any approval action listed above, as scope metadata is broadly available. However, if your policy references build metadata — like in the example below — it can only be applied to a deployment:create action, since build metadata is exclusive to deployments.

Adding metadata to policies

Before using metadata in policies, you need to define a catalog specification. This outlines the structure and rules for the data you want to enforce.

For example, the following catalog specification tracks code coverage in a build entity:

{
"name": "Coverage",
"description": "Build coverage report",
"nrn": "organization=1",
"entity": "build",
"metadata": "coverage",
"schema": {
"type": "object",
"properties": {
"percent": {
"type": "number",
"default": 0,
"minimum": 80,
"maximum": 100
},
"report": {
"type": "string",
"format": "uri"
}
},
"required": ["percent", "report"],
"additionalProperties": false
}
}

See the API reference for more info on how to create a catalog specification.

Now that the specification is created, policies can reference this metadata to enforce coverage requirements before approving deployments.

Create a policy

To create a policy, send a POST request to the approval policy endpoint. The conditions object defines the rules that must be met for an approval action to proceed.

Conditions' syntax

Policies use MongoDB syntax for conditions, allowing you to create flexible and complex rules.

Example: Enforcing approval conditions for deployments

The following policy ensures that deployments are only approved if:

  • Code coverage is at least 80%.
  • Security issues do not exceed 4.
  • The resource supports auto-scaling.
  • The environment is either dev or qa.
np approval policy create
--body '{
"nrn": "organization=1:account=2:namespace=3:application=4",
"name": "Enforce coverage, security, and scaling for deployments",
"conditions": {
"build.metadata.coverage.percent": { "$gte": 80 },
"build.metadata.security.issues": { "$lte": 4 },
"scope.capabilities.auto_scaling": true,
"$or": [
{ "scope.dimensions.environment": "dev" },
{ "scope.dimensions.environment": "qa" }
]
},
"selector": {}
}'

Example: Restricting scope creation by environment

Use this pattern to require manual approval whenever a scope is created directly in production, while allowing development and staging environments to proceed automatically.

{
"nrn": "organization=1:account=2:namespace=3",
"name": "Block direct scope creation in production",
"conditions": {
"$nor": [
{ "scope.dimensions.environment": "production" }
]
},
"selector": {}
}

When combined with an approval action that has "on_policy_fail": "manual", any scope creation attempt in production is flagged for review instead of going through automatically.

Example: Restricting access to parameter secrets

This policy narrows who can read secrets by restricting access to a specific application. It's designed for use with the parameter:read-secrets action.

{
"nrn": "organization=1:account=2:namespace=3:application=4",
"name": "Require approval to read production secrets",
"conditions": {
"application.id": { "$eq": 4 }
},
"selector": {}
}

You can combine this with additional conditions — such as a metadata field on the parameter or application — to enforce more specific access rules.

Example response

If the policy is successfully created, you'll receive a response like this:

{
"id": 1234,
"nrn": "organization=1:account=2:namespace=3:application=4",
"name": "Enforce coverage, security, and scaling for deployments",
"conditions": {
"build.metadata.coverage.percent": { "$gte": 80 },
"build.metadata.security.issues": { "$lte": 4 },
"scope.capabilities.auto_scaling": true,
"$or": [
{ "scope.dimensions.environment": "dev" },
{ "scope.dimensions.environment": "qa" }
]
},
"selector": {}
}
tip

The id field contains the unique policy ID. Be sure to save it, as you'll need it in the next steps.

Using selectors

A selector narrows down which requests a policy applies to, acting as a pre-filter before the conditions are evaluated.

  • If the selector matches the context, conditions are evaluated normally.
  • If the selector doesn't match, the policy is skipped entirely for that request.

This is especially useful when multiple policies are attached to the same approval action and you want each one to apply only to a specific subset of requests — for example, targeting a particular service specification.

Using selectors for service actions

We recommend using selectors for services, as they allow you to target specific service specifications. For example:

Service action example
{
"nrn": "organization=1:account=2:namespace=3:application=4",
"name": "This service requires approval",
"conditions": {
"$or": [
{
"$and": {
"action.slug": "provision-service",
"action.parameters.endpoint_type": "private"
}
},
{
"$nor": [
{ "action.slug": "provision-service" }
]
}
]
},
"selector": { "service_specification.slug": "my-service" }
}

Updating a policy

To update a policy's conditions or selector, send a PATCH request with the fields you want to change:

curl -L -X PATCH 'https://api.nullplatform.com/approval/policy/1234' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>' \
-d '{
"conditions": {
"build.metadata.coverage.percent": { "$gte": 90 },
"scope.capabilities.auto_scaling": true
}
}'

You can update conditions, selector, or both in a single request. Fields not included in the request body remain unchanged. Changes take effect immediately for all new approval requests.

What's next

Now that you've created a policy, the next step is to link it to an approval action so it can be evaluated.

Learn how to associate a policy with an action.