feat(gateway,adapters): /publish endpoint (ADR-068) + to_openapi 6-endpoint projection
gateway-publish:
- GatewayDispatch::invoke_sink (internal:false, forwarded_for:None)
- POST /publish: NDJSON body, first line {operation, chunk} (OQ-02
resolved: first-line convention; terminal errors = plain HTTP status
+ JSON body, not NDJSON lines); 404 internal/unknown, 401/403 ACL,
400 INVALID_OPERATION_TYPE for non-Pub
- ADR-068 + open-questions.md updated with the OQ-02 resolution
adapter-to-openapi:
- src/adapters/openapi_spec.rs: OpenAPISpec model (JSON/YAML/from_str
JSON-first per ADR-051, $ref resolution) shared by from/to_openapi
- src/adapters/to_openapi.rs: 6-endpoint projection, info.version
1.0.0 -> 1.1.0 (minor: /publish addition per ADR-045), /publish
NDJSON doc with 400 oneOf (INVALID_INPUT + INVALID_OPERATION_TYPE),
ADR-023 error fidelity (protocol statuses, HTTP_<status> passthrough,
internal-op exclusion)
- GET /openapi.json wired into HttpAdapter's router (bearer-auth layer)
Verified: cargo test (136 lib), test --all-features (136+10 WS),
clippy -D warnings (both), fmt. Doc validates against openapiv3.
This commit is contained in:
@@ -45,11 +45,11 @@ stream; the operation's final `ResponseEnvelope` is the HTTP response.
|
||||
- Auth: `Authorization: Bearer <token>` — same as every gateway
|
||||
endpoint ([ADR-004](004-auth-as-shared-core.md)).
|
||||
- The target operation is named the same way as `/call` — the body's
|
||||
first line (or a `?operation=` query parameter) carries
|
||||
`{ "operation": "/{service}/{op}", "chunk": {...} }` for the first
|
||||
chunk, with subsequent lines carrying `chunk` values only; see OQ-02
|
||||
for the exact first-line convention before the gateway-spec version
|
||||
bumps.
|
||||
first line carries `{ "operation": "/{service}/{op}", "chunk": {...}`
|
||||
for the first chunk, with subsequent lines carrying `chunk` values
|
||||
only. (OQ-02 resolved: first-line convention, no query parameter, no
|
||||
header; a `?operation=` parameter was rejected because it duplicates
|
||||
the first-line field and complicates curl one-liners for no gain.)
|
||||
|
||||
### Dispatch
|
||||
|
||||
@@ -114,8 +114,10 @@ the doc does not preload operations.
|
||||
indistinguishable from a network error to the server side (the
|
||||
handler sees EOF either way). Callers needing explicit failure
|
||||
semantics use the call protocol (WS channel 0).
|
||||
- OQ-02 (first-line operation-naming convention) must settle before
|
||||
the `/openapi.json` version bumps.
|
||||
- ~~OQ-02 (first-line operation-naming convention) must settle before
|
||||
the `/openapi.json` version bumps~~ — settled: first-line
|
||||
`{operation, chunk}` convention; terminal errors are plain HTTP
|
||||
status + JSON body (not an NDJSON line).
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -40,15 +40,17 @@ with their resolutions; new alkhttp OQs start at OQ-01.
|
||||
### OQ-02: `/publish` body framing details
|
||||
|
||||
- **Origin**: [ADR-068](decisions/068-gateway-publish-endpoint.md)
|
||||
- **Status**: open
|
||||
- **Status**: resolved (implementation: gateway-publish task, 2026-08-28)
|
||||
- **Priority**: medium
|
||||
- **Resolution**: (pending)
|
||||
- **Question**: The exact first-line convention for naming the target
|
||||
operation (first line `{operation, chunk}` vs `?operation=` query
|
||||
parameter vs required header), and where a terminal error envelope
|
||||
lives (final NDJSON line of a JSON error object vs plain HTTP status
|
||||
with JSON body). Must settle before the gateway contract's
|
||||
`info.version` bumps ([ADR-045](decisions/045-to-openapi-gateway-spec-versioning.md)).
|
||||
- **Resolution**: First line of the NDJSON body carries
|
||||
`{ "operation": "/{service}/{op}", "chunk": {...} }`; subsequent
|
||||
lines are chunk values only. Terminal errors are plain HTTP status +
|
||||
JSON body (NOT an NDJSON line) — consistent with every other gateway
|
||||
endpoint's error surface. A `?operation=` query parameter was
|
||||
considered and rejected: it duplicates the first-line field and adds
|
||||
a second way to name the op (two sources of truth) for no curl-ability
|
||||
gain. The first-line convention is the single naming point.
|
||||
Implemented in `src/gateway/routes.rs::publish_handler`.
|
||||
|
||||
### OQ-03: `from_wss` reconnection semantics
|
||||
|
||||
|
||||
Reference in New Issue
Block a user