fix: remediate consumer findings CF-001..004 (alkhttp ledger)

- CF-004: services_schema_handler now applies the same visibility +
  AccessControl gates as invoke() (identity resolution mirrors invoke:
  handler_identity under internal). Restricted ops return spec-404 NOT_FOUND
  — matches "restricted ops don't exist" and leaks nothing about the
  restricted surface. Closes the unauthenticated /call-path disclosure.
- CF-003: publish_schema compiled at registration time (both
  OperationRegistry::register and OperationRegistryBuilder::store);
  un-compilable schemas are a registration error — an unvalidated ingest
  path can no longer be constructed. Compiled validator cached per-op
  (publish_validator) and consumed by dispatch; per-request compile gone.
  BEHAVIOR CHANGE: register/builder reject un-compilable publish_schema.
- CF-002: demux TooLarge skip streams through a fixed 64 KiB buffer
  instead of allocating the peer-declared length (u32, up to ~4 GiB);
  cumulative 256 MiB skipped-bytes budget tears down dribbling peers.
  Existing resync test passes unchanged.
- CF-001: new retryable CallError::connection_closed (CONNECTION_CLOSED)
  applied only where the call is provably undelivered — request-frame
  write failures on all consumer paths (call/subscribe/publish, both
  stream modes; publish pump tags write stages). Mid-publish failures and
  producer-side fail_all stay non-retryable INTERNAL (delivery ambiguous).
  New code string is additive; retryable flag is the machine-readable
  signal.

Verification: cargo test (558 pass, 15 new), clippy --all-targets -D
warnings, fmt --check, wasm32-unknown-unknown check.
This commit is contained in:
glm-5.3-flash committed 2026-08-31 08:22:55 +00:00
1 parent a2d72f9737
commit 8cb2a6eb6d
8 files changed
+613 -167

No files matched your search

+1 -15
View File
@@ -349,21 +349,7 @@ impl Dispatcher {
Ok(h) => h,
Err(envelope) => return DispatchResult::Once(envelope),
};
let publish_validator = self
.registry
.registration(&operation_name)
.and_then(|r| r.spec.publish_schema.as_ref())
.and_then(|schema| match jsonschema::options().build(schema) {
Ok(v) => Some(v),
Err(e) => {
warn!(
operation = %operation_name,
error = %e,
"publish_schema failed to compile; chunks will not be validated",
);
None
}
});
let publish_validator = self.registry.publish_validator(&operation_name);
let (chunk_tx, chunk_rx) =
mpsc::channel::<Result<Value, CallError>>(PUBLISH_CHANNEL_BUFFER);
let publish_stream: PublishStream = Box::pin(chunk_rx);