Rule Cascade
Examples

OpenAPI contract

The payments API description and its ruleset bound to each other - entities reference schemas, operations carry x-rule-cascade, and baseline rules are derived from schema constraints.

Files: examples/contracts/payments.openapi.yaml, examples/contracts/payments-transfer.ruleset.yaml, examples/derived/. The full explanation is OpenAPI and Rule Cascade.

The API names its ruleset and tags each operation

examples/contracts/payments.openapi.yaml
# Root binding: which ruleset governs this API.
x-rule-cascade:
  ruleset: acme.payments.transfer
  version: ^1.0.0

paths:
  /transfers:
    post:
      operationId: createTransfer
      summary: Create a transfer
      x-rule-cascade: { entity: Transfer, operation: create }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/TransferRequest" }
      responses:
        "201":
          description: Created. Non-blocking findings are returned alongside the resource.
          content:
            application/json:
              schema: { $ref: "#/components/schemas/TransferEnvelope" }
        "422": { $ref: "#/components/responses/RuleViolation" }

Every operation the rules can deny declares a 422 response: RFC 9457 problem details extended with the evaluation result.

The ruleset references the schema and binds the operations

examples/contracts/payments-transfer.ruleset.yaml
entities:
  Transfer:
    schema: { $ref: "./payments.openapi.yaml#/components/schemas/Transfer" }
examples/contracts/payments-transfer.ruleset.yaml
bindings:
  openapi:
    - document: ./payments.openapi.yaml
      entity: Transfer
      operations:
        create: createTransfer
        read: getTransfer
        update: updateTransfer
        delete: deleteTransfer
        approve: approveTransfer

Because the entity references a component schema, a rule that reads a field the API does not have fails to load with PATH_UNKNOWN. Because both sides name each other, check reports BINDING_MISMATCH when they disagree, for example after a major version of the ruleset that the API still binds as ^1.0.0.

Baseline rules derived from the schema

required, enum, minLength, pattern, minimum, format and similar constraints become rules with codes, messages and field pointers:

rcas derive examples/catalog/onboarding.openapi.yaml \
  --schema Customer --id acme.generated.customer -o customer.ruleset.yaml

The generated rulesets and their golden tests are committed in examples/derived and checked in CI; a unit test fails when they are stale. The commands that produce them are in OpenAPI and Rule Cascade, section 3.

The evaluation API itself

The rule server's own HTTP API is described in OpenAPI 3.1: spec/v1/rule-evaluation.openapi.yaml. Its central operation, a dry run:

spec/v1/rule-evaluation.openapi.yaml
/evaluations:
  post:
    operationId: evaluateRules
    tags: [evaluation]
    summary: Evaluate an operation on an entity
    description: >
      Stateless and side-effect free. It returns a decision, findings, field effects
      and - only when the decision is allow - the commands the caller should execute
      after it has persisted the change.

The full description of every operation is on the rule server page and in OpenAPI and Rule Cascade.

On this page