- build_request takes the op's input_schema and rejects undeclared input keys (INVALID_INPUT) before any outbound request is built; explicit `additionalProperties: true` opts into catch-all input; non-object inputs rejected (OAI-02) - in: header parameters are stamped `wire: header` in the generated input schema and sent as upstream request headers, not query params; in: cookie fails import with a clear error (OAI-03) - a spec parameter named `body` is rejected at import unconditionally (OAI-07) - FromJsonSchema::new returns Result and validates method/path template/ base_url at construction; registered visibility forced to Internal like from_openapi; module doc corrected (OAI-09) Verified: cargo test, cargo test --all-features, clippy (both feature sets, -D warnings), cargo fmt --check
5.0 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| review-001-input-schema-enforcement | Send exactly what the input schema advertises (OAI-02, OAI-03, OAI-07, OAI-09) | completed |
|
narrow | medium | component | implementation |
|
Description
Review 001 findings OAI-02 + OAI-03 + OAI-07 + OAI-09 — the request a
forwarder sends must match the contract /schema advertises:
- OAI-02 (
forward.rs:60-72): no input-schema enforcement — every input key that isn't a path placeholder (and isn't literally"body") becomes an upstream query parameter regardless of the registeredinput_schema. Peer input like"debug": "true"or"impersonate_id": "…"reaches the upstream. ADR-066's "input schema validation before send" is implemented nowhere. Fix: enforceinput_schemaat call time — reject undeclared keys (or document pass-through as an explicit, per-adapter choice). - OAI-03 (
openapi_spec.rs:35-40):in: headerparameters are silently sent as query parameters (in_is a dead field). Upstream auth/trace headers never arrive, and header-designated values land in upstream access logs instead. Honorin: header; fixin: cookie(reject with a clear unsupported error). - OAI-07: the magic
"body"key collides with a spec parameter actually namedbody— the declared parameter is silently diverted. Namespace the body input or reject the collision loudly. - OAI-09 (
from_jsonschema.rs:36-51): malformedmethod/path_template/base_urlvalidate only at first invoke; and the module doc says "Internalby default" while the adapter passes the caller's spec through verbatim (from_openapihardcodesVisibility::Internal). Validate at construction; align the doc or default the visibility.
Acceptance Criteria
- Undeclared input keys are rejected (or the pass-through is explicit config, tested) — peer input cannot add upstream query params (test)
in: headerparameters send as headers;in: cookieerrors clearly at import (tests)body-named parameter collision handled loudly (test)from_jsonschemavalidates method/path_template/base_url at construction;Internal-by-default matchesfrom_openapior the doc is correctedcargo testandcargo clippy --all-targets -- -D warningspass
References
- docs/reviews/001-initial-implementation-review.md (Part E, OAI-02, OAI-03, OAI-07, OAI-09)
- docs/architecture/decisions/066-from-jsonschema-as-http-adapter.md
Notes
Agent fills during implementation. Depends on ref-resolution only for shared fixtures/types in
openapi_spec.rs; start after it lands to avoid churn. OAI-06 (silent feature degradation) is deliberately deferred — revisit after this task.
Summary
Forwarders now send exactly what the input schema advertises.
OAI-02 (forward.rs): build_request takes the operation's
input_schema and enforces it at call time — every input key must be
declared in properties (path placeholders included; from_openapi
declares them) or the input is rejected as INVALID_INPUT before any
outbound request is built. An explicit "additionalProperties": true
opts an operation into catch-all input (JSON Schema semantics — the
schema advertises that extra keys are valid); non-object inputs are
rejected. No pass-through knob: the review's preferred reject-undeclared
posture is the behavior, documented in the module doc.
OAI-03 (forward.rs + from_openapi.rs): the Parameter.in_ field
is no longer dead. from_openapi builds header-param properties as
{"wire": "header", "schema": …} in the generated input schema;
build_request routes marked properties into HTTP request headers
(validated name/value, loud INTERNAL on refusal) instead of the query
string. in: cookie fails import with a clear SchemaParse message
(OAI-06's silent-degradation pattern avoided here).
OAI-07 (from_openapi.rs): a spec parameter named body is rejected
at import unconditionally (previously only when a requestBody coexisted)
— the magic gateway body key would divert the declared parameter.
OAI-09 (from_jsonschema.rs): FromJsonSchema::new now returns
Result and validates at construction — method parses, path template
placeholders are balanced and bound by the input schema, base URL is a
userinfo-free http(s) URL — instead of surfacing INTERNAL on first
invoke. The registered visibility is forced to Internal (ADR-015) like
from_openapi; the module doc corrected (it previously claimed verbatim
pass-through).
Integration note: from_openapi's declaration-side checks
(unbound_placeholders, collision rejection) now have a call-time
counterpart; to_openapi's gateway projection was untouched (its
CallRequest shape passes through unchanged).
Verification: cargo test (297 lib), cargo test --all-features (368 +
integration suites), cargo clippy --all-targets -- -D warnings
(default + all features), cargo fmt --check — all green.