Chio/Docs
LOGIN · JOIN

OpenAPI Integration

Look up how an OpenAPI document becomes tool definitions, which x-chio keys shape route policy, and what the protecting proxy answers.

Reference chio@5f63e6e

On this page

An OpenAPI document is the contract Chio reads to govern an existing HTTP API. Each operation becomes a tool definition for the bridge and a route with a default policy for the protecting proxy.

A tool definition describes one operation and grants nothing. Authority comes from the capability a caller presents, which the kernel checks on each request before the upstream sees it.

Synopsis

chio-openapi parses one OpenAPI 3.x document and returns one ToolDefinition per operation. tools_from_spec is its convenience entry point: it parses the document and generates its tools with the default configuration. chio api protect loads the same document into a route table and serves it as a reverse proxy in front of the upstream.

chio_openapi::tools_from_specrust
pub fn tools_from_spec(input: &str) -> Result<Vec<chio_core_types::ToolDefinition>>
Command synopsistext
chio api protect [OPTIONS] --upstream <UPSTREAM>

Tool generation pipeline

OpenAPI bridgeChoose an outcome.

κcapabilityσscopegguardsBbudget

The kernel admits the tool before the bridge sends HTTP

At startup the bridge compiles each OpenAPI operation into a named tool and a route binding. The kernel admits tools/call for createNote under the grant; the bridge then resolves the route, enforces the egress contract, and calls the HTTP dispatcher. The MCP result carries httpStatus, method, path, and body. Bridge OpenAPI to MCP.

One tools/call for a tool generated from an OpenAPI operation, through the MCP edge and the kernel to the OpenAPI bridge and its upstream API. Tool generation, redirects, and response-size checks are left out of the drawing.Bridge OpenAPI to MCP

The generator produces ToolDefinition values that conform to chio.manifest.v1: one per HTTP operation, a method and path pair. The output drives both the OpenAPI-to-MCP bridge and the chio api protect reverse proxy. The bridge resolves the route for an admitted call, applies its egress contract, and returns an MCP result carrying httpStatus, method, path, and body.

The parser resolves local references while it reads the document. The generator then merges path and operation parameters, reads extensions, skips unpublished operations when configured, and creates tool definitions: unsigned descriptions with annotations, which the caller registers. The proxy reads each operation's method and extensions separately to build its route policy, so an unpublished operation still has a route. The field mapping and the default policy give the exact rules.

Supported OpenAPI versions

The parser MUST accept specifications declaring version 3.0.x or 3.1.x in the top-level openapi field. The value MUST begin with 3..

The parser MUST reject specifications with any other version prefix with an UnsupportedVersion error. OpenAPI 2.0 (Swagger) documents fail this check.

Supported formats

The parser MUST accept both JSON and YAML input. Format detection is automatic: if the input, after leading whitespace, begins with {, the parser treats it as JSON; otherwise it treats the input as YAML. The caller passes no format flag.

Required top-level fields

A document MUST carry openapi, info, and paths. A missing field fails with MissingField("openapi"), MissingField("info"), or MissingField("paths").

When info.title is absent, the parser MUST default to "Untitled API". When info.version is absent, the parser MUST default to "0.0.0". The parser sorts paths by name, so the generated tool order is independent of the document's key order.

Operation to tool mapping

Each operation the parser extracts becomes one tool, built from its parameters, its request body, and its successful responses.

Route extraction

For each entry in paths, the parser MUST extract operations for these HTTP methods, in this order: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. The parser reads only those keys and ignores any other method key.

Parameter extraction

Each parameter MUST have a non-empty name and in field; a missing one is a MissingField("parameter.name") or MissingField("parameter.in") error. The in field MUST be one of path, query, header, or cookie. Any other value is an InvalidSpec error, as is a parameters value that is not an array or a required value that is not a boolean.

When required is absent, a path parameter is required and any other parameter is optional. Header and cookie parameters are parsed but MUST NOT appear in the generated ToolDefinition input schema. Only path and query parameters become tool input properties.

Parameter merging

Path-level parameters and operation-level parameters MUST be merged before tool generation. If an operation-level parameter has the same name and location as a path-level parameter, the operation level wins.

Request body schema

When a requestBody is present, the parser MUST look for a content["application/json"].schema entry first. If absent, the parser MUST fall back to the first available content type. If the body or the schema is a $ref, the parser resolves it before returning. The parser also records requestBody.required, which defaults to false.

Response schema selection

The output schema for a ToolDefinition comes from the response schemas. The generator MUST prefer the 200 response, then 201, then any 2xx response that includes a schema. If no successful response includes a schema, the output schema is None. Each response schema uses the same content selection as the request body: application/json first, then the first content type.

$ref resolution

The parser MUST resolve JSON Reference pointers that begin with #/. This covers #/components/schemas, #/components/parameters, and other #/components/ namespaces. The parser MUST reject, with an UnresolvedRef error:

  • External references, URIs that do not begin with #/.
  • Internal references that point to a path the document does not contain.

ToolDefinition derivation

Each ToolDefinition field takes its value from the operation as follows.

  • name: operationId if present; otherwise "{METHOD} {path}".
  • description: summary if present, else description, else "{METHOD} {path}".
  • input_schema: a JSON Schema object built from path and query parameters as properties, plus a body property from the request body schema.
  • output_schema: the selected 2xx response schema, or None when include_output_schemas is off.
  • annotations.read_only: true if the operation has no side effects (DefaultPolicy::has_side_effects).
  • annotations.destructive: true if the method is DELETE.
  • annotations.idempotent: true if the method is GET, PUT, or DELETE.
  • annotations.requires_approval: the value of x-chio-approval-required, defaulting to false.
  • annotations.estimated_duration_ms: None.
  • pricing: None.

Input schema normalization

OpenAPI schemas project as JSON Schema in the generated tools. build_input_schema preserves each parameter's own schema and applies these normalizations:

  • The input_schema is one JSON Schema object with type: "object".
  • Path and query parameters become top-level properties named after the parameter; header and cookie parameters are skipped.
  • A parameter with no schema, or a schema that is not an object, becomes { "type": "string" }. A parameter description is copied into its property.
  • Required parameters appear in the required array, which is omitted when empty.
  • A request body schema appears under a top-level body property, listed in required only when requestBody.required is true.

The parser resolves internal $ref pointers before a schema reaches the generator, so a consumer sees expanded schemas.

Generator configuration

OptionTypeDefaultEffect
server_id
string
"openapi-server"
Manifest configuration; tool definitions carry no server ID
include_output_schemas
boolean
true
Derive output schemas from response definitions
respect_publish_flag
boolean
true
Honor x-chio-publish: false

x-chio-* extension vocabulary

ChioExtensions::from_operation reads these keys from the raw operation object. They are per-route policy hints that the manifest generator and the chio api protect proxy consume. Every key is optional, and a key whose value has the wrong JSON type is treated as absent.

ExtensionScopeTypeDefaultMeaning
x-chio-sensitivity
operation
enum string
internal
Classification metadata
x-chio-side-effects
operation
boolean
method-driven
Overrides the side-effect annotation and method default
x-chio-approval-required
operation
boolean
false
Forces DenyByDefault; sets annotations.requires_approval
x-chio-budget-limit
operation
unsigned 64-bit integer
none
Budget hint in minor currency units
x-chio-publish
operation
boolean
true
Includes the operation in the generated manifest (should_publish)

x-chio-side-effects overrides the method-based default policy, and x-chio-approval-required: true takes precedence over a false override. x-chio-publish: false fits internal or health-check endpoints that stay reachable through the proxy.

x-chio-sensitivity and x-chio-budget-limit are parsed metadata. The tool generator and proxy route builder carry the sensitivity label as classification, and they read the budget hint but do not turn it into a budget guard or spending limit. Spending limits come from the runtime's budget enforcement.

Sensitivity levels

x-chio-sensitivity takes one of four values: public for publicly available data, internal (the enum default), sensitive, and restricted for highly restricted data. Handling for sensitive and approval for restricted are configured separately: in the tool-generation and proxy-route paths, the label leaves approval and logging unchanged.

If the value does not match one of the four strings, the parser MUST ignore it and treat the key as absent. Sensitivity serializes in lowercase and defaults to internal; the parsed extension stays absent when the key is missing.

Approval precedence

x-chio-approval-required: true MUST take precedence over all other policy inputs. An operation that requires approval is DenyByDefault even when x-chio-side-effects is false and the method is GET.

Extension precedence summary

DefaultPolicy::for_method_with_extensions checks approval first, then the side-effects override, then the method:

Methodx-chio-side-effectsx-chio-approval-requiredResulting policy
GET
absent
absent
SessionAllow
GET
absent
true
DenyByDefault
GET
true
absent
DenyByDefault
GET
false
true
DenyByDefault
POST
absent
absent
DenyByDefault
POST
false
absent
SessionAllow
POST
false
true
DenyByDefault
POST
absent
true
DenyByDefault

Petstore example

The generator tests run this Petstore document, which has four operations on two paths:

spec/OPENAPI-INTEGRATION.mdyaml
openapi: "3.0.3"
info:
  title: Petstore
  description: A sample API for pets
  version: "1.0.0"
paths:
  /pets:
    get:
      operationId: listPets
      summary: List all pets
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            format: int32
          description: How many items to return
      responses:
        "200":
          description: A list of pets
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Pet"
    post:
      operationId: createPet
      summary: Create a pet
      x-chio-sensitivity: internal
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                tag:
                  type: string
              required:
                - name
      responses:
        "201":
          description: Pet created
  /pets/{petId}:
    get:
      operationId: showPetById
      summary: Info for a specific pet
      parameters:
        - name: petId
          in: path
          required: true
          schema:
            type: string
          description: The id of the pet to retrieve
      responses:
        "200":
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
    delete:
      operationId: deletePet
      summary: Delete a pet
      x-chio-approval-required: true
      parameters:
        - name: petId
          in: path
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Pet deleted
components:
  schemas:
    Pet:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
      required:
        - id
        - name

It generates four tools. Each row is one ToolDefinition, with its annotations and the policy the route table assigns.

ToolDescriptionread_onlydestructiveidempotentrequires_approvalPolicy
listPets
List all pets
true
false
true
false
SessionAllow
createPet
Create a pet
false
false
false
false
DenyByDefault
showPetById
Info for a specific pet
true
false
true
false
SessionAllow
deletePet
Delete a pet
false
true
true
true
DenyByDefault

listPets takes an optional limit property and returns the array schema of the 200 response. createPet takes a required body property, because its requestBody.required is true. showPetById and deletePet take a required petId property. deletePet is DenyByDefault twice over: DELETE is a side-effect method, and the operation sets x-chio-approval-required: true.

Default deny-by-method policy

Every route in the proxy's table carries one of two PolicyDecision variants, decided by the method and the two policy extensions.

Method classification

HttpMethod::is_safe divides the methods, and DefaultPolicy::for_method maps the two classes to the two variants.

CategoryMethodsDefault policy
Safe (read-only)
GET, HEAD, OPTIONS
SessionAllow
Side-effect (mutating)
POST, PUT, PATCH, DELETE
DenyByDefault

SessionAllow

An operation classified as SessionAllow is permitted by default within an active session, and the caller presents no capability token. The proxy MUST still generate a signed HttpReceipt for every SessionAllow request; its evidence carries a passing DefaultPolicyGuard entry.

DenyByDefault

An operation classified as DenyByDefault requires the caller to present a valid capability token. Without a token, the proxy MUST return a structured 403 response whose verdict names CapabilityGuard.

The caller presents a capability token in the X-Chio-Capability HTTP header, matched case-insensitively, or the chio_capability query parameter; the header wins when both are present. A valid token satisfies the capability requirement, and the other configured runtime checks still apply before upstream dispatch. A token that fails validation yields a deny from the same guard, with the validation failure as the reason.

Extension overrides

  1. If x-chio-approval-required is true, the check returns DenyByDefault and takes highest precedence.
  2. If x-chio-side-effects is explicitly set, it overrides the method default: true forces DenyByDefault, false forces SessionAllow.
  3. If neither extension is set, the method classification applies.

Unmatched routes

If a request path matches no route in the loaded OpenAPI spec, the proxy MUST fall back to the method-based default policy: safe methods receive SessionAllow, and side-effect methods receive DenyByDefault. The receipt then records the raw request path as route_pattern. Route matching compares path segments one by one, and a {param} segment matches any single segment.

Caller identity and request forwarding

The proxy extracts caller identity from request headers in the order below and retains only a SHA-256 hash of the credential. The subject is the prefix plus the first 16 hex characters of the hash, and verified is false.

PriorityHeaderIdentity format
1
Authorization: Bearer <token>
bearer:<truncated-sha256>
2
x-api-key (any letter case)
apikey:<truncated-sha256>
3
(none)
anonymous

A credential that is empty, carries surrounding whitespace, or contains a control character is ignored, and extraction falls through to the next row.

To forward an allowed request, the proxy builds the upstream URL from the upstream base, the request path, and the query string with chio_capability removed. It forwards every request header except the hop-by-hop headers (connection, proxy-connection, keep-alive, proxy-authenticate, proxy-authorization, te, trailer, transfer-encoding, upgrade), host, content-length, x-chio-capability, and x-chio-execution-nonce. The request body is forwarded verbatim.

The proxy reads at most 10 MiB of body and answers 400 when the limit is exceeded. A request with a duplicate query key is answered 400 chio_bad_request, and a method outside the seven the route table knows is answered 405.

Error mapping

Each non-forwarded outcome has a fixed status and body. Library errors from the parser and the proxy are listed under the error catalog.

Structured 403 response

When a request is denied, a DenyByDefault route without a valid capability token, the proxy MUST return an HTTP 403 response with a JSON body conforming to this schema:

403 response bodyjson
{
  "error": "chio_access_denied",
  "message": "<human-readable denial reason>",
  "receipt_id": "<receipt ID for the denial>",
  "suggestion": "provide a valid capability token in the X-Chio-Capability header or chio_capability query parameter"
}
FieldTypeDescription
error
string
Always "chio_access_denied"
message
string
The verdict's reason
receipt_id
string
ID of the signed receipt that records this denial
suggestion
string
Actionable guidance for the caller

The Content-Type on the 403 response MUST be application/json. The status is the verdict's http_status, 403 by default, and the proxy also sets X-Chio-Receipt-Id. A request that presents a revoked capability is denied before evaluation with the message "capability token has been revoked" and the suggestion "request a fresh capability token before retrying".

Cancel and incomplete verdicts

The proxy forwards only an allow verdict. For any other verdict it finalizes the receipt and answers with the EvaluateResponse as the body: 428 Precondition Required for incomplete, which a strict execution-nonce preflight produces, and 500 for cancel.

Upstream failure

If the upstream request cannot be built or the connection fails, the proxy MUST return HTTP 502 (Bad Gateway) with an X-Chio-Receipt-Id header. The finalized receipt keeps the allow verdict and records 502 as response_status, because the access-control decision stands. An upstream response with an error status is relayed with that status.

Error catalog

OpenApiError, the error type of chio-openapi:

  • InvalidJson: the input was detected as JSON and failed to parse.
  • InvalidYaml: the input was detected as YAML and failed to parse.
  • MissingField: a required top-level field (openapi, info, or paths) or a parameter's name or in is absent.
  • UnsupportedVersion: the openapi version does not begin with 3..
  • UnresolvedRef: a $ref pointer could not be resolved, an external URI or a missing internal path.
  • InvalidSpec: parameters is not an array, parameter.in names an unsupported location, or parameter.required is not a boolean.

ProtectError, the error type of chio-api-protect:

  • SpecLoad: the OpenAPI spec file cannot be read, or auto-discovery failed.
  • SpecParse: the loaded spec failed OpenAPI parsing; wraps OpenApiError.
  • Config: the durable-receipts gate, an invalid upstream URL, or a listen address that cannot be bound.
  • Upstream: the upstream request failed.
  • Evaluation: policy evaluation failed in caller identity hashing, content hashing, or the kernel.
  • PendingApproval: the route is approval-gated and the decision is pending. Carries approval_id and kernel_receipt_id and drives the HTTP 409 approval workflow.
  • ReceiptSign: receipt signing failed.
  • ReceiptStore: receipt persistence failed, or a durable store could not be opened at startup.
  • Io: an IO error during server operation.
  • HttpClient: an HTTP client error during upstream communication.

Approval required (HTTP 409)

When evaluation of an approval-gated route returns PendingApproval, the proxy answers HTTP 409 with a body that identifies the approval workflow:

409 response bodyjson
{
  "error": "chio_approval_required",
  "message": "request requires human approval before it can proceed",
  "kernel_receipt_id": "<kernel receipt id>",
  "approval_id": "<approval id>",
  "resume_path": "/approvals/{approval_id}/respond"
}

error, message, and kernel_receipt_id are always present. approval_id and resume_path are present when the proxy has an approval handle to resume against. A person approves at resume_path, one of the approval routes the proxy mounts behind the sidecar-control token. Any other evaluation error is answered 500 with "error": "chio_evaluation_failed" and the error text as message.

chio api protect contract

Reverse proxyChoose an outcome.

κcapabilityσscopegguardsBbudget

A matched write forwards with its receipt

The proxy matches the method and path against its route table, then the kernel checks the capability in X-Chio-Capability. An allowed request is forwarded with that header stripped, and the response returns with its receipt id. HTTP Proxy.

One request through the reverse proxy to the kernel and the upstream API. The proxy fails closed; a caller that can reach the upstream directly is outside this boundary, and identity extraction is left out.HTTP Proxy

chio api protect is a reverse proxy that places Chio capability checks between callers and an existing HTTP API, with no change to the upstream's code. The same process serves the sidecar routes under /chio that HTTP Transport specifies.

Command interface

Command synopsistext
chio api protect --upstream <URL> [--spec <path>] [--listen <addr>] \
  (--receipt-store <path> | --allow-ephemeral-receipts) [--upstream-timeout-secs <n>]

The flags the command adds to the global set, with the help text the binary prints:

FlagRequiredDefaultDescription
--upstream <UPSTREAM>
Yes
Upstream base URL to proxy to
--spec <SPEC>
No
auto-discovered
Optional local OpenAPI spec path. Auto-discovered when omitted
--listen <LISTEN>
No
127.0.0.1:9090
Address to listen on
--receipt-store <RECEIPT_STORE>
No
Optional SQLite receipt store path; the global --receipt-db otherwise
--allow-ephemeral-receipts
No
false
Permit in-memory receipts, lost on every restart
--upstream-timeout-secs <UPSTREAM_TIMEOUT_SECS>
No
20 seconds (DEFAULT_UPSTREAM_REQUEST_TIMEOUT)
Wall-clock ceiling on a single upstream hop

--allow-ephemeral-receipts is for local development, since in-memory receipts lose their audit evidence on every restart. The --upstream-timeout-secs ceiling, in seconds, includes reading the full response; raise it for upstreams with legitimately slow calls or large bounded responses.

The global --authority-seed-file keeps the receipt signer stable across restarts. Without it, the proxy generates a fresh signer per boot and logs a warning, because receipts signed before a restart are then unverifiable against the new kernel_key. The global --revocation-db, --budget-db, --control-url, and --control-token pass through to the proxy configuration.

chio api protect refuses to start without a durable receipt store, given through --receipt-store or the global --receipt-db, unless --allow-ephemeral-receipts opts in explicitly. An in-memory SQLite path counts as no store, and the library entry point ProtectProxy::run applies the same gate to ProtectConfig.

reference · api-protect-boot-gatetranscript
$ chio api protect --upstream http://127.0.0.1:1
error[CHIO-CLI-RECEIPT-STORE-REQUIRED]: refusing to start without a durable receipt store
  help: pass --receipt-store <path> for a durable audit log, or --allow-ephemeral-receipts to keep receipts in memory, where a restart loses them
  code: urn:chio:error:cli:receipt-store-required
  docs: https://chio.computer/docs/reference/errors#error-cli-receipt-store-required
exit 1

Spec auto-discovery

When --spec is not provided, the proxy MUST attempt to auto-discover the OpenAPI specification from the upstream server. It probes these well-known paths in order:

  1. /openapi.json
  2. /openapi.yaml
  3. /swagger.json
  4. /api-docs

For each path, the proxy issues an HTTP GET request to {upstream}{path} under an egress contract pinned to the upstream's scheme and authority. The first response with a successful status (2xx) and a non-empty body is used as the spec. If every probe fails, the proxy MUST fail with a SpecLoad error directing the operator to use --spec. An upstream URL without a host is a Config error.

Receipt generation

The proxy MUST generate a signed HttpReceipt for every request, allowed or denied. The full field shape is on HTTP Transport. The proxy takes each value from these sources:

  • id: a content-addressed receipt id, SHA-256 of the canonical receipt body with id removed, assigned by HttpReceipt::sign.
  • request_id: a UUIDv7 minted per request; a retry that presents an execution nonce reuses the request id the nonce is bound to.
  • route_pattern: the matched OpenAPI path pattern, such as /pets/{petId}, or the raw path when no route matched.
  • method: the HTTP method.
  • caller_identity_hash: SHA-256 of the canonical CallerIdentity.
  • verdict: Allow, or Deny with reason and guard name; Incomplete on a strict nonce preflight.
  • receipt_kind: mediated_decision.
  • boundary_class: prevent.
  • tool_origin: caller_executed.
  • redaction_mode: none.
  • actor_chain: empty, and therefore omitted from the wire.
  • evidence: DefaultPolicyGuard or CapabilityGuard entries from the HTTP authority.
  • response_status: the status the proxy answered with: the verdict's http_status on deny, the upstream status on a forwarded request, 502 on upstream failure, 428 on an incomplete verdict.
  • timestamp: the Unix timestamp when the receipt was signed.
  • content_hash: ChioHttpRequest::content_hash over method, route pattern, path, query, and body hash.
  • policy_hash: the SHA-256 hash of the loaded OpenAPI spec bytes.
  • trust_level: mediated.
  • capability_id: the id of the presented capability token, when one was presented.
  • metadata: chio_http_status_scope (decision at evaluation, final once the response status is known) and chio_decision_receipt_id on the finalized receipt.
  • kernel_key: the public key of the proxy's signer, derived from --authority-seed-file when given and generated at startup otherwise.

The receipt MUST be signed with the proxy's signer keypair, and the signature MUST be verifiable using the kernel_key field embedded in the receipt. For a request that reaches a response, the proxy records the finalized receipt: a re-signed copy of the decision receipt with the answered status, a fresh timestamp, and the decision receipt's id in metadata.

Receipt header

The proxy sets an X-Chio-Receipt-Id header on every response it signs a receipt for: proxied responses, 403 denials, 428 and 500 non-allow verdicts, and 502 upstream failures. For 403 responses the receipt ID also appears in the JSON body as receipt_id.

Startup behavior

  1. Apply the durable-receipts gate: refuse to start without a durable receipt store unless ephemeral receipts were allowed.
  2. Load the OpenAPI spec, from --spec or by auto-discovery.
  3. Parse the spec with chio-openapi and build a route table that maps (method, path pattern) to a PolicyDecision through DefaultPolicy::for_method_with_extensions.
  4. Derive the signing keypair from the seed, or generate one.
  5. Compute the SHA-256 hash of the spec content for use as policy_hash in receipts.
  6. Open the receipt, approval, revocation, and authority stores: on the receipt store file and its sibling files when one is configured, in memory otherwise.
  7. Bind to the --listen address and begin accepting requests.

With logging enabled, startup records the number of routes loaded, the upstream URL, and the bound address. /chio/live and /chio/health report liveness and readiness; a log line alone establishes neither.

Source and implementation references

The contract follows spec/OPENAPI-INTEGRATION.md in the Chio repository: status Normative, version 1.0, with MUST, SHOULD, and MAY as normative keywords. Where that document and the code differ, behavior follows the crates crates/protocol/chio-openapi and crates/products/chio-api-protect and the help text of chio api protect. The generator tests that run the Petstore document live in crates/protocol/chio-openapi/src/generator.rs; the document is section 5.1 of the specification, and its generated tools are section 5.2.

ComponentCrateEntry point
OpenAPI parser
chio-openapi
crates/protocol/chio-openapi/src/parser.rs
Manifest generator
chio-openapi
crates/protocol/chio-openapi/src/generator.rs
Extension vocabulary
chio-openapi
crates/protocol/chio-openapi/src/extensions.rs
Default policy
chio-openapi
crates/protocol/chio-openapi/src/policy.rs
Reverse proxy
chio-api-protect
crates/products/chio-api-protect/src/proxy.rs
Request evaluator
chio-api-protect
crates/products/chio-api-protect/src/evaluator.rs
Spec discovery
chio-api-protect
crates/products/chio-api-protect/src/spec_discovery.rs
CLI command
chio-cli
crates/products/chio-cli/src/cli/runtime.rs
Convenience function
chio-openapi
chio_openapi::tools_from_spec()

Next: generate tools from your own document