From 06e2da11e207d1d20610c6ea2619af22101f9d5f Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 25 May 2026 10:33:55 -0700 Subject: [PATCH 1/3] Document calculated field params dictionary including model_stage. Adds a reference table for built-in params keys on inventory and artifact calculation fields to close the documentation gap identified in sc-15239. --- site/guide/inventory/_field-types.qmd | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index 619e33d3d..0d4f7c3d3 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -68,6 +68,19 @@ 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. +##### 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` object: + +| Param | Applies to | Availability | Description | +|---|---|---|---| +| `params.` | 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_`. 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`). | + :::: {.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**.
Keep your code simple and avoid complex logic and imports.] From 847c77a0aee5ead4899f35d0de4b66001f32ec78 Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 25 May 2026 11:09:29 -0700 Subject: [PATCH 2/3] Restore Starlark calculated fields docs and add params dictionary. Re-applies the Calculation section from #1323, which was regressed by #1328, and inserts the params reference table above Available helpers for sc-15239. --- site/guide/inventory/_field-types.qmd | 132 ++++++++++++++------------ 1 file changed, 71 insertions(+), 61 deletions(-) diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index 0d4f7c3d3..97db447be 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -66,24 +66,48 @@ 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. +::: ##### 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` object: +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.` | 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_`. 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`). | +| `params[""]` | 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_`. 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. | :::: {.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**.
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.

@@ -93,38 +117,29 @@ In addition to custom field keys you add from the **available fields** drop-down ### 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**.
Keep your code simple and avoid complex logic and imports.] +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. 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.

@@ -134,10 +149,10 @@ Your calculated field is grouped under `Model Risk` inventory fields, and can on ### 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 @@ -151,44 +166,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 ``` ::: @@ -264,9 +274,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. From b8fb6d7749a9b659c39d80adfdea807c141ccff6 Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 25 May 2026 18:32:59 -0700 Subject: [PATCH 3/3] Move params and helpers reference and turn into tabset --- site/guide/inventory/_field-types.qmd | 76 ++++++++++++++------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index 97db447be..f0779eaf2 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -72,39 +72,6 @@ Calculation {{< 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. ::: -##### 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[""]` | 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_`. 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. | - :::: {.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.^[Reference fields with dictionary-style access — `params["fieldKey"]` — and use the available helpers for date and number work.] @@ -139,9 +106,9 @@ def formula(params): :::: {.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.^[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. -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. +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.

::: {.callout-button .pl4 .nt4} @@ -208,6 +175,43 @@ def formula(params): :::: +::: {.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[""]` | 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_`. 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.