Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 83 additions & 56 deletions site/guide/inventory/_field-types.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,15 @@ Attachments
::::

Calculation
: Define a `formula(params)` function that automatically calculates and returns a read-only value based on the params dictionary, which includes selected custom field keys retrieved from your other inventory record fields.
: Define a `formula(params)` function that reads field values from the `params` dictionary and returns a read-only value. Formulas are written in Starlark^[[Starlark](https://github.com/bazelbuild/starlark)], a small, sandboxed scripting language with a Python-style syntax and a set of built-in helper functions for working with dates, numbers, and lists.

::: {.callout title="A note on calculated fields"}
{{< var vm.product >}} runs calculated field formulas on the Starlark formula engine. Formulas authored on earlier releases were written in Python and have been migrated to Starlark automatically. When creating or editing formulas, you now must use the Starlark syntax.
:::

:::: {.content-visible when-format="html" when-meta="includes.inventory"}
1. Select from the drop-down of **[available record fields]{.smallcaps}** to allow your formula access to the field's values.^[Fields are grouped by field type.]
2. Replace the demonstration formula with your own in the code box provided.^[**Stick to basic operations**.<br>Keep your code simple and avoid complex logic and imports.]
2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` — and use the available helpers for date and number work.]
3. Click **Test Calculation {{< fa angle-down >}}** to open the testing area.
4. Enter sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.
<br><br>
Expand All @@ -80,51 +84,42 @@ Calculation

### Example — Risk tier calculation

You have numeric inventory fields of `materiality` and `complexity`, where a larger value indicates a lower risk.
You have inventory fields named `materiality` and `complexity` that classify a record's risk.

##### Example formula

You want a calculated field that automatically returns a risk score based on `materiality` and `complexity`:
A calculated field that returns a combined risk tier based on `materiality` and `complexity`:

```python
def formula(params):
# High Risk: If materiality is high risk, return high risk regardless of complexity
if params.materiality == "High Risk":
return "High Risk"
# Medium Risk: If materiality is low risk but complexity is high risk, return medium risk
if params.materiality == "Low Risk" and params.complexity == "High Risk":
return "Medium Risk"
# Low Risk: Both materiality and complexity are low risk
return "Low Risk"
def formula(params):
if params["materiality"] == "High Risk":
return "High Risk"
if params["materiality"] == "Low Risk" and params["complexity"] == "High Risk":
return "Medium Risk"
return "Low Risk"
```

##### Example Calculation field configuration

Your calculated field is grouped under `Model Risk` inventory fields, and can only be manually overridden by that record's Validators:

![Adding a calculation type field that automatically calculates risk tier](calculation-field.png){fig-alt="A screenshot showing the screen for adding a calculation type field that automatically calculates risk tier" width=90% .screenshot}

:::
:::

::::

:::: {.content-visible when-format="html" when-meta="includes.artifacts"}
1. Select from the drop-down of **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params.model`** to allow your formula access to the field's values.^[Fields are grouped by field type.]
2. Replace the demonstration formula with your own in the code box provided.^[**Stick to basic operations**.<br>Keep your code simple and avoid complex logic and imports.]
4. Click **Test Calculation {{< fa angle-down >}}** to open the testing area.
5. Enter in sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.
1. Select from the drop-down of **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params["model"]`** to allow your formula access to the field's values.^[Fields are grouped by field type.]
2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` and `params["model"]["fieldKey"]` for parent inventory record data — and use the available helpers for date and number work.]
3. Click **Test Calculation {{< fa angle-down >}}** to open the testing area.
4. Enter in sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.
<br><br>

::: {.callout-button .pl4 .nt4}
::: {.callout collapse="true" appearance="minimal"}

### Example — Use artifact types in your formulas to create dynamic calculations

Use simple dot notation to include [artifact types](/guide/validation/manage-artifact-types.qmd){target="_blank"}:
The [artifact type](/guide/validation/manage-artifact-types.qmd){target="_blank"} is exposed under `params["finding_type"]` so you can branch on it:

- `finding_type.tag` — Technical tag: `VALIDATION_ISSUE`
- `finding_type.name` — Human-readable name: `Validation Issue`
- `params["finding_type"]["tag"]` — Technical tag: `VALIDATION_ISSUE`
- `params["finding_type"]["name"]` — Human-readable name: `Validation Issue`

##### Example use cases

Expand All @@ -138,44 +133,39 @@ Use simple dot notation to include [artifact types](/guide/validation/manage-art
#### Severity calculation

```python
# Calculate different severity scores based on artifact type

if finding_type.tag == "VALIDATION_ISSUE":
return severity_score * 2.5
elif finding_type.tag == "POLICY_EXCEPTION":
return severity_score * 1.0
else:
return severity_score * 1.8
def formula(params):
if params["finding_type"]["tag"] == "VALIDATION_ISSUE":
return params["severity_score"] * 2.5
elif params["finding_type"]["tag"] == "POLICY_EXCEPTION":
return params["severity_score"] * 1.0
else:
return params["severity_score"] * 1.8
```

#### Due date calculation

```python
# Dynamically calculate due dates based on artifact type

base_days = 30
if finding_type.tag == "VALIDATION_ISSUE":
urgency_multiplier = 0.5 # 15 days
elif finding_type.tag == "MODEL_LIMITATION":
urgency_multiplier = 2.0 # 60 days
else:
urgency_multiplier = 1.0 # 30 days

return base_days * urgency_multiplier
def formula(params):
base_days = 30
if params["finding_type"]["tag"] == "VALIDATION_ISSUE":
urgency_multiplier = 0.5
elif params["finding_type"]["tag"] == "MODEL_LIMITATION":
urgency_multiplier = 2.0
else:
urgency_multiplier = 1.0
return base_days * urgency_multiplier
```

#### Custom fields & parent record data

```python
# Combine artifact types with custom fields and parent record data

risk_factor = custom_field_risk_score or 1.0
model_criticality = params.model.get("criticality_level", "medium")

if finding_type.tag == "VALIDATION_ISSUE" and model_criticality == "high":
return risk_factor * 3.0
else:
return risk_factor * 1.5
def formula(params):
risk_factor = params["custom_field_risk_score"] or 1.0
model_criticality = params["model"].get("criticality_level", "medium")
if params["finding_type"]["tag"] == "VALIDATION_ISSUE" and model_criticality == "high":
return risk_factor * 3.0
else:
return risk_factor * 1.5
```

:::
Expand All @@ -185,6 +175,43 @@ else:

::::

::: {.panel-tabset}

#### Params dictionary

In addition to custom field keys you add from the **available fields** drop-down, formulas can read built-in keys on the `params` dictionary:

| Param | Applies to | Availability | Description |
|---|---|---|---|
| `params["<fieldKey>"]` | Inventory records and artifacts | Add the field from the **available fields** drop-down | Current value of another custom field on the same record or artifact. |
| `params["model_stage"]` | Inventory records | Add **Model Stage** from the **available fields** drop-down | Current model stage name as a string (for example, `"Production"`). Returns an empty string when no stage is assigned. Compare directly: `params["model_stage"] == "Production"`. |
| `params["stakeholders"]` | Inventory records | Add a stakeholder role from the **available fields** drop-down (for example, **Stakeholders — Owners**) | Assigned users by stakeholder role. Default role keys are `owners`, `developers`, and `validators`. Custom stakeholder types use `custom_stakeholder_<cuid>`. Each entry includes `name`, `email`, and `title`. |
| `params["integrations"]` | Inventory records and artifacts | Reference `params["integrations"]` in the formula source | Linked external integration data keyed by service (for example, `params["integrations"]["mlflow"]`). Empty when integrations are not configured or not referenced. |
| `params["finding_type"]` | Artifacts | Always available on artifact formulas | Artifact type metadata with `["tag"]` (technical identifier) and `["name"]` (display name). |
| `params["model"]` | Artifacts | Always available when the artifact is linked to an inventory record | Parent inventory record custom field values (for example, `params["model"]["criticality_level"]`). |

#### Available helpers

Reference these helpers in your formulas — they cover the date, number, and list operations the engine does not expose directly:

| Helper | Returns | Description |
|---|---|---|
| `today()` | `"YYYY-MM-DD"` | Current date as an ISO string. |
| `safe_parse_date(value, default=None)` | `"YYYY-MM-DD"` or `default` | Parses ISO dates/datetimes or millisecond/second epoch timestamps. |
| `to_iso(value)` | `"YYYY-MM-DD"` or `None` | Alias for `safe_parse_date` with no default. |
| `add_days(date, n)` | `"YYYY-MM-DD"` or `None` | Adds `n` days to an ISO date. |
| `add_months(date, n)` | `"YYYY-MM-DD"` or `None` | Adds `n` months to an ISO date. |
| `days_between(a, b)` | `int` or `None` | Days between two ISO dates (`a` − `b`). |
| `days_since(date)` | `int` or `None` | Days from `date` to today. |
| `months_between(a, b)` | `int` or `None` | Full-month difference between two ISO dates. |
| `get_year(date)` / `get_month(date)` / `get_day(date)` | `int` or `None` | Components of an ISO date. |
| `safe_int(value, default=0)` | `int` | Tolerates strings and missing values. |
| `safe_float(value, default=0.0)` | `float` | Tolerates strings and missing values. |
| `list_count(list, value)` | `int` | Number of times `value` appears in `list`. |
| `zfill(value, width)` | `string` | Zero-pads `value` to `width` characters. |

:::

Checkbox
: A `true`/`false` value set by a toggle.

Expand Down Expand Up @@ -251,9 +278,9 @@ Attachments
: Upload supporting files for your [record](/guide/inventory/edit-inventory-fields.qmd#manage-attachments){target="_blank"} or [artifact](/guide/validation/add-manage-artifacts.qmd#manage-attachments){target="_blank"}. Files must be less than 50 MB each in size.

Calculation
: Define a `formula(params)` function that automatically calculates and returns a read-only value based on the params dictionary, which includes selected custom field keys retrieved from your other inventory record fields.
: Define a `formula(params)` function that reads field values from the `params` dictionary (`params["fieldKey"]`) and returns a read-only value. Formulas are written in Starlark and have access to a set of built-in helpers for dates, numbers, and lists.

1. Select from the drop-down of **[available record fields]{.smallcaps}**, or **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params.model`** (artifact fields) to allow your formula access to the field's values.
1. Select from the drop-down of **[available record fields]{.smallcaps}**, or **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params["model"]`** (artifact fields) to allow your formula access to the field's values.
2. Replace the demonstration formula with your own in the code box provided.
4. Click **Test Calculation {{< fa angle-down >}}** to open the testing area.
5. Enter in sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.
Expand Down
Loading