docs(http): resolve OQ-39; add ADRs 045-047; record pubsub prior art for WS path
OQ-39 (to_openapi published-spec versioning) resolved by ADR-045:
info.version semver tracks the gateway endpoint contract, not the
operation set — per-caller operations discovered via /search do not
bump the version. The gateway pattern (ADR-042) dissolved most of the
original churn concern.
ADR-046: assembly-layer custom HTTP routes on HttpAdapter. The HTTP
router had no documented extension point for deployment-specific
endpoints (e.g., an OAI-compatible proxy at /v1/chat/completions). Adds
extra_routes: Option<Router> at construction; raw HTTP, not operations;
default surface takes precedence on collision. The mechanism is the
one-way door; specific routes are two-way.
ADR-047: remove the direct-call POST /{service}/{op} HTTP surface. The
gateway /call is the sole invoke path — the simplified contract is a
few fixed endpoints, not a per-operation REST tree. The direct-call
surface re-introduced the 'dump the full API regardless of privs'
failure mode at the HTTP level that the gateway /search was built to
escape. ADR-036's routing decision is superseded; its non-routing
clauses (SSE, Bearer auth, /healthz, stealth, error mapping) survive.
A deployment wanting a REST-like per-operation surface builds it as a
custom route projection (ADR-046).
ADR-044 updated with the tradeoff framing (WSS is the right tool for
the call-protocol-from-browser case; WebTransport is the right tool for
the generalized ALPN-stream-proxy case we don't have yet — coexist, not
migrate) and the @alkdev/pubsub concrete prior art (the EventEnvelope
{type,id,payload} the call protocol was derived from already has a
working WebSocket client/server; the sync is a small adjustment, not a
from-scratch build).
call-protocol.md references the pubsub lineage for the
transport-agnosticism claim.
This commit is contained in:
@@ -805,31 +805,56 @@ is a feature extension, not an unmade architecture decision.
|
||||
|
||||
- **Origin**: [ADR-017](decisions/017-call-protocol-client-and-adapter-contract.md)
|
||||
Consequences, [http-adapters.md](crates/http/http-adapters.md)
|
||||
- **Status**: open
|
||||
- **Status**: **resolved** (2026-06-30 by ADR-045)
|
||||
- **Door type**: One-way (after first publication), two-way (before)
|
||||
- **Priority**: medium
|
||||
- **Resolution**: ADR-017 Consequences notes that published `to_*`
|
||||
specs are compatibility contracts: once a generated OpenAPI spec is
|
||||
published and external clients build against it, the mapping
|
||||
semantics (e.g., subscriptions → SSE long-poll, error codes → HTTP
|
||||
statuses) become a de facto contract. Changing the mapping later
|
||||
breaks every client. `to_openapi` mapping choices are two-way *before*
|
||||
first publication but one-way *after*.
|
||||
- **Priority**: medium → resolved
|
||||
- **Resolution**: **[ADR-045](decisions/045-to-openapi-gateway-spec-versioning.md)
|
||||
commits the versioning scheme.** The gateway pattern (ADR-042)
|
||||
dissolved most of the original concern: the published doc describes
|
||||
**5 fixed gateway endpoints** (`/search`, `/schema`, `/call`,
|
||||
`/batch`, `/subscribe`), not the per-operation surface. Per-caller
|
||||
operation changes (add/remove/modify an operation, change an
|
||||
operation's schema) do **not** change the published doc — the
|
||||
operation set is discovered at runtime via `AccessControl`-filtered
|
||||
`/search`, not preloaded into the doc. So the version does not churn
|
||||
on every operation change (the original OQ-39 worry, framed under the
|
||||
pre-ADR-042 per-operation-paths model).
|
||||
|
||||
The versioning strategy for generated OpenAPI specs needs
|
||||
specifying: version the generated spec (e.g., an OpenAPI `info.version`
|
||||
tied to the registry's `External` operation set version) and emit a
|
||||
spec version marker so consumers can detect mapping changes. The
|
||||
exact versioning scheme (semver tied to operation additions/changes,
|
||||
a content-hash, a monotonically-increasing counter) is a two-way-door
|
||||
implementation detail before first publication; the one-way constraint
|
||||
is that the version marker is emitted and consumers can detect
|
||||
breaking changes. This is the "published artifact is a contract"
|
||||
blind spot in ADR-009's framework (it classifies doors by reversal
|
||||
cost in the codebase, not by compatibility cost for external
|
||||
consumers).
|
||||
- **Cross-references**: ADR-009, ADR-017, ADR-023, ADR-036,
|
||||
[http-adapters.md](crates/http/http-adapters.md)
|
||||
What remains is narrow: how the published gateway doc signals its
|
||||
version. The decision:
|
||||
|
||||
1. **`to_openapi` emits `info.version` as semver.** Standard OpenAPI
|
||||
field, standard semver interpretation — no alknet-specific
|
||||
detection mechanism.
|
||||
2. **The version tracks the gateway endpoint contract, not the
|
||||
operation set.** Major = breaking change to the gateway (endpoint
|
||||
removed/renamed, required request field added, response shape
|
||||
changed, error-mapping semantics changed per ADR-023); Minor =
|
||||
additive (new endpoint, new optional field); Patch = wording/docs.
|
||||
Per-caller operation changes do **not** bump the version.
|
||||
3. **Bump on change to the gateway shape, not on regeneration.**
|
||||
A restart that regenerates the same gateway shape yields the same
|
||||
version.
|
||||
4. **Consumers detect breaking changes via the major version.** A
|
||||
client compares `info.version`'s major component to the version it
|
||||
built against; a major bump signals "re-read the doc, something
|
||||
broke." Minor/patch are informational.
|
||||
5. **The additive traditional per-operation-paths projection
|
||||
(ADR-042 §5) versions independently** on its own schedule — its
|
||||
surface *does* change with the operation set, so its versioning is
|
||||
the per-operation churn the original OQ-39 framed. That projection
|
||||
is opt-in and out of scope for ADR-045; the gateway doc is the
|
||||
default published contract and the one ADR-045 governs.
|
||||
|
||||
The original "version marker emitted so consumers can detect mapping
|
||||
changes" constraint (from ADR-017 Consequences) is satisfied by
|
||||
`info.version` semver. ADR-045 lifts the "published artifact is a
|
||||
contract" blind spot in ADR-009's framework (it classifies doors by
|
||||
reversal cost in the codebase, not by compatibility cost for external
|
||||
consumers) into its Context and honors the constraint without changing
|
||||
ADR-009's framework.
|
||||
- **Cross-references**: ADR-009, ADR-017, ADR-023, ADR-036, ADR-042,
|
||||
ADR-045, [http-adapters.md](crates/http/http-adapters.md)
|
||||
|
||||
### OQ-40: reqwest Client Config and Connection Pooling
|
||||
|
||||
|
||||
Reference in New Issue
Block a user