Skip to content

Data Namespaces (p., s., i., o., steps., submission.)

Whenever you write a rule in Validibot — a CEL assertion, a signal data path, a row rule on a Tabular step — you're reaching into one of six data namespaces. Each namespace holds a different kind of value, and you choose which one by the short prefix you put in front of the name: p., s., i., o., steps., or submission..

If you've ever written p.price > 0 or s.target_eui <= 60 and wondered what the p and s actually mean, this page is the one-stop explainer.

Validibot tip

You don't have to use the short prefix. p.price and payload.price mean the same thing. The short forms keep expressions readable; the long forms are there when you want to be explicit.

The six namespaces at a glance

Short Long What it holds Scope
p. payload. The raw file the submitter sent (JSON, XML, CSV cells, parsed RDF, …) Whole workflow
s. signal. The workflow's named vocabulary — values you've mapped or promoted Whole workflow
i. input. This step's inputs — facts the validator sees before it runs One step, before its run
o. output. This step's outputs — values the validator produced after running One step, after its run
steps.<key>.input. / steps.<key>.output. An earlier step's inputs or outputs, addressed by step key Whole workflow
submission. The submission envelope — metadata and server-stamped facts that live beside the file Whole workflow

The teaching analogy: think of each step as a function in a program.

  • i.* are the function's parameters.
  • o.* is what the function returns.
  • s.* is module-level state shared across functions.
  • p.* is the raw input the program started with.
  • submission.* is metadata about that input — who, when, what type, how big.
  • steps.foo.* is direct access to another function's parameters or return value.

When to reach for each one

p.* — the raw submission. Always present. Whatever the submitter sent, exactly as they sent it. p.price reads the price field of a JSON submission. For XML, attributes appear with an @ prefix (m["@Conductivity"]); see the CEL Expressions page for the XML rules.

s.* — the workflow's vocabulary. Named values any step can reference. You create them two ways:

  1. Workflow signal mapping — on the workflow's settings page, pick a name like target_eui, point it at a path in the submission, and it's available everywhere as s.target_eui.
  2. Promotion from a step — take an input or output of a particular step, click Copy to Signal, give it a workflow-wide name. From that point on, every step can reference it as s.<your_name>.

If you're writing steps.preflight.output.zone_count in more than one assertion, that's the cue to promote it — s.zone_count is stabler and shorter.

i.* — this step's inputs. Values the validator can see at the start of this step, before its main work runs. For an EnergyPlus step this is parser-extracted facts about the IDF (i.zone_count, i.idf_version). For a step with template variables, the resolved variable values land here. i.* is step-local — i.zone_count in one step is unrelated to i.zone_count in another.

o.* — this step's outputs. Values the validator produced after running. For an EnergyPlus step this is the simulation results (o.site_eui_kwh_m2, o.unmet_heating_hours). For a JSON Schema step there are usually no outputs — the validator just says pass or fail.

o.* is step-local and temporally bound: only available in output-stage assertions on the step that produced it. The assertion editor enforces this — when you're editing an input-stage assertion, autocomplete won't offer o.* references.

steps.<step_key>.input.* / steps.<step_key>.output.* — direct access to an earlier step's values by step key. Good for one-off cross-step references. For values you cite often, promote to s.* instead.

submission.* — the submission envelope. Context about the submission that lives beside the file rather than inside it, so it resolves the same way no matter what was uploaded — JSON, XML, CSV, or an RDF .ttl graph. Two flavours:

  • Submitter-provided (treat as untrusted): submission.name, submission.short_description, and the free-form submission.metadata.<key> bag. Whoever launched the run set these.
  • Server-stamped (trustworthy): submission.file_type, submission.size (bytes), submission.uploaded_at (a timestamp). Validibot sets these — a submitter can't forge them.

submission is long-only. There's no single-letter alias because s is already taken by signals.

When i.* and o.* are empty

A natural question: "Why are i.* and o.* sometimes empty?"

A step populates i.* or o.* only when its validator runs a process that transforms data. Three positions on the spectrum:

  • No process (JSON Schema, XML Schema, Basic) — assertions use p.* and optionally s.*. i.* and o.* are empty.
  • Process produces outputs only (SHACL, THERM) — the validator parses or evaluates the payload and emits results. Assertions primarily use o.*. i.* is empty.
  • Process has discrete input and output stages (EnergyPlus, FMU) — the validator extracts facts from the payload first (i.*), runs its main work, then emits results (o.*). Both stages are meaningful.

If you open a workflow step and the Inputs or Outputs panel is empty, that's intentional — it accurately reflects what the chosen validator does with your data.

A special case: row.*

There's one namespace that doesn't appear in the table above because it only exists in one place. Inside a row rule on a Tabular validator step, row.<column> refers to the current row's value for a declared column (row.min_depth <= row.max_depth), and the rule runs once per data row.

row.* isn't available anywhere else, and a row rule may only reference columns declared in the step's schema — typos are caught when you save the step, not on the next run.

Where to next

  • CEL Expressions — the full guide to writing rules over these namespaces, including all supported operators, Validibot helpers, and worked examples.
  • Tabular Validator — the only place row.* exists.
  • Glossary — formal definitions of signal, payload, submission, and friends.
Spotted a problem on this page? Report it or suggest an edit