@h-ai/serv 0.1.0-alpha.68 → 0.1.0-alpha.70
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/README.en.md +33 -1
- package/README.ja.md +33 -1
- package/README.md +33 -1
- package/dist/features/ai.d.ts +2 -2
- package/dist/features/feedback.d.ts +688 -0
- package/dist/features/feedback.js +82 -0
- package/dist/features/feedback.js.map +1 -0
- package/dist/features/iam.d.ts +1 -1
- package/dist/features/storage.d.ts +2 -2
- package/dist/index.d.ts +11 -4
- package/dist/index.js +27 -8
- package/dist/index.js.map +1 -1
- package/dist/{serv-context-C48WdBcd.d.ts → serv-context-B-AxU8hj.d.ts} +2 -0
- package/dist/{serv-router-BX8hgYxo.d.ts → serv-router-C8dSz2k-.d.ts} +1 -1
- package/package.json +23 -14
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { implement, servM } from '../chunk-TWHCU6HT.js';
|
|
2
|
+
import { apiContract } from '@h-ai/api-contract';
|
|
3
|
+
import { core, err, HaiCommonError } from '@h-ai/core';
|
|
4
|
+
|
|
5
|
+
function createFeedbackProcedures(deps) {
|
|
6
|
+
const contextFor = async (context) => {
|
|
7
|
+
try {
|
|
8
|
+
const actor = await deps.resolveContext(context);
|
|
9
|
+
if (!actor?.scopeId || actor.userId !== context.session.userId)
|
|
10
|
+
return err(HaiCommonError.FORBIDDEN, servM("serv_errorForbidden", { locale: context.locale }));
|
|
11
|
+
return { success: true, data: actor };
|
|
12
|
+
} catch {
|
|
13
|
+
return err(HaiCommonError.INTERNAL_ERROR, servM("serv_errorInternal", { locale: context.locale }));
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const router = implement(apiContract.feedback).context();
|
|
17
|
+
return router.route("reports.submit").auth().handle(async ({ input, context }) => {
|
|
18
|
+
const actor = await contextFor(context);
|
|
19
|
+
if (!actor.success)
|
|
20
|
+
return actor;
|
|
21
|
+
return core.context.run(actor.data, () => deps.feedback.submit(input, actor.data));
|
|
22
|
+
}).route("reports.list").auth().handle(async ({ input, context }) => {
|
|
23
|
+
const actor = await contextFor(context);
|
|
24
|
+
if (!actor.success)
|
|
25
|
+
return actor;
|
|
26
|
+
return core.context.run(actor.data, () => deps.feedback.list(input, actor.data));
|
|
27
|
+
}).route("reports.get").auth().handle(async ({ input, context }) => {
|
|
28
|
+
const actor = await contextFor(context);
|
|
29
|
+
if (!actor.success)
|
|
30
|
+
return actor;
|
|
31
|
+
return core.context.run(actor.data, () => deps.feedback.get(input.id, actor.data));
|
|
32
|
+
}).route("reports.getEvidence").auth().handle(async ({ input, context }) => {
|
|
33
|
+
const actor = await contextFor(context);
|
|
34
|
+
if (!actor.success)
|
|
35
|
+
return actor;
|
|
36
|
+
return core.context.run(actor.data, () => deps.feedback.getEvidence(input, actor.data));
|
|
37
|
+
}).route("reports.setStatus").auth().handle(async ({ input, context }) => {
|
|
38
|
+
const actor = await contextFor(context);
|
|
39
|
+
if (!actor.success)
|
|
40
|
+
return actor;
|
|
41
|
+
return core.context.run(actor.data, () => deps.feedback.setStatus(input, actor.data));
|
|
42
|
+
}).route("reports.retry").auth().handle(async ({ input, context }) => {
|
|
43
|
+
const actor = await contextFor(context);
|
|
44
|
+
if (!actor.success)
|
|
45
|
+
return actor;
|
|
46
|
+
return core.context.run(actor.data, () => deps.feedback.retry(input, actor.data));
|
|
47
|
+
}).route("reports.export").auth().handle(async ({ input, context }) => {
|
|
48
|
+
const actor = await contextFor(context);
|
|
49
|
+
if (!actor.success)
|
|
50
|
+
return actor;
|
|
51
|
+
return core.context.run(actor.data, () => deps.feedback.export(input, actor.data));
|
|
52
|
+
}).route("reports.getExport").auth().handle(async ({ input, context }) => {
|
|
53
|
+
const actor = await contextFor(context);
|
|
54
|
+
if (!actor.success)
|
|
55
|
+
return actor;
|
|
56
|
+
return core.context.run(actor.data, () => deps.feedback.getExport(input, actor.data));
|
|
57
|
+
}).route("reports.appendEvidence").auth().handle(async ({ input, context }) => {
|
|
58
|
+
const actor = await contextFor(context);
|
|
59
|
+
if (!actor.success)
|
|
60
|
+
return actor;
|
|
61
|
+
return core.context.run(actor.data, () => deps.feedback.appendEvidence(input, actor.data));
|
|
62
|
+
}).route("reports.completeCollection").auth().handle(async ({ input, context }) => {
|
|
63
|
+
const actor = await contextFor(context);
|
|
64
|
+
if (!actor.success)
|
|
65
|
+
return actor;
|
|
66
|
+
return core.context.run(actor.data, () => deps.feedback.completeCollection(input, actor.data));
|
|
67
|
+
}).route("attachments.upload").auth().handle(async ({ input, context }) => {
|
|
68
|
+
const actor = await contextFor(context);
|
|
69
|
+
if (!actor.success)
|
|
70
|
+
return actor;
|
|
71
|
+
return core.context.run(actor.data, () => deps.feedback.uploadAttachment(input, actor.data));
|
|
72
|
+
}).route("attachments.get").auth().handle(async ({ input, context }) => {
|
|
73
|
+
const actor = await contextFor(context);
|
|
74
|
+
if (!actor.success)
|
|
75
|
+
return actor;
|
|
76
|
+
return core.context.run(actor.data, () => deps.feedback.getAttachment(input, actor.data));
|
|
77
|
+
}).build();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { createFeedbackProcedures };
|
|
81
|
+
//# sourceMappingURL=feedback.js.map
|
|
82
|
+
//# sourceMappingURL=feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/features/serv-feature-feedback.ts"],"names":[],"mappings":"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","file":"feedback.js","sourcesContent":["/** @h-ai/serv — 按需挂载反馈领域,不接收客户端身份或对象存储路径。 */\nimport type { FeedbackContext, FeedbackFunctions } from '@h-ai/feedback'\nimport type { ServContext } from '../serv-context.js'\nimport type { AuthenticatedServContext } from '../serv-router.js'\nimport { apiContract } from '@h-ai/api-contract'\nimport { core, err, HaiCommonError } from '@h-ai/core'\nimport { servM } from '../serv-i18n.js'\nimport { implement } from '../serv-router.js'\n\n/**\n * 已认证请求到反馈范围的可信映射,返回 null 时拒绝访问。\n * @example\n * ```ts\n * import type { FeedbackProcedureDeps } from '@h-ai/serv/features/feedback'\n * import { feedback } from '@h-ai/feedback'\n * const deps: FeedbackProcedureDeps = { feedback, resolveContext: ({ session }) => ({ scopeId: 'tenant-from-server', userId: session.userId, permissions: session.permissions }) }\n * ```\n */\nexport interface FeedbackProcedureDeps {\n readonly feedback: FeedbackFunctions\n readonly resolveContext: (context: AuthenticatedServContext) => FeedbackContext | null | Promise<FeedbackContext | null>\n}\n\n/**\n * 创建反馈的默认 procedures。宿主解析租户与权限,领域模块再次检查资源范围。\n * @example\n * ```ts\n * import { feedback } from '@h-ai/feedback'\n * import { createFeedbackProcedures } from '@h-ai/serv/features/feedback'\n * const procedures = createFeedbackProcedures({ feedback, resolveContext: ({ session }) => ({ scopeId: 'trusted-tenant', userId: session.userId, permissions: session.permissions }) })\n * ```\n */\nexport function createFeedbackProcedures(deps: FeedbackProcedureDeps) {\n const contextFor = async (context: AuthenticatedServContext) => {\n try {\n const actor = await deps.resolveContext(context)\n if (!actor?.scopeId || actor.userId !== context.session.userId)\n return err(HaiCommonError.FORBIDDEN, servM('serv_errorForbidden', { locale: context.locale }))\n return { success: true as const, data: actor }\n }\n catch {\n return err(HaiCommonError.INTERNAL_ERROR, servM('serv_errorInternal', { locale: context.locale }))\n }\n }\n const router = implement(apiContract.feedback).context<ServContext>()\n return router\n .route('reports.submit')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.submit(input, actor.data))\n })\n .route('reports.list')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.list(input, actor.data))\n })\n .route('reports.get')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.get(input.id, actor.data))\n })\n .route('reports.getEvidence')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getEvidence(input, actor.data))\n })\n .route('reports.setStatus')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.setStatus(input, actor.data))\n })\n .route('reports.retry')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.retry(input, actor.data))\n })\n .route('reports.export')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.export(input, actor.data))\n })\n .route('reports.getExport')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getExport(input, actor.data))\n })\n .route('reports.appendEvidence')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.appendEvidence(input, actor.data))\n })\n .route('reports.completeCollection')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.completeCollection(input, actor.data))\n })\n .route('attachments.upload')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.uploadAttachment(input, actor.data))\n })\n .route('attachments.get')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getAttachment(input, actor.data))\n })\n .build()\n}\n"]}
|
package/dist/features/iam.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as zod from 'zod';
|
|
|
4
4
|
import * as _orpc_contract from '@orpc/contract';
|
|
5
5
|
import { IamFunctions } from '@h-ai/iam';
|
|
6
6
|
export { TokenPair } from '@h-ai/iam';
|
|
7
|
-
import { S as ServContext } from '../serv-context-
|
|
7
|
+
import { S as ServContext } from '../serv-context-B-AxU8hj.js';
|
|
8
8
|
import '@h-ai/core';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -2,8 +2,8 @@ import * as _orpc_server from '@orpc/server';
|
|
|
2
2
|
import * as zod_v4_core from 'zod/v4/core';
|
|
3
3
|
import * as zod from 'zod';
|
|
4
4
|
import { StorageFunctions } from '@h-ai/storage';
|
|
5
|
-
import { S as ServContext } from '../serv-context-
|
|
6
|
-
import { A as AuthenticatedServContext } from '../serv-router-
|
|
5
|
+
import { S as ServContext } from '../serv-context-B-AxU8hj.js';
|
|
6
|
+
import { A as AuthenticatedServContext } from '../serv-router-C8dSz2k-.js';
|
|
7
7
|
import '@h-ai/core';
|
|
8
8
|
|
|
9
9
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -3,15 +3,15 @@ import { HaiResult, ValidationFormError } from '@h-ai/core';
|
|
|
3
3
|
import { AIFunctions, AudioWsStartMessage, AudioFormat } from '@h-ai/ai';
|
|
4
4
|
import { AnyContractRouter, OpenAPI } from '@orpc/contract';
|
|
5
5
|
import { ProcedureHandler, ErrorMap, Meta, ProcedureHandlerOptions, ORPCErrorConstructorMap, Router } from '@orpc/server';
|
|
6
|
-
import { a as ServSession, S as ServContext, b as ServIam, R as RefreshCookieConfig, C as CreateServContext, c as ServRequestMetadata, p as parseRequestContext, d as buildAuthContextFactory } from './serv-context-
|
|
7
|
-
export { e as CreateServContextInput, N as NativeRefreshTokenTransportConfig, f as RefreshTokenPair } from './serv-context-
|
|
6
|
+
import { a as ServSession, S as ServContext, b as ServIam, R as RefreshCookieConfig, C as CreateServContext, c as ServRequestMetadata, p as parseRequestContext, d as buildAuthContextFactory } from './serv-context-B-AxU8hj.js';
|
|
7
|
+
export { e as CreateServContextInput, N as NativeRefreshTokenTransportConfig, f as RefreshTokenPair } from './serv-context-B-AxU8hj.js';
|
|
8
8
|
import { MiddlewareHandler } from 'hono';
|
|
9
9
|
import { z, ZodType } from 'zod';
|
|
10
10
|
import { TransportServerKeyRing, CryptoFunctions, TransportKeyStore } from '@h-ai/crypto';
|
|
11
11
|
import { ServerType } from '@hono/node-server';
|
|
12
12
|
import { AddressInfo } from 'node:net';
|
|
13
|
-
import { i as implement } from './serv-router-
|
|
14
|
-
export { A as AuthenticatedServContext, S as ServImplementer, a as ServRouteHandler, b as ServRoutePath, c as ServRouterBuilder } from './serv-router-
|
|
13
|
+
import { i as implement } from './serv-router-C8dSz2k-.js';
|
|
14
|
+
export { A as AuthenticatedServContext, S as ServImplementer, a as ServRouteHandler, b as ServRoutePath, c as ServRouterBuilder } from './serv-router-C8dSz2k-.js';
|
|
15
15
|
import { StorageFunctions } from '@h-ai/storage';
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -248,6 +248,8 @@ interface ServRpcHttpConfig {
|
|
|
248
248
|
* ```
|
|
249
249
|
*/
|
|
250
250
|
interface ServTransportRuntimeConfig {
|
|
251
|
+
/** 双向明文 UTF-8 字节上限;省略使用 1 MiB,范围 1 KiB~64 MiB。 */
|
|
252
|
+
readonly maxPlaintextBytes?: number;
|
|
251
253
|
readonly keyExchangePath: `/${string}`;
|
|
252
254
|
readonly excludePaths: readonly `/${string}`[];
|
|
253
255
|
}
|
|
@@ -334,6 +336,7 @@ type ServCorsRuntimeConfigInput = Partial<ServCorsRuntimeConfig>;
|
|
|
334
336
|
* ```
|
|
335
337
|
*/
|
|
336
338
|
type ServTransportRuntimeConfigInput = Partial<{
|
|
339
|
+
readonly maxPlaintextBytes: number;
|
|
337
340
|
readonly keyExchangePath: `/${string}`;
|
|
338
341
|
readonly excludePaths: readonly `/${string}`[];
|
|
339
342
|
}>;
|
|
@@ -428,6 +431,7 @@ declare const ServConfigSchema: z.ZodPipe<z.ZodObject<{
|
|
|
428
431
|
credentials: z.ZodDefault<z.ZodBoolean>;
|
|
429
432
|
}, z.core.$strip>>;
|
|
430
433
|
transport: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
|
|
434
|
+
maxPlaintextBytes: z.ZodOptional<z.ZodNumber>;
|
|
431
435
|
keyExchangePath: z.ZodDefault<z.ZodCustom<`/${string}`, `/${string}`>>;
|
|
432
436
|
excludePaths: z.ZodDefault<z.ZodArray<z.ZodCustom<`/${string}`, `/${string}`>>>;
|
|
433
437
|
}, z.core.$strip>]>>;
|
|
@@ -472,6 +476,7 @@ declare const ServConfigSchema: z.ZodPipe<z.ZodObject<{
|
|
|
472
476
|
transport?: false | {
|
|
473
477
|
keyExchangePath: `/${string}`;
|
|
474
478
|
excludePaths: `/${string}`[];
|
|
479
|
+
maxPlaintextBytes?: number | undefined;
|
|
475
480
|
} | undefined;
|
|
476
481
|
}>>;
|
|
477
482
|
|
|
@@ -511,6 +516,8 @@ declare const ServConfigSchema: z.ZodPipe<z.ZodObject<{
|
|
|
511
516
|
*/
|
|
512
517
|
interface ServTransportConfig {
|
|
513
518
|
/** 受管服务端密钥环,仅运行时从私有 Secret 注入。 */
|
|
519
|
+
/** 双向业务明文 UTF-8 字节上限;默认 1 MiB,整数范围 1 KiB~64 MiB。 */
|
|
520
|
+
readonly maxPlaintextBytes?: number;
|
|
514
521
|
readonly serverKeyRing: TransportServerKeyRing;
|
|
515
522
|
/**
|
|
516
523
|
* crypto 服务实例。serv 通过 `crypto.transport.createServer()` 创建
|
package/dist/index.js
CHANGED
|
@@ -10,12 +10,12 @@ import { Hono } from 'hono';
|
|
|
10
10
|
import { WebSocketServer } from 'ws';
|
|
11
11
|
import { Buffer } from 'buffer';
|
|
12
12
|
import { BlockList, isIP } from 'net';
|
|
13
|
+
import { TRANSPORT_PLAINTEXT_RANGE, TRANSPORT_BODY_LIMITS, TRANSPORT_PROTOCOL, authenticateTransportRequest, TransportTimeError, createTransportErrorResponse, TransportBodyTooLargeError, readTransportBody, isValidSM2PublicKey } from '@h-ai/crypto';
|
|
13
14
|
import { z } from 'zod';
|
|
14
15
|
import { getCookie } from 'hono/cookie';
|
|
15
16
|
import { readFile } from 'fs/promises';
|
|
16
17
|
import { OpenAPIGenerator } from '@orpc/openapi';
|
|
17
18
|
import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4';
|
|
18
|
-
import { TRANSPORT_PROTOCOL, authenticateTransportRequest, readTransportBody, TRANSPORT_BODY_LIMITS, isValidSM2PublicKey } from '@h-ai/crypto';
|
|
19
19
|
|
|
20
20
|
// src/adapters/serv-adapter-fetch.ts
|
|
21
21
|
function toFetch(app) {
|
|
@@ -724,6 +724,7 @@ var RpcHttpConfigInputSchema = z.union([
|
|
|
724
724
|
var TransportRuntimeConfigInputSchema = z.union([
|
|
725
725
|
z.literal(false),
|
|
726
726
|
z.object({
|
|
727
|
+
maxPlaintextBytes: z.number().int().min(TRANSPORT_PLAINTEXT_RANGE.min).max(TRANSPORT_PLAINTEXT_RANGE.max).optional().describe("\u53CC\u5411\u4E1A\u52A1\u660E\u6587 UTF-8 \u5B57\u8282\u4E0A\u9650\uFF1B\u9ED8\u8BA4 1 MiB\uFF0C\u5BC6\u6587\u4E0E\u4EE3\u7406\u9884\u7B97\u81EA\u52A8\u63A8\u5BFC").meta({ default: TRANSPORT_BODY_LIMITS.plaintextBytes }),
|
|
727
728
|
keyExchangePath: AbsolutePathSchema.default("/_hai/key-exchange"),
|
|
728
729
|
excludePaths: z.array(AbsolutePathSchema).default([])
|
|
729
730
|
})
|
|
@@ -786,6 +787,9 @@ function resolveServTransportRuntimeConfig(input = false) {
|
|
|
786
787
|
var HEADER_REQUEST_ID = "x-request-id";
|
|
787
788
|
var HEADER_AUTHORIZATION = "authorization";
|
|
788
789
|
var HEADER_USER_AGENT = "user-agent";
|
|
790
|
+
function resolveRequestId(value) {
|
|
791
|
+
return value && /^[\w.:-]{1,128}$/.test(value) ? value : core.id.uuid();
|
|
792
|
+
}
|
|
789
793
|
function extractBearerToken(value) {
|
|
790
794
|
if (!value)
|
|
791
795
|
return void 0;
|
|
@@ -796,7 +800,7 @@ function extractBearerToken(value) {
|
|
|
796
800
|
}
|
|
797
801
|
function parseRequestContext(input) {
|
|
798
802
|
const headers = input.request.headers;
|
|
799
|
-
const requestId =
|
|
803
|
+
const requestId = core.context.get().requestId ?? resolveRequestId(headers.get(HEADER_REQUEST_ID));
|
|
800
804
|
const ip = normalizeClientIp(Object.hasOwn(input, "ip") ? input.ip : input.remoteAddress);
|
|
801
805
|
const locale = resolveRequestLocale(headers);
|
|
802
806
|
const accessToken = extractBearerToken(headers.get(HEADER_AUTHORIZATION));
|
|
@@ -1068,12 +1072,17 @@ function createTransportMiddleware(manager, keyExchangePath, excludePaths = [])
|
|
|
1068
1072
|
let requestContext;
|
|
1069
1073
|
try {
|
|
1070
1074
|
const verified = await authenticateTransportRequest(manager, c.req.raw);
|
|
1071
|
-
if (!verified.success)
|
|
1075
|
+
if (!verified.success) {
|
|
1076
|
+
if (verified.error.cause instanceof TransportTimeError && verified.error.cause.context)
|
|
1077
|
+
return createTransportErrorResponse(verified.error.cause, { manager, context: verified.error.cause.context });
|
|
1072
1078
|
return jsonError(servM("serv_transportDecryptFailed"), 400);
|
|
1079
|
+
}
|
|
1073
1080
|
requestContext = verified.data.context;
|
|
1074
1081
|
if (c.req.method !== "GET" && c.req.method !== "HEAD")
|
|
1075
1082
|
replaceRequestBody(c, verified.data.plaintext);
|
|
1076
1083
|
} catch (error) {
|
|
1084
|
+
if (error instanceof TransportBodyTooLargeError)
|
|
1085
|
+
return createTransportErrorResponse(error);
|
|
1077
1086
|
return jsonError(servM("serv_transportInvalidPayload"), error instanceof RangeError ? 413 : 400);
|
|
1078
1087
|
}
|
|
1079
1088
|
await next();
|
|
@@ -1098,10 +1107,15 @@ function createTransportMiddleware(manager, keyExchangePath, excludePaths = [])
|
|
|
1098
1107
|
let bodyText;
|
|
1099
1108
|
try {
|
|
1100
1109
|
bodyText = bodyless ? "" : await readTransportBody(response.body, {
|
|
1101
|
-
maxBytes:
|
|
1110
|
+
maxBytes: manager.bodyLimits.plaintextBytes,
|
|
1111
|
+
direction: "response",
|
|
1102
1112
|
signal: c.req.raw.signal
|
|
1103
1113
|
});
|
|
1104
1114
|
} catch (cause) {
|
|
1115
|
+
if (cause instanceof TransportBodyTooLargeError) {
|
|
1116
|
+
c.res = await createTransportErrorResponse(cause, { manager, context: requestContext });
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1105
1119
|
logger2.warn("Failed to read response body for encryption", { error: cause });
|
|
1106
1120
|
c.res = jsonError(servM("serv_transportEncryptFailed"), 500);
|
|
1107
1121
|
return;
|
|
@@ -1145,7 +1159,7 @@ async function handleKeyExchange(request, manager) {
|
|
|
1145
1159
|
if (new TextEncoder().encode(serverPublicKey).byteLength > TRANSPORT_BODY_LIMITS.publicKeyBytes)
|
|
1146
1160
|
return jsonError(servM("serv_transportKeyExchangeFailed"), 500);
|
|
1147
1161
|
const clientId = await manager.registerClientKey(body.clientPublicKey);
|
|
1148
|
-
return new Response(JSON.stringify({ serverKeyId: manager.getServerKeyId(), serverPublicKey, clientId }), {
|
|
1162
|
+
return new Response(JSON.stringify({ serverKeyId: manager.getServerKeyId(), serverPublicKey, clientId, maxPlaintextBytes: manager.bodyLimits.plaintextBytes }), {
|
|
1149
1163
|
status: 200,
|
|
1150
1164
|
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
1151
1165
|
});
|
|
@@ -1198,7 +1212,11 @@ var audioWsServers = /* @__PURE__ */ new WeakMap();
|
|
|
1198
1212
|
function createApp(options) {
|
|
1199
1213
|
const http = resolveServHttpConfig(options.http);
|
|
1200
1214
|
const app = new Hono();
|
|
1201
|
-
app.use("*", (c, next) =>
|
|
1215
|
+
app.use("*", async (c, next) => {
|
|
1216
|
+
const requestId = resolveRequestId(c.req.header("x-request-id") ?? null);
|
|
1217
|
+
await core.context.run({ requestId, userId: void 0, scopeId: void 0, jobId: void 0 }, () => core.i18n.runWithLocale(resolveRequestLocale(c.req.raw.headers), next));
|
|
1218
|
+
c.header("x-request-id", requestId);
|
|
1219
|
+
});
|
|
1202
1220
|
app.notFound((c) => c.json(buildHaiErrorBody(
|
|
1203
1221
|
HaiCommonError.NOT_FOUND,
|
|
1204
1222
|
core.i18n.coreM("core_errorNotFound", { locale: resolveRequestLocale(c.req.raw.headers) })
|
|
@@ -1219,7 +1237,8 @@ function createApp(options) {
|
|
|
1219
1237
|
if (options.transport) {
|
|
1220
1238
|
const mgr = options.transport.crypto.transport.createServer({
|
|
1221
1239
|
serverKeyRing: options.transport.serverKeyRing,
|
|
1222
|
-
keyStore: options.transport.keyStore
|
|
1240
|
+
keyStore: options.transport.keyStore,
|
|
1241
|
+
maxPlaintextBytes: options.transport.maxPlaintextBytes
|
|
1223
1242
|
});
|
|
1224
1243
|
if (!mgr.success) {
|
|
1225
1244
|
throw core.error.buildHaiErrorInst(
|
|
@@ -1301,7 +1320,7 @@ function mountRPCRoutes(app, procedures, rpcConfig, createContext) {
|
|
|
1301
1320
|
}
|
|
1302
1321
|
async function handleORPC(c, next, prefix, handler, createContext) {
|
|
1303
1322
|
const context = await createContext({ request: c.req.raw, remoteAddress: readRemoteAddress(c.env) });
|
|
1304
|
-
const { matched, response } = await handler.handle(c.req.raw, { prefix, context });
|
|
1323
|
+
const { matched, response } = await core.context.run({ requestId: context.requestId, userId: context.session?.userId, scopeId: context.scopeId }, () => handler.handle(c.req.raw, { prefix, context }));
|
|
1305
1324
|
if (!matched) {
|
|
1306
1325
|
await next();
|
|
1307
1326
|
return;
|