@keri-ts/hosting 2.2.1 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/hosting/npm/src/src/http/protocol/context.js +9 -5
- package/esm/hosting/npm/src/src/http/protocol/endpoints/oobi.js +24 -5
- package/package.json +3 -3
- package/types/src/http/protocol/context.d.ts +2 -1
- package/types/src/http/protocol/context.d.ts.map +1 -1
- package/types/src/http/protocol/endpoints/oobi.d.ts +5 -1
- package/types/src/http/protocol/endpoints/oobi.d.ts.map +1 -1
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The router is path-first: every endpoint classifier receives the same
|
|
5
5
|
* normalized path plus hosted-prefix projections, so mailbox admin, OOBI, and
|
|
6
|
-
* generic CESR ingress cannot disagree about which local AID a URL addresses.
|
|
6
|
+
* generic CESR ingress cannot disagree about which local AID a URL addresses. When several local AIDs share
|
|
7
|
+
* one URL, the request's `CESR-DESTINATION` picks among them.
|
|
7
8
|
*/
|
|
8
|
-
import { resolveHostedEndpointPath } from "keri-ts/runtime";
|
|
9
|
+
import { CESR_DESTINATION_HEADER, resolveHostedEndpointPath, } from "keri-ts/runtime";
|
|
9
10
|
import { parseOobiRouteRequest } from "./endpoints/oobi.js";
|
|
10
11
|
/** Snapshot one request into the path-first routing context. */
|
|
11
12
|
export function buildProtocolRequestContext(req, runtime, policy = {}) {
|
|
@@ -14,14 +15,17 @@ export function buildProtocolRequestContext(req, runtime, policy = {}) {
|
|
|
14
15
|
// Resolve the same normalized path against the three hosted path shapes used
|
|
15
16
|
// by the HTTP edge: plain hosted endpoints, mailbox admin endpoints, and
|
|
16
17
|
// generic root-relative CESR ingress.
|
|
18
|
+
// Several local identifiers may advertise one ingress URL; the path then cannot tell them apart and the
|
|
19
|
+
// request's own destination does.
|
|
20
|
+
const destination = req.headers.get(CESR_DESTINATION_HEADER);
|
|
17
21
|
const hosted = runtime
|
|
18
|
-
? resolveHostedEndpointPath(runtime.hby, pathname, "", policy.hostedPrefixes)
|
|
22
|
+
? resolveHostedEndpointPath(runtime.hby, pathname, "", policy.hostedPrefixes, destination)
|
|
19
23
|
: null;
|
|
20
24
|
const mailboxAdmin = runtime
|
|
21
|
-
? resolveHostedEndpointPath(runtime.hby, pathname, "/mailboxes", policy.hostedPrefixes)
|
|
25
|
+
? resolveHostedEndpointPath(runtime.hby, pathname, "/mailboxes", policy.hostedPrefixes, destination)
|
|
22
26
|
: null;
|
|
23
27
|
const genericIngress = runtime
|
|
24
|
-
? resolveHostedEndpointPath(runtime.hby, pathname, "/", policy.hostedPrefixes)
|
|
28
|
+
? resolveHostedEndpointPath(runtime.hby, pathname, "/", policy.hostedPrefixes, destination)
|
|
25
29
|
: null;
|
|
26
30
|
const oobiPath = hosted?.relativePath ?? pathname;
|
|
27
31
|
return {
|
|
@@ -69,7 +69,7 @@ export function handleOobiRoute(context, request) {
|
|
|
69
69
|
endpoint: null,
|
|
70
70
|
relativePath: null,
|
|
71
71
|
};
|
|
72
|
-
const respondingHabAid = selectResponderHab(runtime, hosted, aid, request.eid, context.policy.hostedPrefixes);
|
|
72
|
+
const respondingHabAid = selectResponderHab(runtime, hosted, aid, request.eid, context.policy.hostedPrefixes, request.role);
|
|
73
73
|
const hab = respondingHabAid ? runtime.hby.habs.get(respondingHabAid) : undefined;
|
|
74
74
|
if (!hab) {
|
|
75
75
|
if (hosted.kind === "ambiguous" && context.policy.hostedPrefixes) {
|
|
@@ -118,8 +118,12 @@ export function defaultOobiAid(runtime, serviceHab, hostedPrefixes) {
|
|
|
118
118
|
* - the requested AID itself when locally controlled
|
|
119
119
|
* - the explicit endpoint AID when it is locally controlled
|
|
120
120
|
* - the hosted endpoint matched from the request path
|
|
121
|
+
* - a local identifier that an accepted end-role record of `aid` names as `eid` in the requested role, so a host
|
|
122
|
+
* serves the OOBI of an identifier it is the agent of even when it hosts no prefix directly. A non-empty
|
|
123
|
+
* `hostedPrefixes` is the operator's stated scope, so the named `eid` must be in it; when it is empty or absent,
|
|
124
|
+
* any local identifier qualifies.
|
|
121
125
|
*/
|
|
122
|
-
export function selectResponderHab(runtime, hosted, aid, eid, hostedPrefixes) {
|
|
126
|
+
export function selectResponderHab(runtime, hosted, aid, eid, hostedPrefixes, role) {
|
|
123
127
|
const hostedSet = hostedPrefixes ? new Set(hostedPrefixes) : null;
|
|
124
128
|
const hostedCandidate = (candidate) => {
|
|
125
129
|
if (!candidate || !runtime.hby.habs.has(candidate)) {
|
|
@@ -154,12 +158,13 @@ export function selectResponderHab(runtime, hosted, aid, eid, hostedPrefixes) {
|
|
|
154
158
|
&& (aid === hostedAid || eid === hostedAid)) {
|
|
155
159
|
return hostedAid;
|
|
156
160
|
}
|
|
157
|
-
return
|
|
161
|
+
return endRoleResponder(runtime, aid, role, eid, hostedPrefixes);
|
|
158
162
|
}
|
|
159
163
|
return hostedCandidate(aid)
|
|
160
164
|
?? hostedCandidate(eid)
|
|
161
165
|
?? rootHostedCandidate(aid)
|
|
162
|
-
?? rootHostedCandidate(eid)
|
|
166
|
+
?? rootHostedCandidate(eid)
|
|
167
|
+
?? endRoleResponder(runtime, aid, role, eid, hostedPrefixes);
|
|
163
168
|
}
|
|
164
169
|
if (runtime.hby.habs.has(aid)) {
|
|
165
170
|
return aid;
|
|
@@ -167,5 +172,19 @@ export function selectResponderHab(runtime, hosted, aid, eid, hostedPrefixes) {
|
|
|
167
172
|
if (eid && runtime.hby.habs.has(eid)) {
|
|
168
173
|
return eid;
|
|
169
174
|
}
|
|
170
|
-
return hosted.endpoint?.eid ??
|
|
175
|
+
return hosted.endpoint?.eid ?? endRoleResponder(runtime, aid, role, eid, hostedPrefixes);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* The local identifier an accepted, uncut end-role record of `aid` names as `eid` in `role` (any role when
|
|
179
|
+
* omitted; only `eid` when given), within `scope` when it is non-empty. Reads accepted state only: a role never accepted, or cut, names nobody.
|
|
180
|
+
*/
|
|
181
|
+
function endRoleResponder(runtime, aid, role, eid, scope) {
|
|
182
|
+
for (const [keys, end] of runtime.hby.db.ends.getTopItemIter([aid], { topive: true })) {
|
|
183
|
+
const [, currentRole, agent] = keys;
|
|
184
|
+
if (!agent || !(end.allowed || end.enabled) || (role && currentRole !== role) || (eid && agent !== eid))
|
|
185
|
+
continue;
|
|
186
|
+
if (runtime.hby.habs.has(agent) && (!scope?.length || scope.includes(agent)))
|
|
187
|
+
return agent;
|
|
188
|
+
}
|
|
189
|
+
return undefined;
|
|
171
190
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keri-ts/hosting",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "HTTP host lifecycle, application middleware and protocol route composition",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"node": ">=20.3"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"cesr-ts": "2.2.
|
|
35
|
+
"cesr-ts": "2.2.1",
|
|
36
36
|
"effection": "^3.6.0",
|
|
37
37
|
"hono": "^4.7.11",
|
|
38
|
-
"keri-ts": "2.2.
|
|
38
|
+
"keri-ts": "2.2.3",
|
|
39
39
|
"@deno/shim-deno": "~0.18.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The router is path-first: every endpoint classifier receives the same
|
|
5
5
|
* normalized path plus hosted-prefix projections, so mailbox admin, OOBI, and
|
|
6
|
-
* generic CESR ingress cannot disagree about which local AID a URL addresses.
|
|
6
|
+
* generic CESR ingress cannot disagree about which local AID a URL addresses. When several local AIDs share
|
|
7
|
+
* one URL, the request's `CESR-DESTINATION` picks among them.
|
|
7
8
|
*/
|
|
8
9
|
import { type AgentRuntime, type ProtocolHostPolicy } from "keri-ts/runtime";
|
|
9
10
|
import type { ProtocolRequestContext } from "./types.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/src/http/protocol/context.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/src/http/protocol/context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,kBAAkB,EAExB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,gEAAgE;AAChE,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE,YAAY,EACtB,MAAM,GAAE,kBAAuB,GAC9B,sBAAsB,CAkDxB;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO9D"}
|
|
@@ -19,6 +19,10 @@ export declare function defaultOobiAid(runtime: AgentRuntime, serviceHab?: Hab,
|
|
|
19
19
|
* - the requested AID itself when locally controlled
|
|
20
20
|
* - the explicit endpoint AID when it is locally controlled
|
|
21
21
|
* - the hosted endpoint matched from the request path
|
|
22
|
+
* - a local identifier that an accepted end-role record of `aid` names as `eid` in the requested role, so a host
|
|
23
|
+
* serves the OOBI of an identifier it is the agent of even when it hosts no prefix directly. A non-empty
|
|
24
|
+
* `hostedPrefixes` is the operator's stated scope, so the named `eid` must be in it; when it is empty or absent,
|
|
25
|
+
* any local identifier qualifies.
|
|
22
26
|
*/
|
|
23
27
|
export declare function selectResponderHab(runtime: AgentRuntime, hosted: {
|
|
24
28
|
kind: "none" | "one" | "ambiguous";
|
|
@@ -27,5 +31,5 @@ export declare function selectResponderHab(runtime: AgentRuntime, hosted: {
|
|
|
27
31
|
url: string;
|
|
28
32
|
basePath: string;
|
|
29
33
|
} | null;
|
|
30
|
-
}, aid: string, eid?: string, hostedPrefixes?: readonly string[]): string | undefined;
|
|
34
|
+
}, aid: string, eid?: string, hostedPrefixes?: readonly string[], role?: string): string | undefined;
|
|
31
35
|
//# sourceMappingURL=oobi.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oobi.d.ts","sourceRoot":"","sources":["../../../../../src/src/http/protocol/endpoints/oobi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAuC,KAAK,GAAG,EAAuB,MAAM,iBAAiB,CAAC;AAExH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE3F,kEAAkE;AAClE,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,GACf,gBAAgB,GAAG,IAAI,CAoCzB;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,sBAAsB,GAC9B,aAAa,GAAG,IAAI,CAWtB;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,gBAAgB,GACxB,QAAQ,
|
|
1
|
+
{"version":3,"file":"oobi.d.ts","sourceRoot":"","sources":["../../../../../src/src/http/protocol/endpoints/oobi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAuC,KAAK,GAAG,EAAuB,MAAM,iBAAiB,CAAC;AAExH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE3F,kEAAkE;AAClE,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,GACf,gBAAgB,GAAG,IAAI,CAoCzB;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,sBAAsB,GAC9B,aAAa,GAAG,IAAI,CAWtB;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,gBAAgB,GACxB,QAAQ,CA2DV;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,YAAY,EACrB,UAAU,CAAC,EAAE,GAAG,EAChB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,GACjC,MAAM,GAAG,SAAS,CAcpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,WAAW,CAAC;IACnC,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACjE,EACD,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,EAClC,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAsDpB"}
|