@astrale-os/kernel-server 0.4.17 → 0.5.0-beta.10

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.
Files changed (235) hide show
  1. package/dist/capture.d.ts +2 -0
  2. package/dist/capture.js +9 -0
  3. package/dist/cors/cors.d.ts +21 -0
  4. package/dist/cors/cors.js +135 -0
  5. package/dist/cors/index.d.ts +2 -0
  6. package/dist/cors/index.js +1 -0
  7. package/dist/cors/types.d.ts +11 -0
  8. package/dist/cors/types.js +1 -0
  9. package/dist/errors/availability.d.ts +10 -0
  10. package/dist/errors/availability.js +14 -0
  11. package/dist/errors/classify.d.ts +3 -0
  12. package/dist/errors/classify.js +41 -0
  13. package/dist/errors/index.d.ts +4 -0
  14. package/dist/errors/index.js +4 -0
  15. package/dist/errors/request-body.d.ts +7 -0
  16. package/dist/errors/request-body.js +14 -0
  17. package/dist/errors/response-body.d.ts +4 -0
  18. package/dist/errors/response-body.js +8 -0
  19. package/dist/index.d.ts +5 -12
  20. package/dist/index.js +4 -19
  21. package/dist/invocation/context.d.ts +6 -0
  22. package/dist/invocation/context.js +60 -0
  23. package/dist/invocation/identity.d.ts +9 -0
  24. package/dist/invocation/identity.js +11 -0
  25. package/dist/invocation/index.d.ts +4 -3
  26. package/dist/invocation/index.js +3 -3
  27. package/dist/invocation/publication-route.d.ts +13 -0
  28. package/dist/invocation/publication-route.js +44 -0
  29. package/dist/invocation/types.d.ts +62 -0
  30. package/dist/invocation/types.js +1 -0
  31. package/dist/issuer/exchange.d.ts +12 -0
  32. package/dist/issuer/exchange.js +136 -0
  33. package/dist/issuer/index.d.ts +3 -0
  34. package/dist/issuer/index.js +1 -0
  35. package/dist/issuer/routes.d.ts +13 -0
  36. package/dist/issuer/routes.js +149 -0
  37. package/dist/issuer/types.d.ts +11 -0
  38. package/dist/issuer/types.js +1 -0
  39. package/dist/lifecycle/active.d.ts +39 -0
  40. package/dist/lifecycle/active.js +199 -0
  41. package/dist/lifecycle/index.d.ts +1 -0
  42. package/dist/lifecycle/index.js +1 -0
  43. package/dist/publication/delivery/handler.d.ts +9 -0
  44. package/dist/publication/delivery/handler.js +127 -0
  45. package/dist/publication/delivery/index.d.ts +2 -0
  46. package/dist/publication/delivery/index.js +1 -0
  47. package/dist/publication/delivery/types.d.ts +11 -0
  48. package/dist/publication/delivery/types.js +1 -0
  49. package/dist/publication/index.d.ts +3 -0
  50. package/dist/publication/index.js +2 -0
  51. package/dist/publication/snapshot.d.ts +16 -0
  52. package/dist/publication/snapshot.js +37 -0
  53. package/dist/publication/table.d.ts +4 -0
  54. package/dist/publication/table.js +16 -0
  55. package/dist/publication/types.d.ts +22 -0
  56. package/dist/publication/types.js +1 -0
  57. package/dist/routes/index.d.ts +1 -0
  58. package/dist/routes/index.js +1 -0
  59. package/dist/routes/routes.d.ts +25 -0
  60. package/dist/routes/routes.js +448 -0
  61. package/dist/server.d.ts +4 -0
  62. package/dist/server.js +266 -0
  63. package/dist/transport/body.d.ts +4 -0
  64. package/dist/transport/body.js +50 -0
  65. package/dist/transport/codecs.d.ts +4 -0
  66. package/dist/transport/codecs.js +5 -0
  67. package/dist/transport/credential.d.ts +10 -0
  68. package/dist/transport/credential.js +28 -0
  69. package/dist/transport/http/handler.d.ts +17 -0
  70. package/dist/transport/http/handler.js +180 -0
  71. package/dist/transport/http/index.d.ts +2 -0
  72. package/dist/transport/http/index.js +2 -0
  73. package/dist/transport/http/render.d.ts +31 -0
  74. package/dist/transport/http/render.js +288 -0
  75. package/dist/transport/index.d.ts +9 -0
  76. package/dist/transport/index.js +8 -0
  77. package/dist/transport/router.d.ts +4 -0
  78. package/dist/transport/router.js +4 -0
  79. package/dist/transport/stream-error.d.ts +3 -0
  80. package/dist/transport/stream-error.js +13 -0
  81. package/dist/transport/types.d.ts +28 -0
  82. package/dist/transport/types.js +1 -0
  83. package/dist/transport/websocket/index.d.ts +2 -0
  84. package/dist/transport/websocket/index.js +2 -0
  85. package/dist/transport/websocket/session.d.ts +20 -0
  86. package/dist/transport/websocket/session.js +335 -0
  87. package/dist/transport/websocket/upgrade.d.ts +20 -0
  88. package/dist/transport/websocket/upgrade.js +46 -0
  89. package/dist/types.d.ts +65 -0
  90. package/dist/types.js +1 -0
  91. package/package.json +24 -14
  92. package/dist/app/create.d.ts +0 -48
  93. package/dist/app/create.d.ts.map +0 -1
  94. package/dist/app/create.js +0 -108
  95. package/dist/app/create.js.map +0 -1
  96. package/dist/app/index.d.ts +0 -4
  97. package/dist/app/index.d.ts.map +0 -1
  98. package/dist/app/index.js +0 -4
  99. package/dist/app/index.js.map +0 -1
  100. package/dist/app/multiplexed.d.ts +0 -53
  101. package/dist/app/multiplexed.d.ts.map +0 -1
  102. package/dist/app/multiplexed.js +0 -64
  103. package/dist/app/multiplexed.js.map +0 -1
  104. package/dist/app/ws-upgrade.d.ts +0 -34
  105. package/dist/app/ws-upgrade.d.ts.map +0 -1
  106. package/dist/app/ws-upgrade.js +0 -94
  107. package/dist/app/ws-upgrade.js.map +0 -1
  108. package/dist/capabilities/contract.d.ts +0 -8
  109. package/dist/capabilities/contract.d.ts.map +0 -1
  110. package/dist/capabilities/contract.js +0 -2
  111. package/dist/capabilities/contract.js.map +0 -1
  112. package/dist/capabilities/defer.d.ts +0 -4
  113. package/dist/capabilities/defer.d.ts.map +0 -1
  114. package/dist/capabilities/defer.js +0 -2
  115. package/dist/capabilities/defer.js.map +0 -1
  116. package/dist/capabilities/hono.d.ts +0 -8
  117. package/dist/capabilities/hono.d.ts.map +0 -1
  118. package/dist/capabilities/hono.js +0 -13
  119. package/dist/capabilities/hono.js.map +0 -1
  120. package/dist/capabilities/index.d.ts +0 -6
  121. package/dist/capabilities/index.d.ts.map +0 -1
  122. package/dist/capabilities/index.js +0 -3
  123. package/dist/capabilities/index.js.map +0 -1
  124. package/dist/capabilities/lifecycle.d.ts +0 -17
  125. package/dist/capabilities/lifecycle.d.ts.map +0 -1
  126. package/dist/capabilities/lifecycle.js +0 -37
  127. package/dist/capabilities/lifecycle.js.map +0 -1
  128. package/dist/capabilities/sleep.d.ts +0 -4
  129. package/dist/capabilities/sleep.d.ts.map +0 -1
  130. package/dist/capabilities/sleep.js +0 -8
  131. package/dist/capabilities/sleep.js.map +0 -1
  132. package/dist/cors.d.ts +0 -21
  133. package/dist/cors.d.ts.map +0 -1
  134. package/dist/cors.js +0 -17
  135. package/dist/cors.js.map +0 -1
  136. package/dist/envelope/batch.d.ts +0 -13
  137. package/dist/envelope/batch.d.ts.map +0 -1
  138. package/dist/envelope/batch.js +0 -96
  139. package/dist/envelope/batch.js.map +0 -1
  140. package/dist/envelope/codec.d.ts +0 -26
  141. package/dist/envelope/codec.d.ts.map +0 -1
  142. package/dist/envelope/codec.js +0 -52
  143. package/dist/envelope/codec.js.map +0 -1
  144. package/dist/envelope/credential.d.ts +0 -20
  145. package/dist/envelope/credential.d.ts.map +0 -1
  146. package/dist/envelope/credential.js +0 -32
  147. package/dist/envelope/credential.js.map +0 -1
  148. package/dist/envelope/http.d.ts +0 -31
  149. package/dist/envelope/http.d.ts.map +0 -1
  150. package/dist/envelope/http.js +0 -132
  151. package/dist/envelope/http.js.map +0 -1
  152. package/dist/envelope/sse.d.ts +0 -11
  153. package/dist/envelope/sse.d.ts.map +0 -1
  154. package/dist/envelope/sse.js +0 -73
  155. package/dist/envelope/sse.js.map +0 -1
  156. package/dist/envelope/ws.d.ts +0 -35
  157. package/dist/envelope/ws.d.ts.map +0 -1
  158. package/dist/envelope/ws.js +0 -142
  159. package/dist/envelope/ws.js.map +0 -1
  160. package/dist/index.d.ts.map +0 -1
  161. package/dist/index.js.map +0 -1
  162. package/dist/invocation/dispatch.d.ts +0 -32
  163. package/dist/invocation/dispatch.d.ts.map +0 -1
  164. package/dist/invocation/dispatch.js +0 -68
  165. package/dist/invocation/dispatch.js.map +0 -1
  166. package/dist/invocation/dispatcher.d.ts +0 -19
  167. package/dist/invocation/dispatcher.d.ts.map +0 -1
  168. package/dist/invocation/dispatcher.js +0 -9
  169. package/dist/invocation/dispatcher.js.map +0 -1
  170. package/dist/invocation/index.d.ts.map +0 -1
  171. package/dist/invocation/index.js.map +0 -1
  172. package/dist/jwks/discovery.d.ts +0 -40
  173. package/dist/jwks/discovery.d.ts.map +0 -1
  174. package/dist/jwks/discovery.js +0 -113
  175. package/dist/jwks/discovery.js.map +0 -1
  176. package/dist/jwks/index.d.ts +0 -3
  177. package/dist/jwks/index.d.ts.map +0 -1
  178. package/dist/jwks/index.js +0 -3
  179. package/dist/jwks/index.js.map +0 -1
  180. package/dist/jwks/issuers.d.ts +0 -47
  181. package/dist/jwks/issuers.d.ts.map +0 -1
  182. package/dist/jwks/issuers.js +0 -76
  183. package/dist/jwks/issuers.js.map +0 -1
  184. package/dist/jwks/keys.d.ts +0 -44
  185. package/dist/jwks/keys.d.ts.map +0 -1
  186. package/dist/jwks/keys.js +0 -56
  187. package/dist/jwks/keys.js.map +0 -1
  188. package/dist/plan/host-params.d.ts +0 -13
  189. package/dist/plan/host-params.d.ts.map +0 -1
  190. package/dist/plan/host-params.js +0 -23
  191. package/dist/plan/host-params.js.map +0 -1
  192. package/dist/plan/host.d.ts +0 -24
  193. package/dist/plan/host.d.ts.map +0 -1
  194. package/dist/plan/host.js +0 -24
  195. package/dist/plan/host.js.map +0 -1
  196. package/dist/plan/index.d.ts +0 -4
  197. package/dist/plan/index.d.ts.map +0 -1
  198. package/dist/plan/index.js +0 -4
  199. package/dist/plan/index.js.map +0 -1
  200. package/dist/plan/walk.d.ts +0 -51
  201. package/dist/plan/walk.d.ts.map +0 -1
  202. package/dist/plan/walk.js +0 -110
  203. package/dist/plan/walk.js.map +0 -1
  204. package/dist/render/binary.d.ts +0 -19
  205. package/dist/render/binary.d.ts.map +0 -1
  206. package/dist/render/binary.js +0 -33
  207. package/dist/render/binary.js.map +0 -1
  208. package/dist/render/body.d.ts +0 -10
  209. package/dist/render/body.d.ts.map +0 -1
  210. package/dist/render/body.js +0 -17
  211. package/dist/render/body.js.map +0 -1
  212. package/dist/render/index.d.ts +0 -3
  213. package/dist/render/index.d.ts.map +0 -1
  214. package/dist/render/index.js +0 -3
  215. package/dist/render/index.js.map +0 -1
  216. package/dist/routed/credential.d.ts +0 -10
  217. package/dist/routed/credential.d.ts.map +0 -1
  218. package/dist/routed/credential.js +0 -55
  219. package/dist/routed/credential.js.map +0 -1
  220. package/dist/routed/handler.d.ts +0 -38
  221. package/dist/routed/handler.d.ts.map +0 -1
  222. package/dist/routed/handler.js +0 -123
  223. package/dist/routed/handler.js.map +0 -1
  224. package/dist/routed/index.d.ts +0 -5
  225. package/dist/routed/index.d.ts.map +0 -1
  226. package/dist/routed/index.js +0 -5
  227. package/dist/routed/index.js.map +0 -1
  228. package/dist/routed/params.d.ts +0 -40
  229. package/dist/routed/params.d.ts.map +0 -1
  230. package/dist/routed/params.js +0 -146
  231. package/dist/routed/params.js.map +0 -1
  232. package/dist/routed/stream.d.ts +0 -21
  233. package/dist/routed/stream.d.ts.map +0 -1
  234. package/dist/routed/stream.js +0 -69
  235. package/dist/routed/stream.js.map +0 -1
@@ -0,0 +1,2 @@
1
+ /** Capture one receiver-bound method while preserving the capability's exact method type. */
2
+ export declare function captureMethod<Receiver extends object, Name extends keyof Receiver>(input: Receiver, name: Name, invalidMessage: string): Receiver[Name];
@@ -0,0 +1,9 @@
1
+ /** Capture one receiver-bound method while preserving the capability's exact method type. */
2
+ export function captureMethod(input, name, invalidMessage) {
3
+ if (input === null || typeof input !== 'object')
4
+ throw new TypeError(invalidMessage);
5
+ const method = input[name];
6
+ if (typeof method !== 'function')
7
+ throw new TypeError(invalidMessage);
8
+ return method.bind(input);
9
+ }
@@ -0,0 +1,21 @@
1
+ /** Request-aware CORS admission shared by every Server-owned HTTP surface. */
2
+ import type { CorsConfig } from './types.js';
3
+ export interface CorsRoute {
4
+ /** Methods that can actually select this route; OPTIONS is added by the policy. */
5
+ readonly methods: readonly string[];
6
+ /** Request headers owned by this route, in addition to the CORS safelist. */
7
+ readonly headers?: readonly string[];
8
+ /** A declared wildcard-header mapping may receive other caller-selected headers. */
9
+ readonly allowAnyHeaders?: boolean;
10
+ }
11
+ export interface CorsPolicy {
12
+ readonly enabled: boolean;
13
+ /** Apply the configured browser-origin rule without treating WebSocket as CORS. */
14
+ allowsBrowserOrigin(request: Request): boolean;
15
+ /** Headers for one ordinary response. Exposed names are additive and canonicalized. */
16
+ response(request: Request, exposedHeaders?: readonly string[]): Readonly<Record<string, string>>;
17
+ /** Validate and answer one route-aware browser preflight without semantic dispatch. */
18
+ preflight(request: Request, route: CorsRoute | undefined): Response;
19
+ }
20
+ /** Admit one immutable policy. `false` delegates the complete concern to an outer application. */
21
+ export declare function prepareCors(input: CorsConfig | false | undefined): CorsPolicy;
@@ -0,0 +1,135 @@
1
+ /** Request-aware CORS admission shared by every Server-owned HTTP surface. */
2
+ const TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/u;
3
+ /** Admit one immutable policy. `false` delegates the complete concern to an outer application. */
4
+ export function prepareCors(input) {
5
+ if (input === false)
6
+ return DISABLED;
7
+ const config = input ?? { origin: '*' };
8
+ const origin = admitHeaderValue(config.origin, 'CORS origin');
9
+ const methods = config.methods === undefined ? undefined : methodSet(config.methods, 'CORS method');
10
+ const headers = config.headers === undefined ? undefined : tokenSet(config.headers, 'CORS header');
11
+ const exposedHeaders = tokenSet(config.exposedHeaders ?? [], 'CORS exposed header');
12
+ const credentials = config.credentials === true;
13
+ if (credentials && origin === '*') {
14
+ throw new TypeError('Credentialed CORS requires one explicit origin.');
15
+ }
16
+ const response = (request, dynamicExposed = []) => {
17
+ const requestOrigin = request.headers.get('origin');
18
+ if (requestOrigin !== null && origin !== '*' && requestOrigin !== origin)
19
+ return Object.freeze({});
20
+ const output = {
21
+ 'access-control-allow-origin': origin,
22
+ };
23
+ if (credentials)
24
+ output['access-control-allow-credentials'] = 'true';
25
+ const exposed = new Set(exposedHeaders);
26
+ for (const name of dynamicExposed)
27
+ exposed.add(admitToken(name, 'CORS exposed header').toLowerCase());
28
+ if (exposed.size > 0)
29
+ output['access-control-expose-headers'] = [...exposed].join(', ');
30
+ if (origin !== '*')
31
+ output.vary = 'origin';
32
+ return Object.freeze(output);
33
+ };
34
+ return Object.freeze({
35
+ enabled: true,
36
+ allowsBrowserOrigin(request) {
37
+ const requestOrigin = request.headers.get('origin');
38
+ return requestOrigin === null || origin === '*' || requestOrigin === origin;
39
+ },
40
+ response,
41
+ preflight(request, route) {
42
+ const requestOrigin = request.headers.get('origin');
43
+ const requestedMethod = request.headers.get('access-control-request-method')?.toUpperCase();
44
+ if (requestOrigin === null || requestedMethod === undefined) {
45
+ return new Response(null, { status: 400, headers: response(request) });
46
+ }
47
+ if (origin !== '*' && requestOrigin !== origin)
48
+ return new Response(null, { status: 403 });
49
+ if (route === undefined) {
50
+ return new Response(null, { status: 404, headers: response(request) });
51
+ }
52
+ const routeMethods = methodSet(route.methods, 'CORS route method');
53
+ const methodAllowed = routeMethods.has(requestedMethod) && (methods?.has(requestedMethod) ?? true);
54
+ if (!methodAllowed) {
55
+ return new Response(null, { status: 405, headers: response(request) });
56
+ }
57
+ const requestedHeaders = parseRequestedHeaders(request.headers.get('access-control-request-headers'));
58
+ const routeHeaders = tokenSet(route.headers ?? [], 'CORS route header');
59
+ const headerAllowed = (name) => (route.allowAnyHeaders === true || routeHeaders.has(name)) && (headers?.has(name) ?? true);
60
+ if (requestedHeaders.some((name) => !headerAllowed(name))) {
61
+ return new Response(null, { status: 403, headers: response(request) });
62
+ }
63
+ const allowedMethods = [...routeMethods].filter((method) => methods?.has(method) ?? true);
64
+ const allowedHeaders = requestedHeaders.length > 0 ? requestedHeaders : [...routeHeaders];
65
+ const output = new Headers(response(request));
66
+ output.set('access-control-allow-methods', [...allowedMethods, 'OPTIONS'].join(', '));
67
+ if (allowedHeaders.length > 0) {
68
+ output.set('access-control-allow-headers', allowedHeaders.join(', '));
69
+ }
70
+ appendVary(output, 'access-control-request-method');
71
+ appendVary(output, 'access-control-request-headers');
72
+ return new Response(null, { status: 204, headers: output });
73
+ },
74
+ });
75
+ }
76
+ const DISABLED = Object.freeze({
77
+ enabled: false,
78
+ allowsBrowserOrigin: () => true,
79
+ response: () => Object.freeze({}),
80
+ preflight: () => new Response(null, { status: 405 }),
81
+ });
82
+ function parseRequestedHeaders(input) {
83
+ if (input === null || input.trim() === '')
84
+ return [];
85
+ const output = [];
86
+ const seen = new Set();
87
+ for (const raw of input.split(',')) {
88
+ const name = admitToken(raw.trim(), 'CORS requested header').toLowerCase();
89
+ if (!seen.has(name)) {
90
+ seen.add(name);
91
+ output.push(name);
92
+ }
93
+ }
94
+ return output;
95
+ }
96
+ function tokenSet(input, label) {
97
+ const output = new Set();
98
+ for (const value of input)
99
+ output.add(admitToken(value, label).toLowerCase());
100
+ return output;
101
+ }
102
+ function methodSet(input, label) {
103
+ const output = new Set();
104
+ for (const value of input)
105
+ output.add(admitToken(value, label).toUpperCase());
106
+ return output;
107
+ }
108
+ function admitHeaderValue(input, label) {
109
+ if (typeof input !== 'string' || input.length === 0 || hasControlCharacter(input)) {
110
+ throw new TypeError(`${label} must be a non-empty control-free string.`);
111
+ }
112
+ return input;
113
+ }
114
+ function hasControlCharacter(input) {
115
+ for (let index = 0; index < input.length; index += 1) {
116
+ const code = input.charCodeAt(index);
117
+ if (code <= 0x1f || code === 0x7f)
118
+ return true;
119
+ }
120
+ return false;
121
+ }
122
+ function admitToken(input, label) {
123
+ if (typeof input !== 'string' || !TOKEN.test(input))
124
+ throw new TypeError(`${label} must be an HTTP token.`);
125
+ return input;
126
+ }
127
+ function appendVary(headers, value) {
128
+ const current = headers.get('vary');
129
+ const names = new Set(current
130
+ ?.split(',')
131
+ .map((name) => name.trim().toLowerCase())
132
+ .filter(Boolean) ?? []);
133
+ names.add(value);
134
+ headers.set('vary', [...names].join(', '));
135
+ }
@@ -0,0 +1,2 @@
1
+ export { prepareCors, type CorsPolicy, type CorsRoute } from './cors.js';
2
+ export type { CorsConfig } from './types.js';
@@ -0,0 +1 @@
1
+ export { prepareCors } from './cors.js';
@@ -0,0 +1,11 @@
1
+ export interface CorsConfig {
2
+ readonly origin: string;
3
+ /** Optional global preflight ceiling; actual responses are narrowed to the matched route. */
4
+ readonly methods?: readonly string[];
5
+ /** Optional global preflight ceiling; route-owned request headers are still matched exactly. */
6
+ readonly headers?: readonly string[];
7
+ /** Additional response headers that browser JavaScript may observe. */
8
+ readonly exposedHeaders?: readonly string[];
9
+ /** Emit Access-Control-Allow-Credentials; requires one explicit origin rather than `*`. */
10
+ readonly credentials?: boolean;
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ /** Expected loss of the external capability used to create a Delivery. */
2
+ export declare class DeliveryUnavailableError extends Error {
3
+ readonly name = "DeliveryUnavailableError";
4
+ constructor(message?: string, options?: ErrorOptions);
5
+ }
6
+ /** Expected loss of the external capability used to load public issuer keys. */
7
+ export declare class IssuerKeysUnavailableError extends Error {
8
+ readonly name = "IssuerKeysUnavailableError";
9
+ constructor(message?: string, options?: ErrorOptions);
10
+ }
@@ -0,0 +1,14 @@
1
+ /** Expected loss of the external capability used to create a Delivery. */
2
+ export class DeliveryUnavailableError extends Error {
3
+ name = 'DeliveryUnavailableError';
4
+ constructor(message = 'Delivery is unavailable.', options) {
5
+ super(message, options);
6
+ }
7
+ }
8
+ /** Expected loss of the external capability used to load public issuer keys. */
9
+ export class IssuerKeysUnavailableError extends Error {
10
+ name = 'IssuerKeysUnavailableError';
11
+ constructor(message = 'Issuer keys are unavailable.', options) {
12
+ super(message, options);
13
+ }
14
+ }
@@ -0,0 +1,3 @@
1
+ import * as errors from '@astrale-os/kernel-protocol/errors';
2
+ /** Convert only errors owned by an admitted Server or Protocol boundary into safe public data. */
3
+ export declare function classifyError(input: unknown): errors.ErrorPayload;
@@ -0,0 +1,41 @@
1
+ import { PathError } from '@astrale-os/kernel-core/path';
2
+ import * as errors from '@astrale-os/kernel-protocol/errors';
3
+ import { RequestBodyTooLargeError } from './request-body.js';
4
+ import { ResponseBodyTooLargeError } from './response-body.js';
5
+ /** Convert only errors owned by an admitted Server or Protocol boundary into safe public data. */
6
+ export function classifyError(input) {
7
+ if (input instanceof errors.ProtocolError)
8
+ return input.payload;
9
+ if (input instanceof RequestBodyTooLargeError) {
10
+ return publicError('LIMIT_EXCEEDED', 'Request body exceeds the configured limit.');
11
+ }
12
+ if (input instanceof ResponseBodyTooLargeError) {
13
+ return publicError('LIMIT_EXCEEDED', 'Response body exceeds the configured limit.');
14
+ }
15
+ if (input instanceof PathError) {
16
+ return publicError('VALIDATION_ERROR', 'Target Path is invalid.');
17
+ }
18
+ return internal(input);
19
+ }
20
+ function publicError(name, message) {
21
+ return { code: errors.CODES[name], message };
22
+ }
23
+ function internal(input) {
24
+ reportInternal(input);
25
+ return publicError('INTERNAL_ERROR', 'Internal application error.');
26
+ }
27
+ function stableCode(input) {
28
+ if (input !== null && typeof input === 'object' && 'code' in input) {
29
+ return typeof input.code === 'string' ? input.code : undefined;
30
+ }
31
+ return undefined;
32
+ }
33
+ function reportInternal(input) {
34
+ const error = input instanceof Error ? input : undefined;
35
+ // Never print the message, cause, input, credentials, query, or backend command.
36
+ // oxlint-disable-next-line no-console
37
+ console.error('[server] Internal dispatch failure', {
38
+ type: error?.constructor.name ?? typeof input,
39
+ code: stableCode(input),
40
+ });
41
+ }
@@ -0,0 +1,4 @@
1
+ export { DeliveryUnavailableError, IssuerKeysUnavailableError } from './availability.js';
2
+ export { classifyError } from './classify.js';
3
+ export { RequestBodyInvalidError, RequestBodyTooLargeError } from './request-body.js';
4
+ export { ResponseBodyTooLargeError } from './response-body.js';
@@ -0,0 +1,4 @@
1
+ export { DeliveryUnavailableError, IssuerKeysUnavailableError } from './availability.js';
2
+ export { classifyError } from './classify.js';
3
+ export { RequestBodyInvalidError, RequestBodyTooLargeError } from './request-body.js';
4
+ export { ResponseBodyTooLargeError } from './response-body.js';
@@ -0,0 +1,7 @@
1
+ export declare class RequestBodyTooLargeError extends Error {
2
+ readonly maximumBytes: number;
3
+ constructor(maximumBytes: number);
4
+ }
5
+ export declare class RequestBodyInvalidError extends Error {
6
+ constructor(message: string);
7
+ }
@@ -0,0 +1,14 @@
1
+ export class RequestBodyTooLargeError extends Error {
2
+ maximumBytes;
3
+ constructor(maximumBytes) {
4
+ super(`Request body exceeds ${maximumBytes} bytes.`);
5
+ this.maximumBytes = maximumBytes;
6
+ this.name = 'RequestBodyTooLargeError';
7
+ }
8
+ }
9
+ export class RequestBodyInvalidError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = 'RequestBodyInvalidError';
13
+ }
14
+ }
@@ -0,0 +1,4 @@
1
+ export declare class ResponseBodyTooLargeError extends Error {
2
+ readonly maximumBytes: number;
3
+ constructor(maximumBytes: number);
4
+ }
@@ -0,0 +1,8 @@
1
+ export class ResponseBodyTooLargeError extends Error {
2
+ maximumBytes;
3
+ constructor(maximumBytes) {
4
+ super(`Server response exceeds maximumResponseBytes (${maximumBytes}).`);
5
+ this.maximumBytes = maximumBytes;
6
+ this.name = 'ResponseBodyTooLargeError';
7
+ }
8
+ }
package/dist/index.d.ts CHANGED
@@ -1,12 +1,5 @@
1
- export { createKernelApp, type KernelAppConfig, type WsAdapter } from './app/create.js';
2
- export { createMultiplexedKernelApp, type MultiplexedKernelAppConfig, type DispatcherResolver, } from './app/multiplexed.js';
3
- export { walkDomain, type ServerHost, type MountedFunction, type MountedRoute, type MountPlan, } from './plan/index.js';
4
- export { buildCorsHeaders, type CorsConfig } from './cors.js';
5
- export { createKernelDispatcher, type KernelDispatcherOptions } from './envelope/http.js';
6
- export { KernelWsConnection, type WebSocketLike } from './envelope/ws.js';
7
- export { createCapabilityLifecycle, honoCapabilityHost, type CapabilityHost, type CapabilityLifecycle, type Defer, type DeferredTask, type Capabilities, type Sleep, } from './capabilities/index.js';
8
- export { dispatchInvocation, executeInvocation, kernelDispatcher, type Invocation, type InvocationPath, type InvocationReply, type InvocationResponse, type Dispatcher, } from './invocation/index.js';
9
- export { createRouteHandler, type RouteHandlerConfig } from './routed/index.js';
10
- export { mountJwks, mountInstanceJwks, mountIssuerRegistry, mountInstanceIssuerRegistry, type JwksKeys, type MultiplexedJwks, type JwksConfig, type InstanceJwksConfig, type IssuerRegistryConfig, type InstanceIssuerRegistryConfig, } from './jwks/index.js';
11
- export { classifyError } from '@astrale-os/kernel-api';
12
- //# sourceMappingURL=index.d.ts.map
1
+ export { createServer, prepareServer } from './server.js';
2
+ export { DeliveryUnavailableError, IssuerKeysUnavailableError } from './errors/index.js';
3
+ export { preparePublicationSnapshot } from './publication/index.js';
4
+ export * as publication from './publication/index.js';
5
+ export type { Application, ApplicationHost, CorsConfig, ExecutionControl, Handler, HandlerRequest, HandlerResult, HandlerStream, HealthProbe, InvocationContext, InvocationSource, RequestBackground, RequestEvidence, RequestSleep, Issuer, exchange, PreparedServer, PublicationSnapshot, PublicationSnapshotInput, PublicationSource, Server, ServerCloseOptions, ServerConfig, ServerLimits, ServerOptions, WebSocketAdapter, WebSocketHandlers, WebSocketLike, WebSocketUpgradeOptions, } from './types.js';
package/dist/index.js CHANGED
@@ -1,19 +1,4 @@
1
- // ─── App entry points ─────────────────────────────────────────────────────────
2
- export { createKernelApp } from './app/create.js';
3
- export { createMultiplexedKernelApp, } from './app/multiplexed.js';
4
- // ─── Plan ────────────────────────────────────────────────────────────────────
5
- export { walkDomain, } from './plan/index.js';
6
- // ─── Cross-cutting ───────────────────────────────────────────────────────────
7
- export { buildCorsHeaders } from './cors.js';
8
- // ─── Kernel envelope dispatcher ──────────────────────────────────────────────
9
- export { createKernelDispatcher } from './envelope/http.js';
10
- export { KernelWsConnection } from './envelope/ws.js';
11
- export { createCapabilityLifecycle, honoCapabilityHost, } from './capabilities/index.js';
12
- export { dispatchInvocation, executeInvocation, kernelDispatcher, } from './invocation/index.js';
13
- // ─── Routed HTTP handler (per-route) ─────────────────────────────────────────
14
- export { createRouteHandler } from './routed/index.js';
15
- // ─── JWKS (OIDC Discovery + JSON Web Key Set) ───────────────────────────────
16
- export { mountJwks, mountInstanceJwks, mountIssuerRegistry, mountInstanceIssuerRegistry, } from './jwks/index.js';
17
- // ─── Dispatch (for custom integrations) ──────────────────────────────────────
18
- export { classifyError } from '@astrale-os/kernel-api';
19
- //# sourceMappingURL=index.js.map
1
+ export { createServer, prepareServer } from './server.js';
2
+ export { DeliveryUnavailableError, IssuerKeysUnavailableError } from './errors/index.js';
3
+ export { preparePublicationSnapshot } from './publication/index.js';
4
+ export * as publication from './publication/index.js';
@@ -0,0 +1,6 @@
1
+ import type * as protocol from '@astrale-os/kernel-protocol/invocation';
2
+ import type { ActiveOperation, ActiveOperations } from '../lifecycle/index.js';
3
+ import type { ApplicationHost, InvocationContext } from './types.js';
4
+ export declare function invocationContext(assigned: protocol.InvocationId, operation: ActiveOperation, active: ActiveOperations, host?: ApplicationHost, requestBody?: Uint8Array, idempotencyKey?: protocol.IdempotencyKey): InvocationContext;
5
+ /** Default non-durable timer used when the application host supplies no timer capability. */
6
+ export declare function defaultSleep(durationMs: number): Promise<void>;
@@ -0,0 +1,60 @@
1
+ export function invocationContext(assigned, operation, active, host, requestBody, idempotencyKey) {
2
+ const body = requestBody?.slice();
3
+ return Object.freeze({
4
+ invocation: assigned,
5
+ execution: Object.freeze({ deadline: operation.deadline, signal: operation.signal }),
6
+ background: (task) => active.background(task, host?.waitUntil),
7
+ sleep: async (durationMs) => {
8
+ await interruptibleSleep(sleepDuration(durationMs), operation.signal, host?.sleep);
9
+ },
10
+ ...(idempotencyKey === undefined ? {} : { idempotencyKey }),
11
+ ...(body === undefined ? {} : { request: Object.freeze({ body: () => body.slice() }) }),
12
+ });
13
+ }
14
+ /** Default non-durable timer used when the application host supplies no timer capability. */
15
+ export async function defaultSleep(durationMs) {
16
+ await new Promise((resolve) => setTimeout(resolve, sleepDuration(durationMs)));
17
+ }
18
+ async function interruptibleSleep(durationMs, signal, sleep) {
19
+ if (signal.aborted)
20
+ throw abortCause(signal);
21
+ if (sleep === undefined) {
22
+ await new Promise((resolve, reject) => {
23
+ const timer = setTimeout(() => finish(resolve), durationMs);
24
+ const abort = () => {
25
+ clearTimeout(timer);
26
+ finish(() => reject(abortCause(signal)));
27
+ };
28
+ const finish = (settle) => {
29
+ signal.removeEventListener('abort', abort);
30
+ settle();
31
+ };
32
+ signal.addEventListener('abort', abort, { once: true });
33
+ });
34
+ return;
35
+ }
36
+ await new Promise((resolve, reject) => {
37
+ let settled = false;
38
+ const finish = (settle) => {
39
+ if (settled)
40
+ return;
41
+ settled = true;
42
+ signal.removeEventListener('abort', abort);
43
+ settle();
44
+ };
45
+ const abort = () => finish(() => reject(abortCause(signal)));
46
+ signal.addEventListener('abort', abort, { once: true });
47
+ Promise.resolve()
48
+ .then(() => sleep(durationMs))
49
+ .then(() => finish(resolve), (cause) => finish(() => reject(cause)));
50
+ });
51
+ }
52
+ function abortCause(signal) {
53
+ return signal.reason instanceof Error ? signal.reason : new Error('Invocation was cancelled.');
54
+ }
55
+ function sleepDuration(input) {
56
+ if (!Number.isFinite(input) || input < 0 || input > 2_147_483_647) {
57
+ throw new RangeError('Sleep duration must be finite, non-negative, and within timer range.');
58
+ }
59
+ return input;
60
+ }
@@ -0,0 +1,9 @@
1
+ import type { IssuerId } from '@astrale-os/kernel-core/auth';
2
+ import type * as protocol from '@astrale-os/kernel-protocol/invocation';
3
+ /** Injected source-owned identity allocator captured before Server readiness. */
4
+ export interface InvocationSource {
5
+ readonly source: IssuerId;
6
+ next(): string;
7
+ }
8
+ export type NextInvocationId = () => protocol.InvocationId;
9
+ export declare function captureInvocationSource(input: InvocationSource): NextInvocationId;
@@ -0,0 +1,11 @@
1
+ import { issuer } from '@astrale-os/kernel-core/auth';
2
+ import * as protocolInvocation from '@astrale-os/kernel-protocol/invocation';
3
+ import { captureMethod } from '../capture.js';
4
+ export function captureInvocationSource(input) {
5
+ if (input === null || typeof input !== 'object') {
6
+ throw new TypeError('Server Invocation source is invalid.');
7
+ }
8
+ const source = issuer.accept(input.source);
9
+ const next = captureMethod(input, 'next', 'Server Invocation source is invalid.');
10
+ return () => protocolInvocation.acceptInvocationId({ source, id: next() });
11
+ }
@@ -1,3 +1,4 @@
1
- export { dispatchInvocation, executeInvocation, type InvocationReply, type InvocationResponse, } from './dispatch.js';
2
- export { kernelDispatcher, type Invocation, type InvocationPath, type Dispatcher, } from './dispatcher.js';
3
- //# sourceMappingURL=index.d.ts.map
1
+ export { defaultSleep, invocationContext } from './context.js';
2
+ export { captureInvocationSource, type InvocationSource, type NextInvocationId, } from './identity.js';
3
+ export { publicationRouteDecision, type PublicationRouteDecision } from './publication-route.js';
4
+ export type { ApplicationHost, ExecutionControl, Handler, HandlerRequest, HandlerResult, HandlerStream, InvocationContext, RequestBackground, RequestEvidence, RequestSleep, } from './types.js';
@@ -1,3 +1,3 @@
1
- export { dispatchInvocation, executeInvocation, } from './dispatch.js';
2
- export { kernelDispatcher, } from './dispatcher.js';
3
- //# sourceMappingURL=index.js.map
1
+ export { defaultSleep, invocationContext } from './context.js';
2
+ export { captureInvocationSource, } from './identity.js';
3
+ export { publicationRouteDecision } from './publication-route.js';
@@ -0,0 +1,13 @@
1
+ import type { ErrorPayload } from '@astrale-os/kernel-protocol/errors';
2
+ import type { Publication } from '@astrale-os/kernel-protocol/publication/publication';
3
+ import type { PublicationRef } from '@astrale-os/kernel-protocol/publication/reference';
4
+ export type PublicationRouteDecision = {
5
+ readonly kind: 'exact';
6
+ } | {
7
+ readonly kind: 'same-schema';
8
+ } | {
9
+ readonly kind: 'rejected';
10
+ readonly error: ErrorPayload;
11
+ };
12
+ /** Compare untrusted installed routing evidence with the one captured serving Publication. */
13
+ export declare function publicationRouteDecision(current: Publication, installed: PublicationRef): PublicationRouteDecision;
@@ -0,0 +1,44 @@
1
+ import { CODES } from '@astrale-os/kernel-protocol/errors';
2
+ import { SCHEMA_UPGRADE_REQUIRED, SERVICE_TRUST_REQUIRED, } from '@astrale-os/kernel-protocol/invocation/service-reason';
3
+ import { compareReference } from '@astrale-os/kernel-protocol/publication/reference';
4
+ /** Compare untrusted installed routing evidence with the one captured serving Publication. */
5
+ export function publicationRouteDecision(current, installed) {
6
+ switch (compareReference(current, installed)) {
7
+ case 'exact':
8
+ return Object.freeze({ kind: 'exact' });
9
+ case 'same-schema':
10
+ return Object.freeze({ kind: 'same-schema' });
11
+ case 'schema-drift':
12
+ return rejected('Installed Domain schema requires an explicit upgrade.', Object.freeze({
13
+ code: SCHEMA_UPGRADE_REQUIRED,
14
+ details: Object.freeze({
15
+ origin: installed.origin,
16
+ installedRevision: installed.revision,
17
+ candidateRevision: current.schema.revision,
18
+ }),
19
+ }));
20
+ case 'identity-drift':
21
+ return rejected('Installed Domain Service identity requires explicit trust.', Object.freeze({
22
+ code: SERVICE_TRUST_REQUIRED,
23
+ details: Object.freeze({
24
+ origin: installed.origin,
25
+ installedIssuer: installed.identity.issuer,
26
+ candidateIssuer: current.identity.issuer,
27
+ }),
28
+ }));
29
+ case 'origin-drift':
30
+ return Object.freeze({
31
+ kind: 'rejected',
32
+ error: Object.freeze({
33
+ code: CODES.INVALID_REQUEST,
34
+ message: 'Routed Publication origin differs from the served Domain.',
35
+ }),
36
+ });
37
+ }
38
+ }
39
+ function rejected(message, data) {
40
+ return Object.freeze({
41
+ kind: 'rejected',
42
+ error: Object.freeze({ code: CODES.CONFLICT, message, data }),
43
+ });
44
+ }
@@ -0,0 +1,62 @@
1
+ import type { CredentialInput } from '@astrale-os/kernel-core/auth';
2
+ import type { CallableResult } from '@astrale-os/kernel-core/callable';
3
+ import type { Value } from '@astrale-os/kernel-dsl/value';
4
+ import type * as protocol from '@astrale-os/kernel-protocol/invocation';
5
+ import type { PublicationSnapshot } from '../publication/index.js';
6
+ /** Optional platform retention and timer adaptation for one Fetch invocation. */
7
+ export interface ApplicationHost {
8
+ waitUntil(promise: Promise<unknown>): void;
9
+ readonly sleep?: (durationMs: number) => Promise<void>;
10
+ }
11
+ /** Ephemeral execution lifetime for one admitted request. */
12
+ export interface ExecutionControl {
13
+ readonly deadline: number;
14
+ readonly signal: AbortSignal;
15
+ }
16
+ /** Register non-durable work with the request owner. */
17
+ export type RequestBackground = (task: () => void | PromiseLike<unknown>) => void;
18
+ /** Request-owner timer bounded by the same cancellation and deadline. */
19
+ export type RequestSleep = (durationMs: number) => Promise<void>;
20
+ /** Exact bounded ingress evidence retained outside portable Function input. */
21
+ export interface RequestEvidence {
22
+ body(): Uint8Array;
23
+ }
24
+ /** Immutable lifetime and execution conveniences for one admitted dispatch. */
25
+ export interface InvocationContext {
26
+ readonly invocation: protocol.InvocationId;
27
+ readonly execution: ExecutionControl;
28
+ readonly idempotencyKey?: protocol.IdempotencyKey;
29
+ readonly request?: RequestEvidence;
30
+ readonly background: RequestBackground;
31
+ /** Rejects promptly when execution is cancelled or reaches its deadline. */
32
+ readonly sleep: RequestSleep;
33
+ }
34
+ export interface HandlerStream extends AsyncIterable<Value> {
35
+ cancel(reason?: string): Promise<void>;
36
+ }
37
+ /** Complete semantic result accepted from one ready application Handler. */
38
+ export type HandlerResult = CallableResult<Value, HandlerStream> | {
39
+ readonly kind: 'redirect';
40
+ readonly redirect: protocol.Redirection;
41
+ } | {
42
+ readonly kind: 'miss';
43
+ };
44
+ /** Ready semantic capability invoked by canonical and advertised transport routes. */
45
+ export interface HandlerRequest {
46
+ readonly call: protocol.Call;
47
+ /** Admitted transport correlation syntax, separate from semantic execution options. */
48
+ readonly trace?: protocol.Trace;
49
+ readonly credential?: CredentialInput;
50
+ /** Source-only effective delegation forwarded unchanged to Runtime. */
51
+ readonly delegate?: protocol.Delegate;
52
+ /** Destination routing witness forwarded after exact or same-schema Server admission. */
53
+ readonly via?: protocol.Via;
54
+ /** Source-only local-target or remote-revision Schema Registration precondition. */
55
+ readonly schema?: protocol.SchemaTarget;
56
+ /** Exact Server-pinned serving generation for a Publication-backed request. */
57
+ readonly publication?: PublicationSnapshot;
58
+ readonly context: InvocationContext;
59
+ }
60
+ export interface Handler {
61
+ dispatch(request: HandlerRequest): Promise<HandlerResult>;
62
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import * as exchangeProtocol from '@astrale-os/kernel-protocol/issuer/exchange';
2
+ import type { CorsPolicy } from '../cors/index.js';
3
+ import type { ActiveOperations } from '../lifecycle/index.js';
4
+ import type { ServerRouter } from '../transport/index.js';
5
+ export interface Context {
6
+ readonly signal: AbortSignal;
7
+ }
8
+ export interface Provider {
9
+ exchange(request: exchangeProtocol.Request, context: Context): Promise<exchangeProtocol.Response>;
10
+ }
11
+ export declare function capture(input: Provider): Provider;
12
+ export declare function mount(app: ServerRouter, issuer: string, provider: Provider, cors: CorsPolicy, active: ActiveOperations, timeoutMs: number): void;