1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! The [`HttpEngine`] contract — what an HTTP-stack adapter must implement.
use crate::;
use Future;
use CancellationToken;
use ;
/// Contract for an HTTP framework adapter.
///
/// The engine declares its native request/response types, supplies two
/// HTTP conversion bridges and two SSE event constructors, and runs an
/// HTTP server until `token` fires. All JSON-RPC framing, SSE
/// replay/dedup, batch fast-path, and oneshot pending logic stays in
/// neva — an engine adapter is the thinnest possible shim from neva's
/// neutral types onto a framework's native types.
///
/// Route handlers typically just call the `dispatch_*` helpers in
/// [`super::handlers`], which compose conversion + protocol dispatch +
/// conversion-back in one call.
///
/// # Authorization contract
///
/// To enable neva's per-tool / per-prompt / per-resource role and
/// permission gates, the engine is responsible for decoding the
/// inbound request's auth credential (bearer token, session cookie,
/// custom header — whatever the engine supports) into a value
/// implementing [`crate::auth::Claims`], wrapping it in
/// `Arc<dyn neva::auth::Claims>`, and inserting it into
/// `request.extensions_mut()` **before** calling [`dispatch_post`].
///
/// neva itself does not parse credentials — that is the engine's job.
/// If no claims are inserted, neva treats the request as unauthenticated
/// and any tool/prompt/resource that declares required roles or
/// permissions will reject it.
///
/// The default `VolgaEngine` (selected by `HttpServer::default()` /
/// `with_default_http`) does this automatically using Volga's
/// `BearerTokenService`. A custom engine adapter wires up the equivalent
/// step in its own POST route.
///
/// [`dispatch_post`]: super::handlers::dispatch_post
///
/// # Example
///
/// ```rust,ignore
/// struct MyEngine;
///
/// impl HttpEngine for MyEngine {
/// type Request = framework::Request;
/// type Response = framework::Response;
/// type SseEvent = framework::sse::Event;
///
/// async fn adapt_request(req: Self::Request) -> Result<HttpRequest, Error> { ... }
/// fn adapt_response(resp: HttpResponse) -> Self::Response { ... }
///
/// fn tracked_event(seq: u64, msg: &Message) -> Self::SseEvent { ... }
/// fn ephemeral_event(msg: &Message) -> Self::SseEvent { ... }
///
/// async fn run(self, ctx: HttpContext, token: CancellationToken)
/// -> Result<(), Error> { ... }
/// }
/// ```
/// `pub(crate)` dyn-compatible bridge: lets `TransportProto::HttpServer`
/// store any `HttpServer<C, E>` behind a single trait object without
/// becoming generic itself. Engines never see this trait — it lives at
/// the `HttpServer` ⇄ `TransportProto` seam.
pub