helixordevelopers

Playbook schema

The keys a playbook file can contain, their types, and which of them the 0.2.1 runtime actually executes. Read the "What runs in 0.2.1" section before you write rules.

Runtime 0.2.1Tier 1 to compile

About the example

Field examples such as PII_SSN_EXTRACT and RULE-PCI-DSS-PAN-BLOCK come from the built-in data-protection pack, which ships with the runtime. The keys themselves describe any decision pack: eligibility, limits, routing and so on. See Core concepts.

What runs in 0.2.1#

A playbook is a declarative description. In 0.2.1, two engines use it in different ways:

EngineHow you get itWhat it executes
Built-in example packHelixorEngine()The six codons and the four rule groups of the example pack, compliance.regulatory_pii_guard.v1 (data protection), built into the runtime. The published playbook documents this pack; the engine does not read a YAML file.
Compiled packhelixor-pack compile, then HelixorEngine.load_pack(), run or serveYour rules (regex and Luhn checksum) and the example pack's built-in checks. Sections it would not execute are rejected at compile time, except the few listed below that are stored but not used.

For a compiled pack in 0.2.1:

  • rules are executed on every payload, together with the example pack's built-in checks. Every match is reported in triggers. The first fatal match decides the action, with your rules checked first, in file order; with no fatal match, the first warning decides.
  • hard_rules and codons are limited to the built-in ones. The compiler accepts the example pack's four hard rules and six codons only if unchanged, and rejects anything else with UnsupportedPackDeclarationError. Executing your own is Planned.
  • default_action is not used. A payload that breaks no rule always gets permit_clean_payload.
  • actions is not enforced. The action names come from the rule IDs (see Action naming) and are not checked against this list.
  • invariants, remedies and budget are accepted but not executed.

Fixed in the next release: declarations are enforced

  • actions, when present, must list every action the pack can return: permit_clean_payload, the four built-in actions (block_glba_ssn_leakage, block_pci_dss_pan_leakage, block_hipaa_phi_leakage, redact_and_permit_contact_pii) and <block|redact>_<id> for each of your rules. A list that leaves one out fails with UnsupportedPackDeclarationError naming the missing actions. Omitting actions is allowed.
  • default_action may only be permit_clean_payload, or omitted; any other value is rejected.
  • budget accepts only max_latency_ms (positive) and max_tokens (0 or more; the engine spends none). Any other key is rejected. max_latency_ms is checked on every decision, and a slower decision raises DecisionBudgetExceededError with its result withheld.
  • invariants and remedies are still accepted and not executed.

The checks run at compile time and again at load, so a pack compiled by 0.2.1 whose declarations break them fails to load with PackDeclarationUnsealError; recompile it from a corrected playbook. The examples on this site list every action, so they compile with 0.2.1 and with the next release.

The same checks run again when a pack is loaded, so a pack sealed by an older compiler with declarations the engine ignores fails to load instead of running without them.

Known issues in 0.2.1

  • A blocked value can stay in clean_text. When a block rule fires and nothing else was redacted, clean_text becomes [BLOCKED: Prohibited Content]. When another rule redacted something, the text keeps the blocked value and only the other redactions are applied.
  • Capturing groups narrow the match. With a pattern such as (AB)(C), only the first group, AB, is reported and redacted.

Workaround: never forward clean_text from a result whose action starts with block, and write patterns with non-capturing groups, (?:...).

Fixed in the next release. Redact rules replace every whole match by position, overlapping matches merge into one redaction, and any fired block rule makes clean_text [BLOCKED: Prohibited Content]. A pattern such as (ACCT)-(\d{6}) reports and redacts ACCT-123456, the whole match.

Example#

A valid playbook for a compiled pack. Quote any string value that contains ": ", such as descriptions. Unquoted, YAML reads the colon as a new key and compilation fails with CompilerError: Failed to parse YAML playbook.

pack_id: custom.internal_code_guard.v1
version: 1.0.0
name: Internal Project Code Guard
kind: compliance
description: "Blocks internal project codes: never send them outside."

budget:
  max_latency_ms: 1.0
  max_tokens: 0

actions:
  - permit_clean_payload
  - block_project_code
  - block_glba_ssn_leakage
  - block_pci_dss_pan_leakage
  - block_hipaa_phi_leakage
  - redact_and_permit_contact_pii

rules:
  - id: project_code
    type: regex
    pattern: '\bPROJ-[A-Z]+-\d+\b'
    action: block

default_action: permit_clean_payload

Compiled and run, Release PROJ-ZEUS-9 today returns action block_project_code. It has one trigger, project_code, with severity FATAL, and clean_text is [BLOCKED: Prohibited Content]. See Custom rules for the full walkthrough.

Top-level keys#

KeyTypeRequiredIn 0.2.1
pack_idstringyesIdentifies the pack and is sealed into the container. Your license must allow it (see License file). Convention: <domain>.<name>.v<n>.
versionstringnoDefault 1.0.0. Reported as the pack version.
namestringnoDisplay name. Defaults to pack_id.
kindstringnoFree-form category, default safety_guard. Appears as law on triggers from your rules.
descriptionstringnoStored.
budgetmapnomax_latency_ms, max_tokens. Documents intent; not enforced. Enforced in the next release (see above).
floornumbernoConfidence floor carried into the manifest. Not stored in a compiled pack.
actionslist of stringsnoStored; not enforced. In the next release it must list every action the pack can return (see above).
ruleslistnoExecuted (see below).
codonslistnoOnly the example pack's built-in codons, unchanged; anything else is rejected. Your own: Planned
hard_ruleslistnoOnly the example pack's built-in hard rules, unchanged; anything else is rejected. Your own: Planned
invariants, remedieslist, mapnoStored; not executed.
default_actionstringnoNot used; permit_clean_payload is always returned. In the next release any other value is rejected.
required_solvers, solver_id, solver_constraintslist, string, listnoChecked against your license's licensed_solvers at compile and load time. A solver_constraints entry with a type and no solver ID counts as solver solver.tcn.basic. Solver behavior is out of scope for this reference.
forecasting_config, belief_configmapnoStored; out of scope for this reference.

Unknown top-level keys are ignored by the compiler. There is no schema validation beyond the checks listed under Compile-time checks.

rules#

The custom rules a compiled pack executes. All of them run on every payload, in order; every match is reported, and the first fatal match decides.

KeyTypeMeaning
idstringRequired. Rule ID. Appears as rule_id and in the action name.
typestringregex (the default) or luhn_checksum. Any other value is rejected.
patternstringRequired for regex. A Python regular expression, matched case-sensitively with no flags anywhere in the text. Single-quote it in YAML so backslashes survive. An invalid pattern is rejected at compile time.
min_length, max_lengthintFor luhn_checksum: digit counts to consider, default 13 and 19. Runs of digits, optionally separated by spaces or hyphens, that pass the Luhn check match.
actionstringblock gives action block_<id> and severity FATAL. redact gives redact_<id> and WARNING, and replaces each match in clean_text with [REDACTED_<ID>]. block_or_redact, found in older catalog packs, is read as block. Any other value is rejected. Default block.

codons#

Codons describe how to extract typed state from input. The example pack's six codons have this shape. A compiled pack accepts only those six, with their built-in patterns.

KeyTypeMeaning
codestringUnique codon ID, for example PII_SSN_EXTRACT in the example pack.
kindstringDefault codon.
codon_typestringextract_pattern, checksum_validator, range_filter or custom.
triggerstringon_input, on_condition or on_remedy. Only on_input is used today.
paramsmapFor extract_pattern: pattern, optional extra *_pattern keys, and flags (a list of MULTILINE, IGNORECASE, DOTALL, ASCII).
checksumstringluhn keeps only matches that pass the Luhn check.
binds_tostringThe boolean state field set when there is a match, for example has_ssn.
matches_fieldstringOptional state field that holds the matches.
remedy_templatestringReplacement text for each match in the remedy, for example "[REDACTED_SSN]" in the example pack.

hard_rules#

Declarative rules over state, as used in the example pack's playbook. A compiled pack accepts only the example pack's four, unchanged; your own are Planned.

KeyTypeMeaning
idstringRule ID, for example RULE-PCI-DSS-PAN-BLOCK in the example pack.
conditionstringAn expression over state, for example state.has_ssn == True or state.has_email == True or state.has_phone == True.
actionstringOne of actions.
descriptionstringBecomes the result's reason. Quote it.
severitystringfatal, warning or info.

Severities#

In YAMLIn resultsMeaning
fatalFATALThe payload must not proceed, remedied or not.
warningWARNINGThe payload may proceed after the remedy is applied.
infonot emittedDocumentation only.

Action naming#

PrefixMeaningExamples
permit_Proceed unchanged.permit_clean_payload
redact_Proceed with remedy.clean_text.redact_and_permit_contact_pii, redact_<rule id>
block_Stop.block_glba_ssn_leakage, block_<rule id>, block_custom_rule_<literal>

Name your rule IDs in lower case with underscores (project_code) so the generated action names read well. Branch on trigger severity rather than parsing action names.

Compile-time checks#

helixor-pack compile fails with an error when:

  • the file is not valid YAML, or its root is not a mapping (CompilerError);
  • pack_id is missing (CompilerError);
  • your license neither lists the pack_id in licensed_packs nor has the custom_playbook_compilation feature (LicenseEntitlementError);
  • a declared solver is not in licensed_solvers (LicenseEntitlementError), or the solver declarations cannot be read (PlaybookParseError, a CompilerError);
  • a rule has no id, an unsupported type or action, no pattern, or a pattern that is not a valid regular expression; or a codon or hard rule is not one of the example pack's built-in ones, unchanged (UnsupportedPackDeclarationError, which lists every problem).

It does not check action names against actions, or the contents of invariants and remedies. See Playbooks and Testing policies.