diff --git a/.vale.ini b/.vale.ini
new file mode 100644
index 0000000..9acad25
--- /dev/null
+++ b/.vale.ini
@@ -0,0 +1,2 @@
+StylesPath = styles
+Vocab = Mintlify
diff --git a/config/navigation.json b/config/navigation.json
index 6c87960..08b7bd1 100644
--- a/config/navigation.json
+++ b/config/navigation.json
@@ -394,6 +394,7 @@
{
"group": "Policies",
"pages": [
+ "policy-reference/environment_policy",
"policy-reference/rego_policy"
]
}
diff --git a/config/redirects.json b/config/redirects.json
index 30c1d66..7dcadd9 100644
--- a/config/redirects.json
+++ b/config/redirects.json
@@ -11,4 +11,9 @@
"source": "/understand_kosli/concepts",
"destination": "/understand_kosli/how_kosli_works"
}
+ ,
+ {
+ "source": "/schemas/policy/v1",
+ "destination": "/schemas/policy/v1.json"
+ }
]
diff --git a/getting_started/attestations.md b/getting_started/attestations.md
index 5f2f6cf..3ce92b2 100644
--- a/getting_started/attestations.md
+++ b/getting_started/attestations.md
@@ -83,7 +83,7 @@ The following sections show how to make each of the four attestations defined in
In this case the Kosli CLI will calculate the fingerprint of the docker image called `my_company/backend:latest` and attest it as the `backend` artifact `name` in the trail.
- In all attestation commands the Kosli CLI automatically gathers the git commit and other information from the current git repository and the [CI environment](https://docs.kosli.com/integrations/ci_cd/). This is how the git commit is used to match attestations to artifacts.
+ In all attestation commands the Kosli CLI automatically gathers the git commit and other information from the current git repository and the [CI environment](/integrations/ci_cd). This is how the git commit is used to match attestations to artifacts.
diff --git a/getting_started/policies.md b/getting_started/policies.md
index 6d05f6b..a8a96fb 100644
--- a/getting_started/policies.md
+++ b/getting_started/policies.md
@@ -20,7 +20,7 @@ You can create a policy via CLI or via the API. Here is a basic policy that requ
attestations:
```yaml prod-policy.yaml
-_schema: https://kosli.com/schemas/policy/environment/v1
+_schema: https://kosli.mintlify.app/schemas/policy/v1
artifacts: # the rules apply to artifacts in an environment snapshot
provenance:
required: true # all artifacts must have provenance
@@ -47,35 +47,11 @@ See [kosli create policy](/client_reference/kosli_create_policy/) for usage deta
Once you create a policy, you will be able to see it in the UI under `policies` in the left navigation menu.
-## Declarative Policy Syntax
+## Policy rules
-A Policy is declaratively defined according to the following schema:
+A policy consists of rules which are applied to artifacts in an environment snapshot.
-```yaml
-_schema: https://kosli.com/schemas/policy/environment/v1
-
-artifacts:
- provenance:
- required: true | false (default = false)
- exceptions: (default [])
- - if: ${{ expression }}
-
- trail-compliance:
- required: true | false (default = false)
- exceptions: (default [])
- - if: ${{ expression }}
-
- attestations: (default [])
- - if: ${{ expression }} (default = true)
- name: str (default = "*") # cannot have both name and type as *
- type: oneOf ['*', 'junit', 'jira', 'pull_request', 'snyk', 'sonar', 'generic', 'custom:'] (default = "*") # cannot have both name and type as *
-```
-
-### Policy Rules
-
-A policy consists of `rules` which are applied to artifacts in an environment snapshot.
-
-#### Provenance
+### Provenance
When `provenance` is set to `required: true`, the artifact must be part of a Kosli Flow (i.e., it must have
provenance information).
@@ -86,7 +62,7 @@ artifacts:
required: true
```
-#### Trail Compliance
+### Trail compliance
When `trail-compliance` is set to `required: true`, the artifact must be part of a compliant Trail in its Flow.
@@ -96,7 +72,7 @@ artifacts:
required: true
```
-#### Specific Attestations
+### Specific attestations
```yaml
artifacts:
@@ -111,92 +87,33 @@ artifacts:
type: custom:my-coverage-metrics # custom attestation type
```
-### Policy Rules Exceptions
+### Exceptions
-You can add exceptions to policy rules using expressions.
+You can add exceptions to policy rules using [policy expressions](/policy-reference/environment_policy#policy-expressions).
```yaml
-_schema: https://kosli.com/schemas/policy/environment/v1
+_schema: https://kosli.mintlify.app/schemas/policy/v1
artifacts:
provenance:
required: true
exceptions:
# provenance is required except when one of the expressions evaluates to true
- - if: ${{ expression1 }}
- - if: ${{ expression2 }}
+ - if: ${{ matches(artifact.name, "^datadog:.*") }}
trail-compliance:
required: true
exceptions:
- # trail-compliance is required except when one of the expressions evaluates to true
- - if: ${{ expression1 }}
- - if: ${{ expression2 }}
+ - if: ${{ matches(artifact.name, "^datadog:.*") }}
attestations:
- - if: ${{ expression }} # this attestation is only required when expression evaluates to true
+ - if: ${{ flow.tags.risk-level == "high" }} # only required when expression is true
name: unit-tests
type: junit
```
-#### Policy Expressions
-
-Policy expressions allow you to create conditional rules using a simple and powerful syntax. Expressions are wrapped
-in `${{ }}` and can be used in policy rules to create dynamic conditions. An expression consists of operands
-and operators:
-
-
-
-
- Expressions support these operators:
-
- - Comparison: `==, !=, <, >, <=, >=`
- - Logical: `and, or, not`
- - List membership: `in`
-
-
-
- Operands can be:
- - Literal string
- - List
- - Context variable
- - Function call
-
-
-
- Contexts are built-in objects which are accessible from an expression. Expressions can access two main contexts:
-
- - `flow` - Information about the Kosli Flow:
- - `flow.name` - Name of the flow
- - `flow.tags` - Flow tags (accessed via flow.tags.tag_name)
- - `artifact` - Information about the artifact:
- - `artifact.name` - Name of the artifact
- - `artifact.fingerprint` - SHA256 fingerprint
-
-
-
- Functions are helpers that can be used when constructing conditions. They may or may not accept arguments. Arguments
- can be literals or context variables. Expressions can use following functions:
-
- - `exists(arg)` : checks whether the value of arg is not None/Null
- - `matches(input, regex)` : checks if input matches regex
-
-
-
- - `${{ exists(flow) }}`
- - `${{ flow.name in ["runner", 'saver', differ] }}`
- - `${{ matches(artifact.name, "^datadog:.*") }}`
- - `${{ flow.name == "runner" and matches(artifact.name, "^runner:.*") }}`
- - `${{ flow.tags.risk-level == "high" or matches(artifact.name, "^runner:.*") }}`
- - `${{ not flow.tags.risk-level == "high"}}`
- - `${{ flow.tags.risk-level != "high"}}`
- - `${{ flow.tags.key.with.dots == "value"}}`
- - `${{ flow.tags.risk-level >= 2 }}`
- - `${{ flow.name == 'prod' and (flow.tags.key_name == "value" or artifact.name == 'critical-service') }}`
- - `${{ flow.name == 'HIGH-RISK' and artifact.fingerprint == "37193ba1f3da2581e93ff1a9bba523241a7982a6c01dd311494b0aff6d349462" }}`
-
-
-
+For the complete YAML specification — fields, types, defaults, expression language, and constraints — see the [Environment Policy reference](/policy-reference/environment_policy).
+
## Attaching/Detaching Policies to/from Environments
Once you define your policies, you can attach them to environments via CLI or API:
diff --git a/labs/lab-05-runtime-controls.mdx b/labs/lab-05-runtime-controls.mdx
index 509dc82..a79f608 100644
--- a/labs/lab-05-runtime-controls.mdx
+++ b/labs/lab-05-runtime-controls.mdx
@@ -95,7 +95,7 @@ See [Environments](/getting_started/environments) for more.
Create `.kosli-policy.yml` in the root of your repository:
```yaml
- _schema: https://kosli.com/schemas/policy/environment/v1
+ _schema: https://kosli.mintlify.app/schemas/policy/v1
artifacts:
provenance:
@@ -203,7 +203,7 @@ See [Environments](/getting_started/environments) for more.
- if: ${{ artifact.name == "legacy-component" }}
```
- See [Policy expressions](/getting_started/policies) for more.
+ See [Policy expressions](/policy-reference/environment_policy#policy-expressions) for more.
## Verification checklist
diff --git a/policy-reference/environment_policy.mdx b/policy-reference/environment_policy.mdx
new file mode 100644
index 0000000..9121ae9
--- /dev/null
+++ b/policy-reference/environment_policy.mdx
@@ -0,0 +1,197 @@
+---
+title: "Environment Policy"
+description: "Reference for the YAML policy files used to define compliance requirements for Kosli environments."
+---
+
+An environment policy is a YAML file that declares compliance requirements for artifacts running in a Kosli environment. You pass the file to [`kosli create policy`](/client_reference/kosli_create_policy) to create or update a policy. For concepts, workflow, and enforcement, see [Environment Policies](/getting_started/policies).
+
+## Specification
+
+
+ Version identifier and [JSON Schema](https://kosli.mintlify.app/schemas/policy/v1.json) URL for the policy format. The final path segment must match `/v{n}` where `n` is a supported major version. Currently only `v1` is supported.
+
+ ```yaml
+ # yaml-language-server: $schema=https://kosli.mintlify.app/schemas/policy/v1.json
+ _schema: https://kosli.mintlify.app/schemas/policy/v1
+ ```
+
+
+
+ Rules applied to artifacts in an environment snapshot. Omitted keys use server defaults.
+
+
+
+ Requires artifacts to have provenance (i.e., be part of a Kosli flow).
+
+
+
+ When `true`, every artifact in the snapshot must have provenance.
+
+
+
+ List of conditions under which the provenance requirement is waived. Each element is an object with a single `if` key containing a [policy expression](#policy-expressions).
+
+ ```yaml
+ exceptions:
+ - if: ${{ matches(artifact.name, "^datadog:.*") }}
+ ```
+
+
+
+
+
+ Requires artifacts to belong to a compliant trail in their flow.
+
+
+
+ When `true`, every artifact must be part of a compliant trail.
+
+
+
+ List of conditions under which the trail-compliance requirement is waived. Same structure as `provenance.exceptions`.
+
+
+
+
+
+ List of attestations every artifact must have. Each element is a required-attestation rule.
+
+
+
+ The [attestation type](#attestation-types) to require. Cannot be `*` when `name` is also `*`.
+
+
+
+ Attestation name to match. `*` matches any name. Cannot be `*` when `type` is also `*`.
+
+
+
+ A [policy expression](#policy-expressions). When present, this attestation is only required when the expression evaluates to `true`.
+
+
+
+
+
+
+## Attestation types
+
+| Value | Description |
+|-------|-------------|
+| `generic` | Generic attestation |
+| `junit` | JUnit test results |
+| `snyk` | Snyk security scan |
+| `pull_request` | Pull request evidence |
+| `jira` | Jira ticket reference |
+| `sonar` | SonarQube analysis |
+| `*` | Matches any built-in or custom type |
+| `custom:` | A [custom attestation type](/client_reference/kosli_create_attestation-type) (e.g., `custom:coverage-metrics`) |
+
+## Policy expressions
+
+Expressions are boolean conditions evaluated against flow and artifact context. They are wrapped in `${{ }}` and can appear in `if` and `exceptions[].if` fields.
+
+```yaml
+if: ${{ flow.tags.risk-level == "high" and matches(artifact.name, "^prod:.*") }}
+```
+
+### Operators
+
+| Operator | Category | Example |
+|----------|----------|---------|
+| `==` | Comparison | `flow.name == "runner"` |
+| `!=` | Comparison | `flow.tags.risk-level != "high"` |
+| `<` | Comparison | `flow.tags.priority < 3` |
+| `>` | Comparison | `flow.tags.priority > 1` |
+| `<=` | Comparison | `flow.tags.risk-level <= 2` |
+| `>=` | Comparison | `flow.tags.risk-level >= 2` |
+| `and` | Logical | `flow.name == "a" and artifact.name == "b"` |
+| `or` | Logical | `flow.name == "a" or flow.name == "b"` |
+| `not` | Logical | `not flow.tags.risk-level == "high"` |
+| `in` | Membership | `flow.name in ["runner", "saver"]` |
+
+Parentheses control precedence: `${{ flow.name == 'prod' and (flow.tags.team == "a" or artifact.name == 'svc') }}`.
+
+### Contexts
+
+
+ Information about the Kosli flow the artifact belongs to.
+
+
+
+ Name of the flow.
+
+
+
+ Flow tags, accessed by key: `flow.tags.risk-level`, `flow.tags.team`. Keys containing dots are supported: `flow.tags.key.with.dots`.
+
+
+
+
+
+ Information about the artifact being evaluated.
+
+
+
+ Name of the artifact.
+
+
+
+ SHA256 fingerprint of the artifact.
+
+
+
+
+### Functions
+
+| Function | Description | Example |
+|----------|-------------|---------|
+| `exists(arg)` | Returns `true` if `arg` is not null. | `${{ exists(flow) }}` |
+| `matches(input, regex)` | Returns `true` if `input` matches the regular expression. | `${{ matches(artifact.name, "^datadog:.*") }}` |
+
+## Constraints
+
+- `_schema` is the only required field. All other fields are optional and use server defaults when omitted.
+- An attestation rule must not have both `name` and `type` set to `*`.
+- Expressions must evaluate to a boolean. An invalid expression causes a policy evaluation error.
+
+## Example
+
+```yaml
+# yaml-language-server: $schema=https://kosli.mintlify.app/schemas/policy/v1.json
+_schema: https://kosli.mintlify.app/schemas/policy/v1
+
+artifacts:
+ provenance:
+ required: true
+ exceptions:
+ - if: ${{ matches(artifact.name, "^datadog:.*") }}
+
+ trail-compliance:
+ required: true
+
+ attestations:
+ - name: security-scan
+ type: snyk
+ - name: pull-request
+ type: pull_request
+ if: ${{ flow.tags.risk-level == "high" }}
+ - name: coverage
+ type: custom:coverage-metrics
+```
+
+## Editor validation
+
+The `_schema` URL resolves to a [JSON Schema](https://kosli.mintlify.app/schemas/policy/v1.json) for the environment policy format. To enable inline validation and autocomplete in VS Code (requires the [YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)) and other schema-aware editors, add a `yaml-language-server` directive:
+
+```yaml
+# yaml-language-server: $schema=https://kosli.mintlify.app/schemas/policy/v1.json
+_schema: https://kosli.mintlify.app/schemas/policy/v1
+```
+
+## See also
+
+- [Environment Policies](/getting_started/policies) — concepts, workflow, and enforcement
+- [`kosli create policy`](/client_reference/kosli_create_policy) — create or update a policy
+- [`kosli attach-policy`](/client_reference/kosli_attach-policy) — attach a policy to an environment
+- [`kosli assert artifact`](/client_reference/kosli_assert_artifact) — enforce policies on an artifact
+- [Terraform: kosli_policy](/terraform-reference/resources/policy) — manage policies via Terraform
diff --git a/schemas/policy/v1.json b/schemas/policy/v1.json
new file mode 100644
index 0000000..2bde12b
--- /dev/null
+++ b/schemas/policy/v1.json
@@ -0,0 +1,92 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://kosli.mintlify.app/schemas/policy/v1",
+ "title": "Kosli Environment Policy",
+ "description": "Schema for Kosli environment policy YAML files used with `kosli create policy`.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["_schema"],
+ "properties": {
+ "_schema": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL of this schema. The path must end with /v{n} where n is the major version (e.g. .../v1). Example: https://kosli.mintlify.app/schemas/policy/v1"
+ },
+ "artifacts": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Rules for artifacts in an environment snapshot. Omitted keys use server defaults (provenance/trail-compliance: required false, empty exceptions; attestations: []).",
+ "properties": {
+ "provenance": { "$ref": "#/definitions/booleanRule" },
+ "trail-compliance": { "$ref": "#/definitions/booleanRule" },
+ "attestations": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/requiredAttestationRule" }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "policyExpression": {
+ "description": "Boolean expression evaluated against flow/artifact context. In YAML this is often written as a string wrapped in ${{ ... }}.",
+ "type": "string"
+ },
+ "conditionalRule": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "if": { "$ref": "#/definitions/policyExpression" }
+ }
+ },
+ "booleanRule": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "required": {
+ "type": "boolean",
+ "default": false
+ },
+ "exceptions": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/conditionalRule" },
+ "default": []
+ }
+ }
+ },
+ "attestationType": {
+ "description": "Built-in attestation type, custom:... reference, or wildcard *.",
+ "oneOf": [
+ {
+ "type": "string",
+ "enum": [
+ "generic",
+ "junit",
+ "snyk",
+ "pull_request",
+ "jira",
+ "sonar",
+ "*"
+ ]
+ },
+ {
+ "type": "string",
+ "pattern": "^custom:.+"
+ }
+ ]
+ },
+ "requiredAttestationRule": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "default": "*",
+ "description": "Attestation name; default * matches any."
+ },
+ "type": { "$ref": "#/definitions/attestationType" },
+ "if": { "$ref": "#/definitions/policyExpression" }
+ },
+ "required": ["type"]
+ }
+ }
+}
\ No newline at end of file
diff --git a/terraform-reference/resources/policy.mdx b/terraform-reference/resources/policy.mdx
index b4c1c56..5efecd2 100644
--- a/terraform-reference/resources/policy.mdx
+++ b/terraform-reference/resources/policy.mdx
@@ -27,7 +27,7 @@ terraform {
resource "kosli_policy" "minimal" {
name = "basic-requirements"
content = <<-YAML
- _schema: https://kosli.com/schemas/policy/environment/v1
+ _schema: https://kosli.mintlify.app/schemas/policy/v1
artifacts:
provenance:
required: true
@@ -39,7 +39,7 @@ resource "kosli_policy" "production" {
name = "prod-requirements"
description = "Compliance requirements for production environments"
content = <<-YAML
- _schema: https://kosli.com/schemas/policy/environment/v1
+ _schema: https://kosli.mintlify.app/schemas/policy/v1
artifacts:
provenance:
required: true
@@ -67,7 +67,7 @@ terraform import kosli_policy.example prod-requirements
### Required
-- `content` (String) YAML content of the policy, conforming to the Kosli policy schema (`_schema: https://kosli.com/schemas/policy/environment/v1`). Supports heredoc syntax for multi-line YAML. Updating this value creates a new policy version.
+- `content` (String) YAML content of the policy, conforming to the Kosli policy schema (`_schema: https://kosli.mintlify.app/schemas/policy/v1`). Supports heredoc syntax for multi-line YAML. Updating this value creates a new policy version.
- `name` (String) Name of the policy. Must be unique within the organization. Changing this will force recreation of the resource.
### Optional