Skip to content

Upsert a Validation Check

Files a validation check as a ticket, parented to the KSI or Rule it evidences. This is the definition of a check: what it asserts and how it is evidenced. The results of running it go to Validation Records.

Call this once per check per system, when your check catalogue changes. Re-sending is safe and is how you update a check.

Before you start: you need a token. See Authentication.


What it does with the payload

It finds the top-level ticket for your control_id on that system, creating it from the control catalogue if the system has none, then creates or updates the check ticket beneath it, and writes the check definition onto it.

KSI-CNA-DBS - Deploying Boundary Security      <- container, created if absent
  KSI-CNA-DBS | Public bucket exposure        <- your check

Two things are composed for you:

Summary is built as <control_id> | <check_title>, for example KSI-CNA-DBS | Public bucket exposure. Do not pre-compose it.

Category is derived, never sent. A control_id beginning KSI- files under Validation>KSI; anything else files under Validation>Rule.


Minimal call

{
  "site_id": 18,
  "control_id": "KSI-CNA-DBS",
  "check_title": "Public bucket exposure",
  "validation_id": "CNA-DBS-01"
}

The call returns 202 with an empty body, so it does not hand you the check's ticket_id. Resolve it once through the Halo API or the UI by its validation_id or its summary, and store it against your check definition. Validation Records needs it on every run. See Responses.


Fields

Field Required Default Notes
site_id / system_name one of - See Identifying the system
control_id yes - The KSI or Rule this check evidences, e.g. KSI-CNA-DBS, VER-EVA-EPA
check_title yes - Short name of this specific check. Becomes the second half of the summary
validation_id yes - Your stable identifier for the check. This is the dedup key
validation_statement no unchanged What outcome the check asserts. Read the note below before using it
validation_test no unchanged How the check is performed
validation_method no Automated Automated or Manual
evidence_type no Configuration See allowed values below
evidence_description no unchanged What the evidence is and where it comes from

Keep validation_id stable

The dedup key is the system plus control_id plus validation_id.

  • Re-posting the same validation_id updates the existing check ticket.
  • Changing check_title on the same validation_id renames the existing ticket rather than creating a second one. Renaming a check is safe.
  • Changing validation_id creates a new check ticket, even if the title is identical. Treat validation_id as the check's permanent identity.

validation_id, validation_method and evidence_type are written on every call, so the two defaults re-assert themselves if you stop sending them. validation_statement, validation_test and evidence_description are written only when you send them, so omit them to leave the current values alone.


Allowed values

validation_method, exactly one of:

Automated | Manual

evidence_type, exactly one of:

Log | Report | Screenshot | Configuration | Policy | Procedure | Audit Record

An unrecognised value is not an error: it silently falls back to the default

Both fields are matched against the lists above. A typo in validation_method is accepted and recorded as Automated; a typo in evidence_type is recorded as Configuration. Nothing tells you it happened, so check your spelling when you first wire up an integration.


A note on validation_statement

For KSI checks the outcome statement belongs on the KSI container ticket, not on the individual check, and it is populated there automatically from the control catalogue. Rule checks carry no statement at all, because a rule's identity lives in its Rule field and its per-rule test.

This endpoint accepts validation_statement because integrations ask for it. If you are filing against the KSI tree, omit it and let the platform own it.


Rejections

Code Rejected because
51001 control_id missing
51002 Neither site_id nor system_name sent
51003 No system matched
51004 check_title missing
51005 validation_id missing
51006 The container ticket for the control does not exist and could not be created
51007 The check ticket could not be resolved after being created

Full example

{
  "site_id": 18,
  "control_id": "KSI-CNA-DBS",
  "check_title": "Public bucket exposure",
  "validation_id": "CNA-DBS-01",
  "validation_test": "Enumerate every object store in the boundary and assert that no bucket policy or ACL grants access to AllUsers or AuthenticatedUsers.",
  "validation_method": "Automated",
  "evidence_type": "Configuration",
  "evidence_description": "Daily Steampipe sweep of aws_s3_bucket across all in-boundary accounts."
}