docs(ledger): file CF-003 — wire-path publish_schema compile failure is fail-open

Found while fixing alkhttp's HTTP-side instance
(review-001-publish-schema-validation-robust): the identical
warn-and-skip pattern exists at src/protocol/dispatch.rs:352-366 — a
compile failure of a Pub op's publish_schema proceeds with
validator: None, so arbitrary unvalidated JSON reaches the sink
handler over the wire. Suggested direction: fail-closed + per-
registration validator cache (worked shape in alkhttp 1572a9d,
src/gateway/schema_cache.rs) + registration-time schema compilation.
Single compile site verified (both pump arms consume the one
InFlightSink.publish_validator).
This commit is contained in:
glm-5.3-flash committed 2026-08-30 08:33:29 +00:00
1 parent 84fe94c4d7
commit 1f08f1e385
1 file changed
+37
+37
View File
@@ -11,6 +11,43 @@ Format: date | found-in (alkhttp context) | severity | status.
## Open
### CF-003 — `publish_schema` compile failure is fail-open on the wire dispatch path (2026-08-30)
- **Found in:** alkhttp Review 001 post-remediation task
`review-001-publish-schema-validation-robust` (the GW-01/#1 follow-up
work). While fixing alkhttp's HTTP-side instance of the pattern, the
identical instance was verified on the wire dispatch path:
`src/protocol/dispatch.rs:352-366` (`Dispatcher::dispatch`,
`OperationType::Pub` arm) — when a Pub op's `publish_schema` fails to
**compile** (`jsonschema::options().build(&schema)` errors, e.g. a
non-array `"required"`, a non-string `"type"`, an invalid `pattern`
regex), the pump logs `warn!("publish_schema failed to compile;
chunks will not be validated")` and proceeds with `validator: None`.
- **Impact:** silent unvalidated ingest, per-request. A Pub op (local
registration or remote import) whose schema is un-compilable by the
pinned jsonschema dialect silently receives arbitrary JSON over the
wire that the registration *declares* validated — the handler's
schema guarantee is transport-dependent and quietly false. One broken
schema in the registry turns that op into an unvalidated ingest path
with only a warn log as the tell. (Per-request recompile cost is the
secondary issue; alkhttp's gateway cache eliminated both.)
- **Suggested direction:** fail-closed — on compile failure, reject the
chunk (or abort the sink dispatch) with `INTERNAL`-class
`CallError` naming the compile failure in the log only (untrusted
schema text off the wire), never a silent skip; cache the compiled
validator per registration (hot-reload by schema-value comparison;
see alkhttp's `src/gateway/schema_cache.rs` for the worked shape).
Complementary hygiene: reject un-compilable `publish_schema` values
at **registration time** (`OperationRegistry::register` observing
`spec.publish_schema`, or `with_publish_schema` validating eagerly)
so the failure never reaches traffic.
- **alkhttp side:** fixed in alkhttp `1572a9d` (gateway cache + lazy
resolution + stream-terminal fail-closed). The wire path is out of
this crate's scope (AGENTS.md: no forking alkcall types; the pump is
alkcall-internal), so the same invariant currently holds only on the
HTTP path.
- **Status:** open — no alkcall change made.
### CF-002 — demux `TooLarge` skip allocates the full peer-declared length up front (up to ~4 GiB from an 8-byte header) (2026-08-30)
- **Found in:** alkhttp Review 001, finding WS-12 (cross-crate;