paybondpaybond
Sign in

Harbor predicate DSL

Supported predicate format, clause semantics, limits, and evaluation responses for Harbor evidence checks.

Harbor uses predicate_dsl to define the release rule attached to an intent. When evidence is later submitted, Harbor evaluates that evidence against the stored rule and returns a pass or fail result with an audit trace.

This format is intentionally narrow. It supports deterministic checks on the submitted evidence and on the intent budget, but it does not run arbitrary code, call external services, or read data from another tenant.

Use predicate_dsl when you want to send the rule inline on POST /intents. Use predicate_ref when you want a reusable, versioned tenant policy managed centrally. For the surrounding endpoints, see the Harbor API reference.

Where this appears

HTTPField / bodyRole
POST /intentspredicate_dsl (JSON object, used when predicate_ref is not provided)Stored on the intent and validated when the intent is created.
POST /intents/{id}/evidenceRequest payloadEvaluated as evidence JSON against the intent's stored predicate.
POST /intents/{id}/evidenceResponse predicate_evaluationReturns the evaluation result (passed and trace).

Harbor rejects malformed or oversized predicate documents at intent creation with 400 Bad Request. During evidence submission, business-rule mismatches usually return passed: false, while evidence-shape problems can return 422 Unprocessable Entity.

Product guarantees

  • Deterministic evaluation: the same predicate and evidence produce the same result.
  • Bounded execution: Harbor enforces fixed depth, path, and fuel limits so evaluation remains predictable.
  • Tenant-scoped inputs only: evaluation uses only the current intent, its declared evidence schema, and the submitted evidence payload.
  • Stable release rule: Harbor binds the predicate to the intent at creation time so the rule evaluated later is the same rule the parties approved.

For the broader isolation model, see Tenant model.

Document envelope

Every predicate document must include:

FieldTypeDescription
versionintegerDSL revision. Only 1 is supported today.
rootobjectRoot clause. Must include string field op.
{
  "version": 1,
  "root": { "op": "true" }
}

Treat unknown version values as unsupported.

Evidence paths

Paths are arrays of string keys into the submitted evidence JSON object. They support nested objects only.

Example:

{ "path": ["status"] }

reads payload.status, while:

{ "path": ["job", "result", "status"] }

reads payload.job.result.status.

Clauses (op)

All clauses are JSON objects with an op field in snake_case.

Boolean composition

opFieldsSemantics
trueAlways satisfied.
andclauses: array of clause objectsAll clauses must pass.
orclauses: array of clause objectsAt least one clause must pass.
notclause: single clause objectNegates the inner result.

Evidence checks

opFieldsSemantics
eqpath: string[], value: anyEvidence at path must equal value using JSON equality.
completionpath: string[], value: anySame as eq, but intended for completion-style checks such as status = completed.
ltepath: string[], limit_source: stringInteger at path must be less than or equal to a server-owned limit. Today the only supported value is "amount_cents", which compares against the intent amount.
budget_cappath: string[]Shorthand for checking that an integer field is less than or equal to amount_cents.

Schema-aware check

opFieldsSemantics
schema_fieldfield: string (non-empty)Top-level evidence key field must exist, and its JSON value type must match the type declared in evidence_schema.properties[field].type.

This is useful when you want to require a field without hard-coding one exact value. evidence_schema follows a minimal JSON Schema-style contract, for example:

{
  "type": "object",
  "properties": {
    "status": { "type": "string" },
    "cost": { "type": "integer" }
  }
}

Supported type values are null, boolean, string, integer, number, array, and object. An array of type strings is also allowed for multi-type fields.

Limits

These limits apply at both intent creation and evidence evaluation.

LimitValueApplies to
Max nesting depth (and / or / not)24Clause tree
Max fuel (AST nodes visited)256Whole document
Max path segments16path on eq, completion, lte, budget_cap
Max clauses length in and / or32Per operator

Evaluation result (predicate_evaluation)

On successful evidence submission, Harbor includes a predicate_evaluation object shaped like:

{
  "passed": true,
  "trace": [
    {
      "kind": "completion",
      "detail": "value matched",
      "data": { "path": "status", "passed": true, "expected": "completed", "observed": "completed" }
    }
  ]
}
FieldDescription
passedWhether the evidence satisfied the predicate.
traceOrdered evaluation steps that explain why Harbor passed or failed the rule.

Logical failures such as an eq mismatch return passed: false with a trace explaining what failed. That is different from a malformed request or invalid evidence shape.

Direct DSL vs managed policies

  • Use predicate_dsl when each intent carries its own inline rule.
  • Use predicate_ref when you want a reusable tenant policy with versioning, preview, and controlled rollout.
  • Managed policy lifecycle endpoints are part of the Harbor API reference.

Examples

Accept any evidence (useful for smoke tests):

{
  "version": 1,
  "root": { "op": "true" }
}

Require a completed status and keep cost within budget:

{
  "version": 1,
  "root": {
    "op": "and",
    "clauses": [
      { "op": "completion", "path": ["status"], "value": "completed" },
      { "op": "budget_cap", "path": ["cost"] }
    ]
  }
}

Evidence might be { "status": "completed", "cost": 5000 } with amount_cents >= 5000.

Require a declared field from the evidence schema:

{
  "version": 1,
  "root": { "op": "schema_field", "field": "invoice_id" }
}

Evidence must include top-level invoice_id, and evidence_schema.properties.invoice_id.type must describe its JSON type.

Version support

predicate_dsl.versionMeaning
1Current wire format (this page).