diff --git a/administration/managing_custom_attestation_types/overview.md b/administration/managing_custom_attestation_types/overview.md
new file mode 100644
index 0000000..08c7c08
--- /dev/null
+++ b/administration/managing_custom_attestation_types/overview.md
@@ -0,0 +1,99 @@
+---
+title: Managing Custom Attestation Types
+description: Learn how to manage Kosli custom attestation types via Terraform, including creating and importing types with JSON Schema and jq evaluation rules.
+---
+
+The preferred way to manage custom attestation types is via the Kosli Terraform provider, so your Kosli configuration is version-controlled alongside your infrastructure. You can also manage custom attestation types through the Kosli CLI.
+
+
+This page covers managing custom attestation types via Terraform. For an introduction to custom attestation types and creating them via the CLI, see [Getting started: Attestations](/getting_started/attestations).
+
+
+Custom attestation types define how Kosli validates evidence from tools that don't have a built-in Kosli attestation command. Each type can include:
+
+- A **JSON Schema** (optional) that defines the expected structure of attestation data
+- **jq rules** (optional) that evaluate the data to determine compliance
+
+At least one of the two must be provided.
+
+## Create a custom attestation type
+
+### With schema and jq rules
+
+```hcl
+resource "kosli_custom_attestation_type" "security_scan" {
+ name = "security-scan"
+ description = "Validates security scan results"
+
+ schema = jsonencode({
+ type = "object"
+ properties = {
+ critical_vulnerabilities = { type = "integer" }
+ high_vulnerabilities = { type = "integer" }
+ scan_date = { type = "string" }
+ }
+ required = ["critical_vulnerabilities", "high_vulnerabilities", "scan_date"]
+ })
+
+ jq_rules = [
+ ".critical_vulnerabilities == 0",
+ ".high_vulnerabilities < 5"
+ ]
+}
+```
+
+### With jq rules only
+
+```hcl
+resource "kosli_custom_attestation_type" "code_coverage" {
+ name = "code-coverage"
+ description = "Requires at least 80% line coverage"
+
+ jq_rules = [".line_coverage >= 80"]
+}
+```
+
+### With schema only
+
+```hcl
+resource "kosli_custom_attestation_type" "deployment_record" {
+ name = "deployment-record"
+ description = "Validates deployment record structure"
+
+ schema = jsonencode({
+ type = "object"
+ properties = {
+ deployed_by = { type = "string" }
+ deployed_at = { type = "string" }
+ environment = { type = "string" }
+ }
+ required = ["deployed_by", "deployed_at", "environment"]
+ })
+}
+```
+
+## Import an existing custom attestation type
+
+If you have custom attestation types created via the CLI, you can bring them under Terraform management by importing them into your Terraform state.
+
+1. Find the attestation type name in the Kosli UI or run:
+
+```shell
+kosli list attestation-types
+```
+
+2. Add a matching `kosli_custom_attestation_type` resource block to your configuration.
+
+3. Run the import:
+
+```shell
+terraform import kosli_custom_attestation_type.security_scan security-scan
+```
+
+4. Verify with `terraform plan` — no changes should be planned if the import succeeded.
+
+## Reference
+
+- [`kosli_custom_attestation_type` resource](/terraform-reference/resources/custom_attestation_type)
+- [`kosli_custom_attestation_type` data source](/terraform-reference/data-sources/custom_attestation_type)
+- [Kosli Terraform provider on the Terraform Registry](https://registry.terraform.io/providers/kosli-dev/kosli/latest)
diff --git a/administration/managing_environments/overview.md b/administration/managing_environments/overview.md
index e131162..5727f0b 100644
--- a/administration/managing_environments/overview.md
+++ b/administration/managing_environments/overview.md
@@ -107,7 +107,7 @@ terraform import kosli_logical_environment.production_all production-all
## Reference
-- [`kosli_environment` resource](https://registry.terraform.io/providers/kosli-dev/kosli/latest/docs/resources/environment)
-- [`kosli_environment` data source](https://registry.terraform.io/providers/kosli-dev/kosli/latest/docs/data-sources/environment)
-- [`kosli_logical_environment` resource](https://registry.terraform.io/providers/kosli-dev/kosli/latest/docs/resources/logical_environment)
-- [`kosli_logical_environment` data source](https://registry.terraform.io/providers/kosli-dev/kosli/latest/docs/data-sources/logical_environment)
+- [`kosli_environment` resource](/terraform-reference/resources/environment)
+- [`kosli_environment` data source](/terraform-reference/data-sources/environment)
+- [`kosli_logical_environment` resource](/terraform-reference/resources/logical_environment)
+- [`kosli_logical_environment` data source](/terraform-reference/data-sources/logical_environment)
diff --git a/docs.json b/docs.json
index 7cb9d4f..d0254bb 100644
--- a/docs.json
+++ b/docs.json
@@ -84,6 +84,12 @@
"pages": [
"administration/managing_environments/overview"
]
+ },
+ {
+ "group": "Managing Custom Attestation Types",
+ "pages": [
+ "administration/managing_custom_attestation_types/overview"
+ ]
}
]
},
@@ -408,6 +414,34 @@
]
}
]
+ },
+ {
+ "item": "Terraform Reference",
+ "icon": "cubes",
+ "groups": [
+ {
+ "group": "Provider",
+ "pages": [
+ "terraform-reference/index"
+ ]
+ },
+ {
+ "group": "Resources",
+ "pages": [
+ "terraform-reference/resources/environment",
+ "terraform-reference/resources/logical_environment",
+ "terraform-reference/resources/custom_attestation_type"
+ ]
+ },
+ {
+ "group": "Data Sources",
+ "pages": [
+ "terraform-reference/data-sources/environment",
+ "terraform-reference/data-sources/logical_environment",
+ "terraform-reference/data-sources/custom_attestation_type"
+ ]
+ }
+ ]
}
]
},
diff --git a/terraform-reference/data-sources/custom_attestation_type.mdx b/terraform-reference/data-sources/custom_attestation_type.mdx
new file mode 100644
index 0000000..c0a810b
--- /dev/null
+++ b/terraform-reference/data-sources/custom_attestation_type.mdx
@@ -0,0 +1,81 @@
+---
+title: "kosli_custom_attestation_type data source"
+description: "Fetches details of an existing custom attestation type from Kosli. Custom attestation types define how Kosli validates and evaluates evidence from proprietary tools, custom metrics, or specialized compliance requirements."
+icon: "database"
+---
+
+Fetches details of an existing custom attestation type from Kosli. Custom attestation types define how Kosli validates and evaluates evidence from proprietary tools, custom metrics, or specialized compliance requirements.
+
+Use this data source to retrieve information about an existing custom attestation type. This is useful for:
+
+- Referencing existing attestation types in other configurations
+- Creating variants of existing types with modified rules
+- Querying attestation type metadata and schemas
+
+## Example usage
+
+```terraform
+terraform {
+ required_providers {
+ kosli = {
+ source = "kosli-dev/kosli"
+ }
+ }
+}
+
+# Query an existing custom attestation type
+data "kosli_custom_attestation_type" "security" {
+ name = "security-scan"
+}
+
+# Use the queried schema in a new attestation type
+resource "kosli_custom_attestation_type" "security_strict" {
+ name = "security-scan-strict"
+ description = "Stricter security requirements"
+
+ # Reuse the schema from the existing type
+ schema = data.kosli_custom_attestation_type.security.schema
+
+ # Apply stricter validation rules
+ jq_rules = [
+ ".critical_vulnerabilities == 0",
+ ".high_vulnerabilities == 0",
+ ".medium_vulnerabilities < 3"
+ ]
+}
+
+# Reference attestation type metadata
+output "security_scan_description" {
+ description = "Description of the security scan attestation type"
+ value = data.kosli_custom_attestation_type.security.description
+}
+
+output "security_scan_rules" {
+ description = "JQ rules for the security scan attestation type"
+ value = data.kosli_custom_attestation_type.security.jq_rules
+}
+
+output "security_scan_archived" {
+ description = "Whether the security scan attestation type is archived"
+ value = data.kosli_custom_attestation_type.security.archived
+}
+```
+
+## Querying archived types
+
+By default, the data source retrieves active (non-archived) attestation types. Archived types can be queried but are read-only and typically represent historical configurations.
+
+The `archived` attribute indicates whether an attestation type has been deleted/archived in Kosli. Archived types cannot be modified through Terraform.
+
+## Schema
+
+### Required
+
+- `name` (String) The name of the custom attestation type. Must start with a letter or number and contain only letters, numbers, periods, hyphens, underscores, and tildes.
+
+### Read-only
+
+- `archived` (Boolean) Whether this attestation type has been archived.
+- `description` (String) A description of what this attestation type validates.
+- `jq_rules` (List of String) List of jq expressions that define evaluation rules. All rules must evaluate to `true` for compliance.
+- `schema` (String) JSON Schema that defines the structure of attestation data.
diff --git a/terraform-reference/data-sources/environment.mdx b/terraform-reference/data-sources/environment.mdx
new file mode 100644
index 0000000..8b0eb41
--- /dev/null
+++ b/terraform-reference/data-sources/environment.mdx
@@ -0,0 +1,102 @@
+---
+title: "kosli_environment data source"
+description: "Fetches details of an existing Kosli environment. Use this data source to reference environments and access metadata like last modified and last reported timestamps."
+icon: "database"
+---
+
+Fetches details of an existing Kosli environment. Use this data source to reference environments and access metadata like last modified and last reported timestamps.
+
+Environments represent runtime locations where artifacts are deployed and tracked for compliance monitoring. Use this data source to:
+
+- Reference existing environment configurations in other resources
+- Monitor environment activity (last modified, last reported timestamps)
+- Create conditional logic based on environment state
+- Build alerts and notifications based on environment metadata
+
+## Example usage
+
+```terraform
+terraform {
+ required_providers {
+ kosli = {
+ source = "kosli-dev/kosli"
+ }
+ }
+}
+
+# Query an existing environment
+data "kosli_environment" "production" {
+ name = "production-k8s"
+}
+
+# Use the data source to create a similar environment
+resource "kosli_environment" "staging" {
+ name = "staging-k8s"
+ type = data.kosli_environment.production.type
+ description = "Staging environment similar to ${data.kosli_environment.production.name}"
+}
+
+# Reference environment metadata for monitoring
+output "production_last_modified" {
+ description = "Timestamp of when production environment was last modified"
+ value = data.kosli_environment.production.last_modified_at
+}
+
+output "production_last_reported" {
+ description = "Timestamp of when production environment last reported a snapshot"
+ value = data.kosli_environment.production.last_reported_at
+}
+
+output "production_type" {
+ description = "Type of the production environment"
+ value = data.kosli_environment.production.type
+}
+
+output "production_includes_scaling" {
+ description = "Whether production environment includes scaling events"
+ value = data.kosli_environment.production.include_scaling
+}
+
+# Conditional logic based on environment metadata
+locals {
+ # Check if environment has never reported a snapshot
+ needs_attention = data.kosli_environment.production.last_reported_at == null
+}
+
+output "production_needs_attention" {
+ description = "Whether production environment needs attention (never reported)"
+ value = local.needs_attention
+}
+```
+
+## Monitoring with data sources
+
+The data source exposes timestamp fields that are useful for monitoring:
+
+- `last_modified_at`: Unix timestamp of when the environment configuration was last changed
+- `last_reported_at`: Unix timestamp of when the environment last reported a snapshot (can be null if never reported)
+
+These timestamps enable you to:
+
+- Create alerts for environments that haven't reported in a certain time period
+- Track configuration changes across your infrastructure
+- Build dashboards showing environment activity
+- Implement conditional deployment logic based on environment state
+
+## Read-only access
+
+Data sources provide read-only access to environment metadata. To modify environment configurations, use the [`kosli_environment` resource](/terraform-reference/resources/environment).
+
+## Schema
+
+### Required
+
+- `name` (String) The name of the environment to query.
+
+### Read-only
+
+- `description` (String) The description of the environment.
+- `include_scaling` (Boolean) Whether the environment includes scaling events in snapshots.
+- `last_modified_at` (Number) Unix timestamp (with fractional seconds) of when the environment was last modified.
+- `last_reported_at` (Number) Unix timestamp (with fractional seconds) of when the environment was last reported. May be null if never reported.
+- `type` (String) The environment type (e.g., K8S, ECS, S3, docker, server, lambda).
diff --git a/terraform-reference/data-sources/logical_environment.mdx b/terraform-reference/data-sources/logical_environment.mdx
new file mode 100644
index 0000000..6eb01ba
--- /dev/null
+++ b/terraform-reference/data-sources/logical_environment.mdx
@@ -0,0 +1,186 @@
+---
+title: "kosli_logical_environment data source"
+description: "Fetches details of an existing Kosli logical environment. Use this data source to reference logical environments and access their aggregated physical environments."
+icon: "database"
+---
+
+Fetches details of an existing Kosli logical environment. Use this data source to reference logical environments and access their aggregated physical environments.
+
+Use this data source to query existing logical environments in Kosli. This is useful for:
+
+- **Referencing metadata**: Access `last_modified_at` timestamps and other computed attributes
+- **Cross-stack references**: Reference logical environments created outside Terraform
+- **Dynamic configuration**: Use existing logical environment configurations to create variants
+- **Validation**: Verify logical environments exist before referencing them
+- **Monitoring**: Create conditional logic based on logical environment state
+
+## Example usage
+
+```terraform
+terraform {
+ required_providers {
+ kosli = {
+ source = "kosli-dev/kosli"
+ }
+ }
+}
+
+# Query an existing logical environment
+data "kosli_logical_environment" "production" {
+ name = "production-aggregate"
+}
+
+# Use the data source to create a similar logical environment
+resource "kosli_logical_environment" "staging" {
+ name = "staging-aggregate"
+ description = "Staging version of ${data.kosli_logical_environment.production.name}"
+ included_environments = data.kosli_logical_environment.production.included_environments
+}
+
+# Reference logical environment metadata
+output "production_name" {
+ description = "Name of the production logical environment"
+ value = data.kosli_logical_environment.production.name
+}
+
+output "production_type" {
+ description = "Type of the environment (should be 'logical')"
+ value = data.kosli_logical_environment.production.type
+}
+
+output "production_description" {
+ description = "Description of the production logical environment"
+ value = data.kosli_logical_environment.production.description
+}
+
+output "production_environments" {
+ description = "List of physical environments included in production aggregate"
+ value = data.kosli_logical_environment.production.included_environments
+}
+
+output "production_last_modified" {
+ description = "Timestamp of when production logical environment was last modified"
+ value = data.kosli_logical_environment.production.last_modified_at
+}
+
+# Count how many environments are aggregated
+output "production_environment_count" {
+ description = "Number of environments aggregated in production"
+ value = length(data.kosli_logical_environment.production.included_environments)
+}
+
+# Conditional logic based on aggregation
+locals {
+ # Check if logical environment is empty (no included environments)
+ is_empty = length(data.kosli_logical_environment.production.included_environments) == 0
+
+ # Check if it includes a specific environment
+ includes_k8s = contains(
+ data.kosli_logical_environment.production.included_environments,
+ "production-k8s"
+ )
+}
+
+output "production_is_empty" {
+ description = "Whether production logical environment has no included environments"
+ value = local.is_empty
+}
+
+output "production_includes_k8s" {
+ description = "Whether production aggregates a K8S environment"
+ value = local.includes_k8s
+}
+```
+
+## Type validation
+
+
+This data source validates that the queried environment is of type `logical`. Attempting to query a physical environment will result in an error. Use the [`kosli_environment` data source](/terraform-reference/data-sources/environment) for physical environments instead.
+
+
+## Use cases
+
+### Reference metadata
+
+Query logical environment metadata for monitoring or conditional logic:
+
+```terraform
+data "kosli_logical_environment" "production" {
+ name = "production-all"
+}
+
+output "production_last_modified" {
+ value = data.kosli_logical_environment.production.last_modified_at
+}
+
+output "production_environment_count" {
+ value = length(data.kosli_logical_environment.production.included_environments)
+}
+```
+
+### Create variants
+
+Use an existing logical environment as a template for creating similar ones:
+
+```terraform
+data "kosli_logical_environment" "production" {
+ name = "production-all"
+}
+
+resource "kosli_logical_environment" "staging" {
+ name = "staging-all"
+ description = "Staging version of ${data.kosli_logical_environment.production.name}"
+
+ # Reuse the same environment structure
+ included_environments = data.kosli_logical_environment.production.included_environments
+}
+```
+
+### Cross-stack references
+
+Reference logical environments created in other Terraform workspaces or outside Terraform:
+
+```terraform
+data "kosli_logical_environment" "shared_production" {
+ name = "production-all" # Created in infrastructure workspace
+}
+
+# Use in application deployment workspace
+locals {
+ production_environments = data.kosli_logical_environment.shared_production.included_environments
+}
+```
+
+### Conditional logic
+
+Create conditional logic based on logical environment configuration:
+
+```terraform
+data "kosli_logical_environment" "production" {
+ name = "production-all"
+}
+
+locals {
+ # Check if environment is empty
+ is_empty = length(data.kosli_logical_environment.production.included_environments) == 0
+
+ # Check if it includes a specific environment
+ includes_k8s = contains(
+ data.kosli_logical_environment.production.included_environments,
+ "production-k8s"
+ )
+}
+```
+
+## Schema
+
+### Required
+
+- `name` (String) The name of the logical environment to query.
+
+### Read-only
+
+- `description` (String) The description of the logical environment.
+- `included_environments` (List of String) List of physical environment names aggregated by this logical environment.
+- `last_modified_at` (Number) Unix timestamp (with fractional seconds) of when the logical environment was last modified.
+- `type` (String) The environment type (always `logical` for logical environments).
diff --git a/terraform-reference/index.mdx b/terraform-reference/index.mdx
new file mode 100644
index 0000000..3afe84c
--- /dev/null
+++ b/terraform-reference/index.mdx
@@ -0,0 +1,73 @@
+---
+title: "Kosli Terraform Provider"
+description: "Manage Kosli resources as Infrastructure-as-Code using Terraform."
+icon: "layer-group"
+---
+
+The Kosli provider allows you to manage Kosli resources as Infrastructure-as-Code using Terraform. Use it to define and manage custom attestation types and integrate Kosli into your compliance workflows. The provider is officially registered at the [Terraform Registry](https://registry.terraform.io/providers/kosli-dev/kosli/latest).
+
+## Requirements
+
+- Terraform >= 1.8
+- A Kosli account with API credentials
+
+## Example usage
+
+```terraform
+terraform {
+ required_providers {
+ kosli = {
+ source = "kosli-dev/kosli"
+ }
+ }
+}
+
+# Configure the Kosli Provider
+# Authentication via environment variables (recommended)
+provider "kosli" {
+ # API token - set via KOSLI_API_TOKEN environment variable
+ # Organization name - set via KOSLI_ORG environment variable
+
+ # Optional: API endpoint URL (defaults to https://app.kosli.com)
+ # api_url = "https://app.us.kosli.com" # Use US region
+
+ # Optional: HTTP client timeout in seconds (defaults to 30)
+ # timeout = 60
+}
+```
+
+## Authentication
+
+The provider requires a Kosli API token and organization name for authentication. These can be configured in two ways (in order of precedence):
+
+1. **Provider configuration** - Set directly in your Terraform configuration
+2. **Environment variables** - Use `KOSLI_API_TOKEN` and `KOSLI_ORG`
+
+### Creating an API token
+
+To create an API token:
+
+1. Log in to [Kosli](https://app.kosli.com)
+2. Navigate to **Settings** → **API Tokens**
+3. Click **Create Token**
+4. Copy the token and store it securely
+
+
+API tokens grant full access to your Kosli organization. Store them securely and never commit them to version control.
+
+
+## Regional endpoints
+
+Kosli operates in multiple regions. Configure the `api_url` to match your organization's region:
+
+- **EU (Default)**: `https://app.kosli.com`
+- **US**: `https://app.us.kosli.com`
+
+## Schema
+
+### Optional
+
+- `api_token` (String, Sensitive) Kosli API token for authentication. Can also be set via KOSLI_API_TOKEN environment variable.
+- `api_url` (String) Kosli API endpoint URL. Defaults to https://app.kosli.com (EU region). Use https://app.us.kosli.com for US region. Can also be set via KOSLI_API_URL environment variable.
+- `org` (String) Kosli organization name. Can also be set via KOSLI_ORG environment variable.
+- `timeout` (Number) HTTP client timeout in seconds. Defaults to 30 seconds.
diff --git a/terraform-reference/resources/custom_attestation_type.mdx b/terraform-reference/resources/custom_attestation_type.mdx
new file mode 100644
index 0000000..0465cd4
--- /dev/null
+++ b/terraform-reference/resources/custom_attestation_type.mdx
@@ -0,0 +1,163 @@
+---
+title: "kosli_custom_attestation_type resource"
+description: "Manages a custom attestation type in Kosli. Custom attestation types define how Kosli validates and evaluates evidence from proprietary tools, custom metrics, or specialized compliance requirements."
+icon: "cube"
+---
+
+Manages a custom attestation type in Kosli. Custom attestation types define how Kosli validates and evaluates evidence from proprietary tools, custom metrics, or specialized compliance requirements.
+
+Custom attestation types define the structure and validation rules for attestations in Kosli. They can include:
+
+- A JSON Schema (optional) that defines the expected structure of attestation data
+- JQ rules (optional) that evaluate the attestation data for compliance
+
+**Note**: While both `schema` and `jq_rules` are optional attributes in Terraform, the Kosli API requires at least one of them to be provided when creating or updating a custom attestation type.
+
+## Example usage
+
+```terraform
+terraform {
+ required_providers {
+ kosli = {
+ source = "kosli-dev/kosli"
+ }
+ }
+}
+
+# Security scan attestation type
+resource "kosli_custom_attestation_type" "security_scan" {
+ name = "security-scan"
+ description = "Validates security scan results"
+
+ schema = jsonencode({
+ type = "object"
+ properties = {
+ critical_vulnerabilities = { type = "integer" }
+ high_vulnerabilities = { type = "integer" }
+ medium_vulnerabilities = { type = "integer" }
+ scan_date = { type = "string" }
+ scanner_version = { type = "string" }
+ }
+ required = ["critical_vulnerabilities", "high_vulnerabilities", "scan_date"]
+ })
+
+ jq_rules = [
+ ".critical_vulnerabilities == 0",
+ ".high_vulnerabilities < 5"
+ ]
+}
+
+# Code coverage attestation type
+resource "kosli_custom_attestation_type" "code_coverage" {
+ name = "code-coverage"
+ description = "Validates code coverage metrics"
+
+ schema = jsonencode({
+ type = "object"
+ properties = {
+ line_coverage = {
+ type = "number"
+ minimum = 0
+ maximum = 100
+ }
+ branch_coverage = {
+ type = "number"
+ minimum = 0
+ maximum = 100
+ }
+ total_lines = { type = "integer" }
+ covered_lines = { type = "integer" }
+ }
+ required = ["line_coverage", "total_lines", "covered_lines"]
+ })
+
+ jq_rules = [
+ ".line_coverage >= 80",
+ ".branch_coverage >= 70"
+ ]
+}
+
+# Age verification attestation type with only jq rules (no schema)
+resource "kosli_custom_attestation_type" "age_verification" {
+ name = "age-verification"
+ description = "Verifies age is over 21 using only jq rules without schema validation"
+
+ jq_rules = [".age > 21"]
+}
+
+# Schema-only attestation type (no jq rules)
+resource "kosli_custom_attestation_type" "schema_validation" {
+ name = "data-structure-validation"
+ description = "Validates data structure using schema without evaluation rules"
+
+ schema = jsonencode({
+ type = "object"
+ properties = {
+ timestamp = { type = "string" }
+ metadata = { type = "object" }
+ status = {
+ type = "string"
+ enum = ["pass", "fail", "skip"]
+ }
+ }
+ required = ["timestamp", "status"]
+ })
+}
+```
+
+## Schema validation
+
+The `schema` attribute is optional and can contain a valid JSON Schema (draft-07) that defines the structure of attestation data. When provided, attestation data will be validated against this schema. Common schema types:
+
+- **Security scans**: Define vulnerability counts and scan metadata
+- **Code coverage**: Define coverage percentages and test metrics
+- **Performance tests**: Define response times and error rates
+
+### Schema example
+
+```json
+{
+ "type": "object",
+ "properties": {
+ "critical_vulnerabilities": { "type": "integer" },
+ "high_vulnerabilities": { "type": "integer" },
+ "scan_date": { "type": "string" }
+ },
+ "required": ["critical_vulnerabilities", "high_vulnerabilities", "scan_date"]
+}
+```
+
+## JQ rules
+
+The `jq_rules` attribute is optional and contains an array of JQ expressions that must ALL evaluate to `true` for an attestation to be considered compliant. When provided, each rule is evaluated against the attestation data. If omitted, no evaluation is performed.
+
+### JQ rules examples
+
+```hcl
+jq_rules = [
+ ".critical_vulnerabilities == 0", # No critical vulnerabilities allowed
+ ".high_vulnerabilities < 5", # Less than 5 high vulnerabilities
+ ".scan_date != null" # Scan date must be present
+]
+```
+
+## Import
+
+Custom attestation types can be imported using their name:
+
+```shell
+# Import an existing custom attestation type by name
+terraform import kosli_custom_attestation_type.security_scan security-scan
+```
+
+## Schema
+
+### Required
+
+- `name` (String) Name of the custom attestation type. Must start with a letter or number and can only contain letters, numbers, periods, hyphens, underscores, and tildes. Changing this will force recreation of the resource.
+
+### Optional
+
+- `description` (String) Description of the custom attestation type. Explains what this attestation type validates.
+- `jq_rules` (List of String) List of jq evaluation rules. Each rule is a jq expression that must evaluate to true for the attestation to be considered compliant. Example: `[".coverage >= 80"]`. If omitted, no evaluation is performed.
+- `schema` (String) JSON Schema definition that defines the structure of attestation data. Can be provided inline using heredoc syntax or loaded from a file using `file()`. If omitted, no schema validation is performed. Semantic equality is used for comparison, so formatting differences are ignored.
diff --git a/terraform-reference/resources/environment.mdx b/terraform-reference/resources/environment.mdx
new file mode 100644
index 0000000..0d22817
--- /dev/null
+++ b/terraform-reference/resources/environment.mdx
@@ -0,0 +1,135 @@
+---
+title: "kosli_environment resource"
+description: "Manages a Kosli environment. Environments represent deployment targets where artifacts are deployed. Supports physical environment types: K8S, ECS, S3, docker, server, and lambda."
+icon: "cube"
+---
+
+Manages a Kosli environment. Environments represent deployment targets where artifacts are deployed. Supports physical environment types: K8S, ECS, S3, docker, server, and lambda.
+
+
+This resource manages the environment configuration only. Environment tags are managed through a separate Kosli API. Environment policies will be available in a future release. For querying environment metadata such as `last_modified_at`, `last_reported_at`, and `archived` status, use the [`kosli_environment` data source](/terraform-reference/data-sources/environment).
+
+
+Kosli environments track deployments and provide visibility into what's running in your infrastructure. Physical environments represent actual runtime locations such as:
+
+- **K8S**: Kubernetes clusters
+- **ECS**: Amazon Elastic Container Service clusters
+- **S3**: Amazon S3 buckets
+- **docker**: Docker containers
+- **server**: Bare-metal or VM servers
+- **lambda**: AWS Lambda functions
+
+
+For aggregating multiple physical environments into logical groups, use the [`kosli_logical_environment` resource](/terraform-reference/resources/logical_environment).
+
+
+
+Environment tags are managed through a separate Kosli API and are not included in this Terraform resource.
+
+
+
+Environment policies will be available in a future release as a separate resource (`kosli_environment_policy`).
+
+
+## Example usage
+
+```terraform
+terraform {
+ required_providers {
+ kosli = {
+ source = "kosli-dev/kosli"
+ }
+ }
+}
+
+# Basic K8S environment
+resource "kosli_environment" "production_k8s" {
+ name = "production-k8s"
+ type = "K8S"
+ description = "Production Kubernetes cluster"
+}
+
+# ECS environment with scaling
+resource "kosli_environment" "staging_ecs" {
+ name = "staging-ecs"
+ type = "ECS"
+ description = "Staging ECS cluster"
+ include_scaling = true
+}
+
+# S3 environment
+resource "kosli_environment" "data_lake" {
+ name = "data-lake-s3"
+ type = "S3"
+ description = "Data lake S3 bucket environment"
+}
+
+# Docker environment
+resource "kosli_environment" "local_docker" {
+ name = "local-docker"
+ type = "docker"
+}
+
+# Server environment
+resource "kosli_environment" "production_servers" {
+ name = "production-servers"
+ type = "server"
+ description = "Production bare-metal servers"
+ include_scaling = false
+}
+
+# Lambda environment
+resource "kosli_environment" "serverless_functions" {
+ name = "serverless-lambda"
+ type = "lambda"
+ description = "AWS Lambda functions"
+}
+```
+
+## Environment types
+
+The `type` attribute must be one of the following physical environment types:
+
+- `K8S` - Kubernetes clusters
+- `ECS` - Amazon Elastic Container Service
+- `S3` - Amazon S3 buckets
+- `docker` - Docker containers
+- `server` - Bare-metal or VM servers
+- `lambda` - AWS Lambda functions
+
+## Configuration options
+
+### Include scaling
+
+The `include_scaling` attribute (default: `false`) determines whether scaling events in the environment should be tracked. This is useful for environments with auto-scaling where you want to monitor scale-up and scale-down events.
+
+## Import
+
+Environments can be imported using their name:
+
+```shell
+#!/bin/bash
+
+# Import an existing environment by name
+terraform import kosli_environment.production_k8s production-k8s
+
+# Import multiple environments
+terraform import kosli_environment.staging_ecs staging-ecs
+terraform import kosli_environment.data_lake data-lake-s3
+```
+
+## Monitoring environments
+
+For querying environment metadata such as `last_modified_at` and `last_reported_at` timestamps, use the [`kosli_environment` data source](/terraform-reference/data-sources/environment). This is useful for monitoring and creating conditional logic based on environment state.
+
+## Schema
+
+### Required
+
+- `name` (String) Name of the environment. Must be unique within the organization. Changing this will force recreation of the resource.
+- `type` (String) Type of the environment. Valid values: `K8S`, `ECS`, `S3`, `docker`, `server`, `lambda`. Changing this will force recreation of the resource.
+
+### Optional
+
+- `description` (String) Description of the environment. Explains the purpose and characteristics of this deployment target.
+- `include_scaling` (Boolean) Whether to include scaling information when reporting environment snapshots. Defaults to `false`.
diff --git a/terraform-reference/resources/logical_environment.mdx b/terraform-reference/resources/logical_environment.mdx
new file mode 100644
index 0000000..8d0987c
--- /dev/null
+++ b/terraform-reference/resources/logical_environment.mdx
@@ -0,0 +1,201 @@
+---
+title: "kosli_logical_environment resource"
+description: "Manages a Kosli logical environment. Logical environments aggregate multiple physical environments for organizational purposes."
+icon: "cube"
+---
+
+Manages a Kosli logical environment. Logical environments aggregate multiple physical environments for organizational purposes.
+
+
+Logical environments can ONLY contain physical environments (K8S, ECS, S3, docker, server, lambda), not other logical environments. Attempting to include a logical environment will result in an error from the Kosli API.
+
+
+
+This resource manages logical environment configuration only. For querying environment metadata such as `last_modified_at` and `archived` status, use the [`kosli_logical_environment` data source](/terraform-reference/data-sources/logical_environment).
+
+
+Logical environments in Kosli aggregate multiple physical environments for organizational purposes, providing:
+
+- **Unified visibility**: View compliance status across multiple environments at once
+- **Flexible grouping**: Organize environments by region, service type, tier, or team
+- **Simplified reporting**: Generate compliance reports for logical groupings
+- **Team organization**: Allow different teams to focus on specific environment groups
+
+## Physical environments only
+
+
+Logical environments can ONLY contain physical environments (K8S, ECS, S3, docker, server, lambda), not other logical environments. Attempting to include a logical environment will result in an API error.
+
+
+## Example usage
+
+```terraform
+terraform {
+ required_providers {
+ kosli = {
+ source = "kosli-dev/kosli"
+ }
+ }
+}
+
+# First, create physical environments that will be aggregated
+resource "kosli_environment" "production_k8s" {
+ name = "production-k8s"
+ type = "K8S"
+ description = "Production Kubernetes cluster"
+}
+
+resource "kosli_environment" "production_ecs" {
+ name = "production-ecs"
+ type = "ECS"
+ description = "Production ECS cluster"
+}
+
+resource "kosli_environment" "production_lambda" {
+ name = "production-lambda"
+ type = "lambda"
+ description = "Production Lambda functions"
+}
+
+# Basic logical environment aggregating production environments
+resource "kosli_logical_environment" "production_all" {
+ name = "production-aggregate"
+ description = "Aggregates all production environments for unified visibility"
+
+ included_environments = [
+ kosli_environment.production_k8s.name,
+ kosli_environment.production_ecs.name,
+ kosli_environment.production_lambda.name,
+ ]
+}
+
+# Logical environment with just two environments
+resource "kosli_logical_environment" "cloud_services" {
+ name = "cloud-services"
+ description = "All cloud-based services"
+
+ included_environments = [
+ kosli_environment.production_ecs.name,
+ kosli_environment.production_lambda.name,
+ ]
+}
+
+# Minimal logical environment with empty list (can be populated later)
+resource "kosli_logical_environment" "future_environments" {
+ name = "future-environments"
+ included_environments = []
+}
+
+# Logical environment without description (optional)
+resource "kosli_logical_environment" "simple" {
+ name = "simple-aggregate"
+
+ included_environments = [
+ kosli_environment.production_k8s.name,
+ ]
+}
+```
+
+## Complete example
+
+For a comprehensive example showing logical environments aggregating physical environments by region, service type, and tier, see the [complete logical environments example](https://github.com/kosli-dev/terraform-provider-kosli/tree/main/examples/complete/logical-environments).
+
+## Common use cases
+
+### By environment tier
+
+Aggregate all production or staging environments for unified compliance reporting:
+
+```terraform
+resource "kosli_logical_environment" "production_all" {
+ name = "production-all"
+ description = "All production environments"
+
+ included_environments = [
+ kosli_environment.prod_k8s.name,
+ kosli_environment.prod_ecs.name,
+ kosli_environment.prod_lambda.name,
+ ]
+}
+```
+
+### By geographic region
+
+Group environments by region for regional compliance or disaster recovery:
+
+```terraform
+resource "kosli_logical_environment" "production_us_east" {
+ name = "production-us-east"
+ description = "All production environments in US East"
+
+ included_environments = [
+ kosli_environment.prod_k8s_us_east.name,
+ kosli_environment.prod_ecs_us_east.name,
+ ]
+}
+```
+
+### By service type
+
+Organize environments by technology stack or service type:
+
+```terraform
+resource "kosli_logical_environment" "all_kubernetes" {
+ name = "all-kubernetes-clusters"
+ description = "All Kubernetes clusters across regions"
+
+ included_environments = [
+ kosli_environment.k8s_us_east.name,
+ kosli_environment.k8s_eu_west.name,
+ kosli_environment.k8s_ap_south.name,
+ ]
+}
+```
+
+## Empty logical environments
+
+Logical environments can be created with empty `included_environments` lists and populated later:
+
+```terraform
+resource "kosli_logical_environment" "future_environments" {
+ name = "planned-expansion"
+ description = "Placeholder for future environments"
+ included_environments = []
+}
+```
+
+## Import
+
+Logical environments can be imported using their name:
+
+```shell
+#!/bin/bash
+
+# Import an existing logical environment by name
+terraform import kosli_logical_environment.production_all production-aggregate
+
+# Import multiple logical environments
+terraform import kosli_logical_environment.cloud_services cloud-services
+terraform import kosli_logical_environment.future_environments future-environments
+```
+
+## Querying metadata
+
+
+This resource manages logical environment configuration only. For querying environment metadata such as `last_modified_at` and `archived` status, use the [`kosli_logical_environment` data source](/terraform-reference/data-sources/logical_environment).
+
+
+## Schema
+
+### Required
+
+- `included_environments` (List of String) List of physical environment names to aggregate. Only physical environments are allowed (K8S, ECS, S3, docker, server, lambda). Can be empty.
+- `name` (String) Name of the logical environment. Must be unique within the organization. Changing this will force recreation of the resource.
+
+### Optional
+
+- `description` (String) Description of the logical environment. Explains the purpose and aggregation strategy.
+
+### Read-only
+
+- `type` (String) Type of the environment. Always set to `logical` (computed by provider, not user-configurable).