Specification · v1

Test vectors

Every case below, and every contract on the examples page, is run through ulang-lite 61af4281ed when this site is built. Each result shown is what that run produced. Use them to check another implementation, or your own understanding.

Download: test-vectors.json. Each vector is { id, title, source, expect }. expect is either { ok: true, contracts: [{ name, digest, canonical }] } plus any decisions, or { ok: false, kind, code, line, column }.

expense Expense approval valid
// Expense approvals: who may approve, and up to how much.
CONTRACT ExpenseApproval {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Expense {
      amount: float
      approver_is_submitter: bool
      approver_limit: float
      receipt_attached: bool
      category: string
    }
    CONSTANTS {
      receipt_threshold: float == 75.0 [SOURCE:FIN-POLICY-4.2]
      hard_cap: float == 10000.0 [SOURCE:FIN-POLICY-4.1]
    }
  }
  TRIGGER {
    approve_expense()
  }
  GUARANTEE {
    ENSURE approve_expense() WHEN Expense.receipt_attached == true OR Expense.amount < receipt_threshold [SOURCE:receipt_required]
  }
  PROHIBITION {
    FORBID approve_expense WHEN Expense.approver_is_submitter == true [SOURCE:no_self_approval]
    FORBID approve_expense WHEN Expense.amount > hard_cap [SOURCE:over_hard_cap]
    FORBID approve_expense WHEN Expense.amount > Expense.approver_limit [SOURCE:over_approver_limit]
    FORBID approve_expense WHEN Expense.category == "gift_card" [SOURCE:no_gift_cards]
  }
  OBSERVABILITY {
    LOG "expense approval decided" ON decision
  }
}

valid ExpenseApproval 5 clauses · sha256 5a6326d24470e02c54a4f175994a1b0c2c4a6efa08baec2c025b0af1fc78e7fd

RequestActionFactsVerdictClause
within limits, receipt attachedapprove_expense{"amount":120,"approver_is_submitter":false,"approver_limit":500,"receipt_attached":true,"category":"travel"}PERMITExpenseApproval.approve_expense.permit
approver submitted itapprove_expense{"amount":120,"approver_is_submitter":true,"approver_limit":500,"receipt_attached":true,"category":"travel"}DENYExpenseApproval.no_self_approval
above the approver’s limitapprove_expense{"amount":800,"approver_is_submitter":false,"approver_limit":500,"receipt_attached":true,"category":"travel"}DENYExpenseApproval.over_approver_limit
no receipt above the thresholdapprove_expense{"amount":120,"approver_is_submitter":false,"approver_limit":500,"receipt_attached":false,"category":"travel"}DENYExpenseApproval.receipt_required
no receipt, under the thresholdapprove_expense{"amount":40,"approver_is_submitter":false,"approver_limit":500,"receipt_attached":false,"category":"travel"}PERMITExpenseApproval.approve_expense.permit
self-approval and no receipt: prohibitions are checked firstapprove_expense{"amount":120,"approver_is_submitter":true,"approver_limit":500,"receipt_attached":false,"category":"travel"}DENYExpenseApproval.no_self_approval
comment-absorbed A comment after an operand becomes part of it unsupported[unknown-name]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  PROHIBITION {
    FORBID grant WHEN Request.count <= zero // must be non-empty
      [SOURCE:claim_nonempty]
  }
}

rejected unsupported[unknown-name] at 19:40 unknown name zero // must be non-empty

not-inside-name NOT inside a name is refused before parsing unsupported[not-operator]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      CANNOT_MERGE: bool
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.CANNOT_MERGE == false [SOURCE:mergeable]
  }
}

rejected unsupported[not-operator] at 5:10 NOT is refused before recursive parsing

constants Constants: hard, typed, sourced; floats may be negative or use an exponent valid
CONTRACT Thermostat {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Reading {
      celsius: float
      sensor_ok: bool
    }
    CONSTANTS {
      floor_c: float == -40.0 [SOURCE:SPEC-7]
      ceiling_c: float == 1.2e2 [SOURCE:SPEC-7]
    }
  }
  TRIGGER {
    accept_reading()
  }
  GUARANTEE {
    ENSURE accept_reading() WHEN Reading.sensor_ok == true [SOURCE:sensor_healthy]
  }
  PROHIBITION {
    FORBID accept_reading WHEN Reading.celsius < floor_c OR Reading.celsius > ceiling_c [SOURCE:out_of_range]
  }
}

valid Thermostat 2 clauses · sha256 46b2bd81659c2d927d909f163fe452baf44c8a0057eaf2ce646c24a80b8ba53a

RequestActionFactsVerdictClause
in rangeaccept_reading{"celsius":21.5,"sensor_ok":true}PERMITThermostat.accept_reading.permit
below the flooraccept_reading{"celsius":-41,"sensor_ok":true}DENYThermostat.out_of_range
sensor unhealthyaccept_reading{"celsius":21.5,"sensor_ok":false}DENYThermostat.sensor_healthy
depth-16 16 comparisons in a flat AND chain: depth 16, accepted valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count != 0 AND Request.count != 1 AND Request.count != 2 AND Request.count != 3 AND Request.count != 4 AND Request.count != 5 AND Request.count != 6 AND Request.count != 7 AND Request.count != 8 AND Request.count != 9 AND Request.count != 10 AND Request.count != 11 AND Request.count != 12 AND Request.count != 13 AND Request.count != 14 AND Request.count != 15 [SOURCE:long_chain]
  }
}

valid Claim 2 clauses · sha256 cd6fcc39d39a158e1a07629a7421a2fd2d6ff8db20478bb73bb6d72a0baa2be8

depth-17 17 comparisons: depth 17, refused limit[condition-depth]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count != 0 AND Request.count != 1 AND Request.count != 2 AND Request.count != 3 AND Request.count != 4 AND Request.count != 5 AND Request.count != 6 AND Request.count != 7 AND Request.count != 8 AND Request.count != 9 AND Request.count != 10 AND Request.count != 11 AND Request.count != 12 AND Request.count != 13 AND Request.count != 14 AND Request.count != 15 AND Request.count != 16 [SOURCE:long_chain]
  }
}

rejected limit[condition-depth] at 22:23 condition depth exceeded

diag-section-order Sections out of order syntax[syntax]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  TRIGGER {
    grant()
  }
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected syntax[syntax] at 6:3 expected '}' closing the contract (sections must appear in the order ENFORCEMENT_MODE, CONTEXT, TRIGGER, GUARANTEE, PROHIBITION, OBSERVABILITY, each at most once), found 'CONTEXT'

diag-soft-constant A soft constant (=) is refused unsupported[constant-invalid]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int = 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[constant-invalid] at 12:7 duplicate/invalid/non-hard constant

diag-string-order Strings cannot be ordered unsupported[kind-mismatch]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.region > "eu" [SOURCE:region]
  }
}

rejected unsupported[kind-mismatch] at 22:23 comparison type mismatch or ordering of nonnumbers

diag-ungoverned Every triggered action needs a clause semantic[ungoverned-action]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
    revoke()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[ungoverned-action] at 15:3 every trigger action requires an executable clause

diag-assignment A single = is an assignment, not a comparison unsupported[condition-form]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready = true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[condition-form] at 19:25 only typed comparisons and AND/OR are supported

canonical-before Any layout, comments and spellings… valid
# layout, comments and spelling do not matter to the digest
CONTRACT   Thermostat{ENFORCEMENT_MODE:ENFORCED
  CONTEXT { ENTITIES Reading { celsius: float
      sensor_ok: bool  retries: int }
    CONSTANTS { ceiling_c: float == 1.2e2 [SOURCE:  SPEC-7 ]
      max_retries: int == 003 [SOURCE:SPEC-9] } }
  TRIGGER { accept_reading( ) }
  GUARANTEE { ENSURE accept_reading() WHEN (Reading.sensor_ok == TRUE) [SOURCE:sensor_healthy] }
  PROHIBITION {
    // over range, or retried too often while unhealthy
    FORBID accept_reading() WHEN Reading.celsius > ceiling_c OR (Reading.retries >= max_retries AND (Reading.sensor_ok == FALSE)) [SOURCE:reject_reading]
  }
}

valid Thermostat 2 clauses · sha256 dfd61b1c80460b5a1e1142a5f5f39bb178d6cc015b846730d52049434c2d0f36

keyword-prefix-name CONTRACTX { is the contract X valid
CONTRACTX {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid X 2 clauses · sha256 faa8a3ad45a3289f43a2da6b10a41daf39b4e66c0d84e2a3bd62b46a9100892d

Same digest as keyword-prefix-spaced.

keyword-prefix-spaced The same contract, spaced valid
CONTRACT X {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid X 2 clauses · sha256 faa8a3ad45a3289f43a2da6b10a41daf39b4e66c0d84e2a3bd62b46a9100892d

android ANDROID reads as AND ROID unsupported[literal-comparison]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count == 1 ANDROID == 2 [SOURCE:x]
  }
}

rejected unsupported[literal-comparison] at 22:45 literal comparisons must name a fact field

integer-type integer reads as int then eger syntax[syntax]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: integer
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected syntax[syntax] at 6:5 expected ':' after the field name, found '}'

hash-comment # starts a comment valid
# a comment
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid Claim 2 clauses · sha256 7f34e8634265f53f0c4870553ea618ab5bf02811d79ae9ac8feed7a73996b647

Same digest as minimal.

minimal The template contract valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid Claim 2 clauses · sha256 7f34e8634265f53f0c4870553ea618ab5bf02811d79ae9ac8feed7a73996b647

RequestActionFactsVerdictClause
ready, under the capgrant{"count":3,"region":"eu","ready":true,"ratio":0.5}PERMITClaim.grant.permit
over the capgrant{"count":30,"region":"eu","ready":true,"ratio":0.5}DENYClaim.over_cap
forbid-parens FORBID grant() is the same clause as FORBID grant valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant() WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid Claim 2 clauses · sha256 7f34e8634265f53f0c4870553ea618ab5bf02811d79ae9ac8feed7a73996b647

Same digest as minimal.

no-escapes Strings have no escapes: \" ends the string syntax[syntax]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.region == "a\"b" [SOURCE:region]
  }
}

rejected syntax[syntax] at 22:45 expected FORBID or '}', found 'b'

float-exponent-int An exponent makes a float: 1e3 cannot be an int constant unsupported[constant-invalid]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 1e3 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[constant-invalid] at 12:7 duplicate/invalid/non-hard constant

plus-exponent 1e+3 is refused: + is arithmetic unsupported[arithmetic]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: float == 1e+3 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[arithmetic] at 12:23 arithmetic is refused before recursive parsing

negative-int-constant Integer constants are 0 … 2^53-1 unsupported[constant-invalid]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == -5 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[constant-invalid] at 12:7 duplicate/invalid/non-hard constant

negative-int-literal Negative integer literals are fine in conditions valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count < -5 [SOURCE:negative]
  }
}

valid Claim 2 clauses · sha256 365efb1d6abc67630059c452a5bed50876c583f2ec59bf96e80995338b987515

integer-range 2^53 is outside the exact domain limit[integer-range]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > 9007199254740992 [SOURCE:huge]
  }
}

rejected limit[integer-range] at 22:39 integer literal outside exact JSON domain

subtraction - 1 is arithmetic unsupported[arithmetic]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap - 1 [SOURCE:x]
  }
}

rejected unsupported[arithmetic] at 22:43 arithmetic is refused before recursive parsing

subtraction-tight cap -1 parses as subtraction, then is refused unsupported[call-or-arithmetic]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap -1 [SOURCE:x]
  }
}

rejected unsupported[call-or-arithmetic] at 22:43 calls, lists and arithmetic are unsupported

not NOT is refused unsupported[not-operator]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN NOT Request.ready == true [SOURCE:x]
  }
}

rejected unsupported[not-operator] at 22:23 NOT is refused before recursive parsing

call Calls are refused unsupported[call-or-arithmetic]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN len(Request.region) > 2 [SOURCE:x]
  }
}

rejected unsupported[call-or-arithmetic] at 22:23 calls, lists and arithmetic are unsupported

bare-operand A bare operand is not a condition unsupported[condition-form]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[condition-form] at 19:25 only typed comparisons and AND/OR are supported

trigger-guard Triggers take no guard unsupported[trigger-form]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant() WHEN Request.ready == true
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[trigger-form] at 16:5 TRIGGER supports unguarded named calls only

trigger-bare Triggers need parentheses unsupported[trigger-form]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[trigger-form] at 16:5 TRIGGER supports unguarded named calls only

trigger-params Triggers take no parameters unsupported[trigger-params]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant(Request.count)
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[trigger-params] at 16:5 TRIGGER calls take no parameters

ensure-no-parens ENSURE keeps its parentheses unsupported[ensure-form]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[ensure-form] at 19:5 GUARANTEE supports ENSURE action() WHEN predicate [SOURCE:id] only

empty-guarantee An empty GUARANTEE block semantic[empty-guarantee]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[empty-guarantee] at 18:3 GUARANTEE block of Claim has no ENSURE clauses

no-guarantee GUARANTEE may be absent valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid Claim 1 clause · sha256 d425f6e5308e2a5e50c888a4947f97493a3553661bcdc8c0349acd81adf7e4c4

advisory Modes other than enforced are refused by default semantic[enforcement-mode]
CONTRACT Claim {
  ENFORCEMENT_MODE: advisory
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[enforcement-mode] at 2:3 all contracts must use ENFORCEMENT_MODE: enforced

two-entities Exactly one ENTITIES block semantic[entity]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    ENTITIES Other {
      x: int
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[entity] at 3:3 wrong facts entity

duplicate-field Field names are unique semantic[fields]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      count: int
      ready: bool
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[fields] at 4:5 CONTEXT must exactly match Request facts schema

collides A constant may not share a field’s name semantic[constant-collides]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      cap: int == 25 [SOURCE:POLICY]
      count: int == 1 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[constant-collides] at 10:5 constant collides with field

duplicate-id Clause ids are unique across ENSURE and FORBID semantic[clause-id]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:must_be_ready]
  }
}

rejected semantic[clause-id] at 22:5 invalid/duplicate clause ID or unknown clause action

spaced-tag [ SOURCE: with a space is not a valid clause id semantic[clause-id]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [ SOURCE:over_cap]
  }
}

rejected semantic[clause-id] at 22:5 invalid/duplicate clause ID or unknown clause action

foreign Only the contract’s own entity resolves unsupported[foreign-reference]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Other.count > cap [SOURCE:x]
  }
}

rejected unsupported[foreign-reference] at 22:23 arithmetic, functions and foreign fields unsupported

unknown-field Unknown field unsupported[unknown-field]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.nope > cap [SOURCE:x]
  }
}

rejected unsupported[unknown-field] at 22:23 unknown field Request.nope

group-value A parenthesised value parses, then is refused unsupported[foreign-reference]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > (25) [SOURCE:x]
  }
}

rejected unsupported[foreign-reference] at 22:39 arithmetic, functions and foreign fields unsupported

constant-literal constant op literal is refused unsupported[literal-comparison]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN cap == 25 [SOURCE:x]
  }
}

rejected unsupported[literal-comparison] at 22:23 literal comparisons must name a fact field

literal-constant literal op constant is accepted (only the other order is refused) valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN 25 == cap [SOURCE:x]
  }
}

valid Claim 2 clauses · sha256 c60dc3c50e70cff315e863bc081f12968551efb42c10d0491ce1a48f37f4a0ba

bool-ordering Booleans compare only with == / != unsupported[kind-mismatch]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.ready < true [SOURCE:x]
  }
}

rejected unsupported[kind-mismatch] at 22:23 comparison type mismatch or ordering of nonnumbers

string-path-path String comparisons must be field op literal unsupported[nonnumeric-comparison]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      home: string
      ready: bool
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.region != Request.home [SOURCE:x]
  }
}

rejected unsupported[nonnumeric-comparison] at 22:23 nonnumeric comparisons require a field and literal

float-equality Numeric == tolerates last-bit noise valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.ratio == 0.3 [SOURCE:ratio_point_three]
  }
}

valid Claim 2 clauses · sha256 329e566997017a2143d420aaecc56eac7dc490de8cd43e19cabc589f3fae34d5

RequestActionFactsVerdictClause
ratio = 0.1 + 0.2 = 0.30000000000000004grant{"count":1,"region":"eu","ready":true,"ratio":0.30000000000000004}DENYClaim.ratio_point_three
ratio = 0.3000001grant{"count":1,"region":"eu","ready":true,"ratio":0.3000001}PERMITClaim.grant.permit
nesting Nesting deeper than 20 is refused before parsing limit[nesting-or-tokens]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN (((((((((((((((((((((Request.count > cap))))))))))))))))))))) [SOURCE:x]
  }
}

rejected limit[nesting-or-tokens] at 22:41 source nesting or token cap exceeded

two-contracts Two contracts in one source valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

CONTRACT Other {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid Claim 2 clauses · sha256 7f34e8634265f53f0c4870553ea618ab5bf02811d79ae9ac8feed7a73996b647

valid Other 2 clauses · sha256 bd91ffba528870bed0355edecd243de6a13350e73ae069ec0c03c3f21b2ee107

duplicate-contract Contract names are unique within a source semantic[duplicate-contract]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[duplicate-contract] at 26:1 duplicate contract Claim

empty An empty source limit[source-size]

rejected limit[source-size] at 1:1 empty or oversized source

type-comment A comment after a type becomes part of it unsupported[type-unsupported]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int // paths requested
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected unsupported[type-unsupported] at 5:14 only primitive fact types supported

bom A byte-order mark is not white space syntax[syntax]
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected syntax[syntax] at 1:1 expected CONTRACT, found ''

no-mode A contract without a mode is refused semantic[enforcement-mode]
CONTRACT Claim {
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

rejected semantic[enforcement-mode] at 1:1 all contracts must use ENFORCEMENT_MODE: enforced

errata-e1 Errata E1: a constant tagged [ SOURCE:P] is accepted, but its canonical text does not re-parse valid
CONTRACT Claim {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Request {
      count: int
      region: string
      ready: bool
      ratio: float
    }
    CONSTANTS {
      zero: int == 0 [SOURCE:POLICY]
      cap: int == 25 [ SOURCE:POLICY]
    }
  }
  TRIGGER {
    grant()
  }
  GUARANTEE {
    ENSURE grant() WHEN Request.ready == true [SOURCE:must_be_ready]
  }
  PROHIBITION {
    FORBID grant WHEN Request.count > cap [SOURCE:over_cap]
  }
}

valid Claim 2 clauses · sha256 1ba3c884488e6b7df67a6335f5ba226e18b175b8194f636ac93f8dd3e570a09e

tut-1 Step 1: the facts semantic[trigger-required]
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
  }
}

rejected semantic[trigger-required] at 1:1 explicit TRIGGER action list required

tut-2 Step 2: the action semantic[ungoverned-action]
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
  }
  TRIGGER {
    deploy()
  }
}

rejected semantic[ungoverned-action] at 13:3 every trigger action requires an executable clause

tut-3 Step 3: a first rule valid
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
  }
  TRIGGER {
    deploy()
  }
  PROHIBITION {
    FORBID deploy WHEN DeployRequest.author_approved_own_change == true [SOURCE:no_self_approval]
  }
}

valid ProductionDeploy 1 clause · sha256 4b1ab28648aa677d0e199d0c53d3573bd48ecd26746e7123b63d29b9d14335b2

RequestActionFactsVerdictClause
a normal deploydeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}PERMITProductionDeploy.deploy.permit
the author approved their own changedeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":true,"error_rate_pct":0.4,"change_freeze":false}DENYProductionDeploy.no_self_approval
tut-4 Step 4: guarantees valid
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
  }
  TRIGGER {
    deploy()
  }
  GUARANTEE {
    ENSURE deploy() WHEN DeployRequest.tests_passed == true [SOURCE:tests_green]
    ENSURE deploy() WHEN DeployRequest.approvals >= 2 [SOURCE:two_approvals]
  }
  PROHIBITION {
    FORBID deploy WHEN DeployRequest.author_approved_own_change == true [SOURCE:no_self_approval]
  }
}

valid ProductionDeploy 3 clauses · sha256 64a8766dab399915424f1024b1b38b353f7c27bc0dbfe03702bff58654149e49

RequestActionFactsVerdictClause
a normal deploydeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}PERMITProductionDeploy.deploy.permit
tests failingdeploy{"environment":"production","tests_passed":false,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}DENYProductionDeploy.tests_green
one approvaldeploy{"environment":"production","tests_passed":true,"approvals":1,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}DENYProductionDeploy.two_approvals
tut-5 Step 5: named, sourced constants valid
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
    CONSTANTS {
      min_approvals: int == 2 [SOURCE:ENG-HANDBOOK-7.1]
      max_error_rate_pct: float == 1.5 [SOURCE:SRE-SLO-3]
    }
  }
  TRIGGER {
    deploy()
  }
  GUARANTEE {
    ENSURE deploy() WHEN DeployRequest.tests_passed == true [SOURCE:tests_green]
    ENSURE deploy() WHEN DeployRequest.approvals >= min_approvals [SOURCE:two_approvals]
  }
  PROHIBITION {
    FORBID deploy WHEN DeployRequest.author_approved_own_change == true [SOURCE:no_self_approval]
    FORBID deploy WHEN DeployRequest.error_rate_pct > max_error_rate_pct [SOURCE:error_budget]
  }
}

valid ProductionDeploy 4 clauses · sha256 ed486438406d7f6025ff25851429dce5708b2d83bb7ef4d2b5ec7fb83f6cc8d8

RequestActionFactsVerdictClause
a normal deploydeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}PERMITProductionDeploy.deploy.permit
error rate 2.5%deploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":2.5,"change_freeze":false}DENYProductionDeploy.error_budget
error rate exactly 1.5%deploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":1.5,"change_freeze":false}PERMITProductionDeploy.deploy.permit
tut-6 Step 6: combining conditions valid
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
    CONSTANTS {
      min_approvals: int == 2 [SOURCE:ENG-HANDBOOK-7.1]
      max_error_rate_pct: float == 1.5 [SOURCE:SRE-SLO-3]
    }
  }
  TRIGGER {
    deploy()
  }
  GUARANTEE {
    ENSURE deploy() WHEN DeployRequest.tests_passed == true [SOURCE:tests_green]
    ENSURE deploy() WHEN DeployRequest.approvals >= min_approvals [SOURCE:two_approvals]
  }
  PROHIBITION {
    FORBID deploy WHEN DeployRequest.change_freeze == true AND DeployRequest.environment == "production" [SOURCE:change_freeze]
    FORBID deploy WHEN DeployRequest.author_approved_own_change == true [SOURCE:no_self_approval]
    FORBID deploy WHEN DeployRequest.error_rate_pct > max_error_rate_pct [SOURCE:error_budget]
  }
}

valid ProductionDeploy 5 clauses · sha256 c6011a1c7c5a6458f4baeeb28608decb7f3f5fe6f4e6a4e27343b768ba526f3c

RequestActionFactsVerdictClause
a normal deploydeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}PERMITProductionDeploy.deploy.permit
freeze, productiondeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":true}DENYProductionDeploy.change_freeze
freeze, stagingdeploy{"environment":"staging","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":true}PERMITProductionDeploy.deploy.permit
tut-7 Step 7: a second action valid
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
    CONSTANTS {
      min_approvals: int == 2 [SOURCE:ENG-HANDBOOK-7.1]
      max_error_rate_pct: float == 1.5 [SOURCE:SRE-SLO-3]
    }
  }
  TRIGGER {
    deploy()
    rollback()
  }
  GUARANTEE {
    ENSURE deploy() WHEN DeployRequest.tests_passed == true [SOURCE:tests_green]
    ENSURE deploy() WHEN DeployRequest.approvals >= min_approvals [SOURCE:two_approvals]
  }
  PROHIBITION {
    FORBID deploy WHEN DeployRequest.change_freeze == true AND DeployRequest.environment == "production" [SOURCE:change_freeze]
    FORBID deploy WHEN DeployRequest.author_approved_own_change == true [SOURCE:no_self_approval]
    FORBID deploy WHEN DeployRequest.error_rate_pct > max_error_rate_pct [SOURCE:error_budget]
    FORBID rollback WHEN DeployRequest.environment != "production" AND DeployRequest.environment != "staging" [SOURCE:known_environments]
  }
}

valid ProductionDeploy 6 clauses · sha256 972a43946ba6393d9189b1f896d9411feabc11ae5d3e30747fe79dc7c2b374de

RequestActionFactsVerdictClause
roll back productionrollback{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}PERMITProductionDeploy.rollback.permit
roll back an unknown environmentrollback{"environment":"dev","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}DENYProductionDeploy.known_environments
roll back during a freezerollback{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":true}PERMITProductionDeploy.rollback.permit
tut-final policy/deploy.ul valid
// Production deploys: who may ship, and when.
CONTRACT ProductionDeploy {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES DeployRequest {
      environment: string
      tests_passed: bool
      approvals: int
      author_approved_own_change: bool
      error_rate_pct: float
      change_freeze: bool
    }
    CONSTANTS {
      min_approvals: int == 2 [SOURCE:ENG-HANDBOOK-7.1]
      max_error_rate_pct: float == 1.5 [SOURCE:SRE-SLO-3]
    }
  }
  TRIGGER {
    deploy()
    rollback()
  }
  GUARANTEE {
    ENSURE deploy() WHEN DeployRequest.tests_passed == true [SOURCE:tests_green]
    ENSURE deploy() WHEN DeployRequest.approvals >= min_approvals [SOURCE:two_approvals]
  }
  PROHIBITION {
    FORBID deploy WHEN DeployRequest.change_freeze == true AND DeployRequest.environment == "production" [SOURCE:change_freeze]
    FORBID deploy WHEN DeployRequest.author_approved_own_change == true [SOURCE:no_self_approval]
    FORBID deploy WHEN DeployRequest.error_rate_pct > max_error_rate_pct [SOURCE:error_budget]
    FORBID rollback WHEN DeployRequest.environment != "production" AND DeployRequest.environment != "staging" [SOURCE:known_environments]
  }
  OBSERVABILITY {
    LOG "deploy decision" ON decision
  }
}

valid ProductionDeploy 6 clauses · sha256 686358ddc154b77b5b7b3a24870b8dd6f79b23d376ed039d6824a923284e4059

RequestActionFactsVerdictClause
a normal deploydeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}PERMITProductionDeploy.deploy.permit
freeze and self-approved: the first FORBID winsdeploy{"environment":"production","tests_passed":true,"approvals":2,"author_approved_own_change":true,"error_rate_pct":0.4,"change_freeze":true}DENYProductionDeploy.change_freeze
self-approved and tests failing: FORBID before ENSUREdeploy{"environment":"production","tests_passed":false,"approvals":2,"author_approved_own_change":true,"error_rate_pct":0.4,"change_freeze":false}DENYProductionDeploy.no_self_approval
tests failing and one approval: the first ENSURE that failsdeploy{"environment":"production","tests_passed":false,"approvals":1,"author_approved_own_change":false,"error_rate_pct":0.4,"change_freeze":false}DENYProductionDeploy.tests_green
pat-not-bad NOT is refused before parsing unsupported[not-operator]
CONTRACT Publish {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Article {
      reviewed: bool
      word_count: int
      status: string
    }
  }
  TRIGGER {
    publish()
  }
  PROHIBITION {
    FORBID publish WHEN NOT Article.reviewed == true [SOURCE:needs_review]
  }
}

rejected unsupported[not-operator] at 14:25 NOT is refused before recursive parsing

pat-not Say it with the opposite comparison valid
CONTRACT Publish {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Article {
      reviewed: bool
      word_count: int
      status: string
    }
  }
  TRIGGER {
    publish()
  }
  PROHIBITION {
    FORBID publish WHEN Article.reviewed == false [SOURCE:needs_review]
    FORBID publish WHEN Article.word_count < 300 [SOURCE:too_short]
    FORBID publish WHEN Article.status != "ready" AND Article.status != "scheduled" [SOURCE:wrong_status]
  }
}

valid Publish 3 clauses · sha256 e21f874658d8a743229e186939fa8b3baf72548147242642ca341549fc6c8987

RequestActionFactsVerdictClause
reviewed, 800 words, readypublish{"reviewed":true,"word_count":800,"status":"ready"}PERMITPublish.publish.permit
not reviewedpublish{"reviewed":false,"word_count":800,"status":"ready"}DENYPublish.needs_review
a draftpublish{"reviewed":true,"word_count":800,"status":"draft"}DENYPublish.wrong_status
pat-allowlist Allow-list of strings valid
CONTRACT Shipping {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Shipment {
      country: string
      weight_kg: float
      hazardous: bool
    }
    CONSTANTS {
      max_weight_kg: float == 30.0 [SOURCE:CARRIER-TERMS-2]
    }
  }
  TRIGGER {
    ship()
  }
  PROHIBITION {
    FORBID ship WHEN Shipment.country != "US" AND Shipment.country != "CA" AND Shipment.country != "MX" [SOURCE:ship_regions]
    FORBID ship WHEN Shipment.hazardous == true OR Shipment.weight_kg > max_weight_kg [SOURCE:carrier_limits]
  }
}

valid Shipping 2 clauses · sha256 849104d027b84a94dfdbc5ee0739dd33fa5c7f66143d5761e05f8ee9e07132f4

RequestActionFactsVerdictClause
US, 2 kgship{"country":"US","weight_kg":2,"hazardous":false}PERMITShipping.ship.permit
Franceship{"country":"FR","weight_kg":2,"hazardous":false}DENYShipping.ship_regions
"us" in lower caseship{"country":"us","weight_kg":2,"hazardous":false}DENYShipping.ship_regions
Canada, 31 kgship{"country":"CA","weight_kg":31,"hazardous":false}DENYShipping.carrier_limits
pat-range A range: inside with ENSURE, outside with FORBID valid
CONTRACT Setpoint {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Change {
      celsius: float
      operator_certified: bool
    }
    CONSTANTS {
      min_c: float == 5.0 [SOURCE:SAFETY-1]
      max_c: float == 28.0 [SOURCE:SAFETY-1]
    }
  }
  TRIGGER {
    set_temperature()
  }
  GUARANTEE {
    ENSURE set_temperature() WHEN Change.celsius >= min_c AND Change.celsius <= max_c [SOURCE:in_range]
  }
  PROHIBITION {
    FORBID set_temperature WHEN Change.celsius > 24.0 AND Change.operator_certified == false [SOURCE:certified_above_24]
  }
}

valid Setpoint 2 clauses · sha256 a55e62765e7467b7cd7309c8219c9af2f7dd80d6ee9a7e6b53a9958ab2c75cc4

RequestActionFactsVerdictClause
21 °Cset_temperature{"celsius":21,"operator_certified":false}PERMITSetpoint.set_temperature.permit
3 °Cset_temperature{"celsius":3,"operator_certified":false}DENYSetpoint.in_range
26 °C, not certifiedset_temperature{"celsius":26,"operator_certified":false}DENYSetpoint.certified_above_24
26 °C, certifiedset_temperature{"celsius":26,"operator_certified":true}PERMITSetpoint.set_temperature.permit
pat-two-fields Compare two facts valid
CONTRACT Purchasing {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Purchase {
      amount_cents: int
      remaining_budget_cents: int
      vendor_approved: bool
    }
  }
  TRIGGER {
    purchase()
  }
  GUARANTEE {
    ENSURE purchase() WHEN Purchase.vendor_approved == true [SOURCE:approved_vendor]
  }
  PROHIBITION {
    FORBID purchase WHEN Purchase.amount_cents > Purchase.remaining_budget_cents [SOURCE:over_budget]
  }
}

valid Purchasing 2 clauses · sha256 80232a79bb4efcf53f35bbfb38f7695e895ebc466f44c79190a4c0c6576a6bd2

RequestActionFactsVerdictClause
$50 of $200 leftpurchase{"amount_cents":5000,"remaining_budget_cents":20000,"vendor_approved":true}PERMITPurchasing.purchase.permit
$250 of $200 leftpurchase{"amount_cents":25000,"remaining_budget_cents":20000,"vendor_approved":true}DENYPurchasing.over_budget
pat-derived-bad Arithmetic is refused unsupported[arithmetic]
CONTRACT Quota {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Usage {
      used: int
      requested: int
      limit: int
    }
  }
  TRIGGER {
    reserve()
  }
  PROHIBITION {
    FORBID reserve WHEN Usage.used + Usage.requested > Usage.limit [SOURCE:quota]
  }
}

rejected unsupported[arithmetic] at 14:36 arithmetic is refused before recursive parsing

pat-derived Compute it in the application, decide it in the contract valid
CONTRACT Quota {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Usage {
      used: int
      requested: int
      projected: int
      limit: int
    }
  }
  TRIGGER {
    reserve()
  }
  PROHIBITION {
    FORBID reserve WHEN Usage.projected > Usage.limit [SOURCE:quota]
  }
}

valid Quota 1 clause · sha256 04b0f1188e1e0b8f95d4e1039faa609a6e8df7b9afb4751d95d7f8071f4d3427

RequestActionFactsVerdictClause
70 used + 20 requestedreserve{"used":70,"requested":20,"projected":90,"limit":100}PERMITQuota.reserve.permit
70 used + 40 requestedreserve{"used":70,"requested":40,"projected":110,"limit":100}DENYQuota.quota
pat-relation-bad Two string facts cannot be compared unsupported[nonnumeric-comparison]
CONTRACT Approvals {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Approval {
      approver_id: string
      requester_id: string
      approver_is_requester: bool
    }
  }
  TRIGGER {
    approve()
  }
  PROHIBITION {
    FORBID approve WHEN Approval.approver_id == Approval.requester_id [SOURCE:four_eyes]
  }
}

rejected unsupported[nonnumeric-comparison] at 14:25 nonnumeric comparisons require a field and literal

pat-relation Pass the relation as a boolean fact valid
CONTRACT Approvals {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Approval {
      approver_id: string
      requester_id: string
      approver_is_requester: bool
    }
  }
  TRIGGER {
    approve()
  }
  PROHIBITION {
    FORBID approve WHEN Approval.approver_is_requester == true [SOURCE:four_eyes]
  }
}

valid Approvals 1 clause · sha256 f6a9fe155f7924641bbe29b6427d5bd4681ae4656de70524db30ca0343940905

RequestActionFactsVerdictClause
someone else approvesapprove{"approver_id":"u-17","requester_id":"u-42","approver_is_requester":false}PERMITApprovals.approve.permit
the requester approvesapprove{"approver_id":"u-42","requester_id":"u-42","approver_is_requester":true}DENYApprovals.four_eyes
pat-time Time windows: the application supplies the clock valid
CONTRACT ChangeWindow {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Window {
      weekday: int
      hour_utc: int
    }
  }
  TRIGGER {
    deploy()
  }
  PROHIBITION {
    FORBID deploy WHEN Window.weekday >= 5 OR Window.hour_utc < 9 OR Window.hour_utc >= 17 [SOURCE:business_hours]
  }
}

valid ChangeWindow 1 clause · sha256 d218eaff9511e87499bbb84b769fb22e58eeca02d08cbe750b785fe7194aa438

RequestActionFactsVerdictClause
Tuesday 14:00deploy{"weekday":1,"hour_utc":14}PERMITChangeWindow.deploy.permit
Saturday 14:00deploy{"weekday":5,"hour_utc":14}DENYChangeWindow.business_hours
Tuesday 18:00deploy{"weekday":1,"hour_utc":18}DENYChangeWindow.business_hours
pat-order-a Most useful rule first valid
CONTRACT Payouts {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Account {
      frozen: bool
      amount_cents: int
      balance_cents: int
    }
  }
  TRIGGER {
    withdraw()
  }
  PROHIBITION {
    FORBID withdraw WHEN Account.frozen == true [SOURCE:account_frozen]
    FORBID withdraw WHEN Account.amount_cents > Account.balance_cents [SOURCE:insufficient_funds]
  }
}

valid Payouts 2 clauses · sha256 7425e5b3fb960f154ecacc95d45edcd68073f269bb9180f80b14cbf5a2fbdf18

RequestActionFactsVerdictClause
frozen and overdrawnwithdraw{"frozen":true,"amount_cents":9000,"balance_cents":5000}DENYPayouts.account_frozen
pat-order-b The same rules, reversed valid
CONTRACT Payouts {
  ENFORCEMENT_MODE: enforced
  CONTEXT {
    ENTITIES Account {
      frozen: bool
      amount_cents: int
      balance_cents: int
    }
  }
  TRIGGER {
    withdraw()
  }
  PROHIBITION {
    FORBID withdraw WHEN Account.amount_cents > Account.balance_cents [SOURCE:insufficient_funds]
    FORBID withdraw WHEN Account.frozen == true [SOURCE:account_frozen]
  }
}

valid Payouts 2 clauses · sha256 9ae8ce9470978d9eac4216cec9c931cbe47d616e382cff79b9f84326d254e1b0

RequestActionFactsVerdictClause
frozen and overdrawnwithdraw{"frozen":true,"amount_cents":9000,"balance_cents":5000}DENYPayouts.insufficient_funds