21 review-001 tasks across server/adapters/client/gateway/websocket/infra, chunked from the 7-unit remediation plan in docs/reviews/001-initial-implementation-review.md. - Scope split by mechanism, not one-per-finding: 15 tasks in generation 1 (parallelizable), 6 sequenced after their file-sharing precursors - Deliberately deferred until dependent fixes land: projection/doc fidelity partial (Unit 6 beyond dependency hygiene), coverage backfills (COV-01..07 via in-task acceptance for forward.rs), and per-finding minors (OAI-06/07, HY-02/04/06/10/11, CON-08) - Cross-crate WS-12 (alkcall demux 4 GiB discard alloc) noted for filing in alkcall, not here taskgraph: validate clean, no cycles, 6 generations
3.2 KiB
3.2 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | ||
|---|---|---|---|---|---|---|---|---|---|---|
| review-001-gateway-publish-semantics | /publish + /batch gateway fixes (GW-01, GW-06, GW-08..GW-11, HY-13) | pending | narrow | medium | component | implementation |
|
Description
Review 001 findings on src/gateway/routes.rs's /publish and /batch
routes:
- GW-01 (major):
/publish(routes.rs:257-276) feeds parsed NDJSON straight toinvoke_sink;publish_schemavalidation lives only in alkcall's wireDispatcher— so a Pub op registered withpublish_schemareceives arbitrary attacker-controlled JSON over HTTP while the same op over the call protocol aborts invalid chunks. Handlers written against the validated-wire guarantee get a transport-dependent invariant. Fix: validate in the route (or move validation into the sharedinvoke_sinkspine so both transports enforce it — prefer the spine if alkcall's surface allows, else the route). - GW-10: a first line missing
chunksilently publishesValue::Null(routes.rs:213) — indistinguishable from intent since null is a legitimate payload. Reject withINVALID_INPUT(the route already rejects a missingoperationthis way). - GW-06:
/publishbuffers the whole NDJSON body (2 MiB-capped) before dispatch, contradicting ADR-068 step 4. Either stream the body (axumBody→ framed stream) — the real fix — or amend ADR-068 to document the buffered 2 MiB semantics. Decide, then implement or amend. - GW-08: no cap on batch operation count; the 2 MiB body is the only bound and the 30 s deadline is unenforced (GW-05). Cap batch size (constant, e.g. 100).
- GW-09: internal-op batch entries emit
request_id: nullwhile dispatched entries carry a UUID — one response body, two envelope shapes. Generate request ids for internal-op entries. - GW-11:
/publishruns four registry lookups + ACL checks thatinvoke_sinkthen repeats — drop the redundant pre-checks (mirror/call//batch, which deliberately rely on the registry). - HY-13: the vacuous test at
routes.rs:1572-1583(publish_body_is_fully_consumed_before_dispatch_not_required) cites a socket-level test that doesn't exist — wire the early-disconnect test or delete the stub.
Acceptance Criteria
/publishtest with apublish_schema-registered Pub op rejects an invalid chunk (review's gate for this unit)- First line without
chunk→INVALID_INPUT, not a null publish (test) - GW-06 decision landed: true streaming or ADR-068 amended; consistent tests + docs
- Batch size capped (test); mixed-shape batch envelopes fixed
- Redundant
/publishpre-checks removed (dispatch still enforces) cargo testandcargo clippy --all-targets -- -D warningspass
References
- docs/reviews/001-initial-implementation-review.md (Part C, GW-01, GW-06, GW-08..GW-11; HY-13)
- docs/architecture/decisions/068-gateway-publish-endpoint.md
- docs/architecture/decisions/023-operation-error-schemas.md
Notes
Agent fills during implementation. If the GW-01 fix goes into alkcall's
invoke_sinkspine, coordinate the alkcall change (small, additive) and note it in the summary.
Summary
Filled on completion.