Decorators
Decorators were introduced in CALM schema version 1.2. To use decorators, reference the following schema in your decorator document:
"$schema": "https://calm.finos.org/release/1.2/meta/decorators.json#/defs/decorator"
Decorators attach supplementary information to nodes, relationships, and other architecture elements without modifying the core architecture definition. They enable cross-cutting concerns — such as deployment tracking, security context, business metadata, and operational information — to be managed separately from the architecture itself.
What is a Decorator?​
A decorator is a standalone object that references one or more architecture elements via their unique-id and attaches typed data to them. This keeps the architecture file clean and focused while allowing rich contextual information to be layered on top.
Key Properties​
- unique-id: A unique identifier for this decorator instance
- type: A string identifying the category of decorator (e.g.
guide,business,threat-model,deployment). This is a free-form string, not an enum — any value is valid - target: An array of file paths or URLs referencing the CALM documents (patterns, architectures, or controls) this decorator targets
- applies-to: An array of
unique-idvalues referencing the architecture elements within the targeted documents this decorator relates to - data: A JSON object containing the decorator's payload, whose shape is determined by the decorator type
Base Decorator Schema​
The base decorator schema defines the top-level structure that all decorators must follow:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://calm.finos.org/release/1.2/meta/decorators.json",
"title": "Common Architecture Language Model Decorators",
"defs": {
"decorator": {
"type": "object",
"properties": {
"unique-id": {
"type": "string"
},
"type": {
"type": "string"
},
"target": {
"type": "array",
"items": { "type": "string" },
"minItems": 1
},
"applies-to": {
"type": "array",
"items": { "type": "string" },
"minItems": 1
},
"data": {
"type": "object",
"minProperties": 1
}
},
"required": ["unique-id", "type", "target", "applies-to", "data"],
"additionalProperties": false
}
}
}
The top-level properties are locked down via additionalProperties: false, while the data object is intentionally open — its shape is defined by decorator-type-specific schemas.
Extending Decorators with Schemas​
Decorator types can define their own schema for the data field by inheriting from the base decorator using allOf. Each extension schema:
- Constrains
typeto a specific value (e.g."deployment") - Adds required and optional properties to
data - Can be further extended by more specific schemas
This creates a composable schema inheritance chain where each layer owns its own namespace within data.
Example: Deployment Decorators​
To illustrate how the base decorator schema can be extended, consider deployment decorators that track when and how architecture components are deployed, including status, timing, and observability links.
Example: Deployment Decorator Schema​
A deployment decorator schema could constrain type to "deployment" and define deployment-specific attributes in data:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://calm.finos.org/release/1.2/meta/deployment.decorator.schema.json",
"title": "CALM Deployment Decorator Schema",
"allOf": [
{
"$ref": "https://calm.finos.org/release/1.2/meta/decorators.json#/defs/decorator"
},
{
"type": "object",
"properties": {
"type": { "const": "deployment" },
"data": {
"type": "object",
"properties": {
"deployment-start-time": {
"type": "string",
"format": "date-time"
},
"deployment-status": {
"type": "string",
"enum": [
"in-progress", "failed", "completed",
"rolled-back", "pending"
]
},
"deployment-observability": {
"type": "string",
"format": "uri"
}
},
"required": ["deployment-start-time", "deployment-status"],
"additionalProperties": true
}
},
"required": ["type", "data"]
}
]
}
| Property | Type | Required | Description |
|---|---|---|---|
deployment-start-time | string (date-time) | Yes | ISO 8601 timestamp of when the deployment started |
deployment-status | string (enum) | Yes | Current status: in-progress, failed, completed, rolled-back, pending |
deployment-observability | string (uri) | No | Link to logs, metrics, or observability dashboards |
The data object uses additionalProperties: true so that extension schemas can add domain-specific sub-objects.
Example: Kubernetes Deployment Decorators​
Taking the extension pattern further, a Kubernetes-specific decorator could add a kubernetes sub-object inside data with cluster-specific attributes. The Kubernetes properties are nested to avoid conflicts with the base deployment properties and to allow each schema layer to lock down its own scope.
Kubernetes Decorator Schema​
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://calm.finos.org/release/1.2/meta/kubernetes.decorator.schema.json",
"title": "CALM Kubernetes Deployment Decorator Schema",
"allOf": [
{
"$ref": "https://calm.finos.org/release/1.2/meta/deployment.decorator.schema.json"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"kubernetes": {
"type": "object",
"properties": {
"helm-chart": {
"type": "string",
"pattern": "^[a-z0-9-]+:[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"cluster": { "type": "string" },
"namespace": { "type": "string" }
},
"required": ["helm-chart", "cluster"],
"additionalProperties": false
}
},
"required": ["kubernetes"]
}
}
}
]
}
| Property | Type | Required | Description |
|---|---|---|---|
kubernetes.helm-chart | string (pattern) | Yes | Helm chart name and semver version (e.g. my-app:1.2.3) |
kubernetes.cluster | string | Yes | Kubernetes cluster identifier |
kubernetes.namespace | string | No | Kubernetes namespace for the deployment |
Schema Inheritance​
The examples above demonstrate how the schema inheritance chain allows each layer to define its own properties while composing cleanly:
decorators.json (base: unique-id, type, applies-to, data)
└── deployment decorator (type="deployment", deployment attributes in data)
└── kubernetes decorator (kubernetes sub-object in data)
Other deployment targets (e.g. AWS ECS, Azure Container Apps) could follow the same pattern — extend a deployment decorator schema and add their own sub-object inside data.
Worked Example​
Given a simple architecture with a single AKS cluster node:
{
"$schema": "https://calm.finos.org/release/1.2/meta/calm.json",
"nodes": [
{
"unique-id": "aks-cluster",
"node-type": "system",
"name": "Azure Kubernetes Service Cluster",
"description": "A Kubernetes cluster running on Azure AKS"
}
],
"relationships": []
}
A Kubernetes deployment decorator for this node could look like:
{
"$schema": "https://calm.finos.org/release/1.2/meta/kubernetes.decorator.schema.json",
"unique-id": "aks-cluster-deployment-001",
"type": "deployment",
"target": ["aks-architecture.json"],
"applies-to": ["aks-cluster"],
"data": {
"deployment-start-time": "2026-02-12T09:30:00Z",
"deployment-status": "completed",
"deployment-observability": "https://grafana.example.com/d/aks-prod/aks-cluster-overview",
"kubernetes": {
"helm-chart": "aks-platform:3.2.1",
"cluster": "prod-uksouth-aks-01",
"namespace": "trading-system"
}
}
}
This decorator:
- Targets the architecture document
aks-architecture.jsonviatarget - References the
aks-clusternode within that architecture viaapplies-to - Satisfies the base decorator schema (has
unique-id,type,target,applies-to,data) - Satisfies the deployment schema (
deployment-start-time,deployment-statusare present) - Satisfies the Kubernetes schema (
helm-chart,clusterare present inside thekubernetessub-object)