@h-ai/kit 0.1.0-alpha.36 → 0.1.0-alpha.38

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.md CHANGED
@@ -242,6 +242,8 @@ export const appKitConfig = resolveKitConfig(parse(rawKitConfig) ?? {})
242
242
  | `a2a` | `HandleA2AOperations \| HandleA2AConfig` | A2A 协议集成(Agent Card + JSON-RPC) |
243
243
  | `onError` | `function` | 自定义错误处理 |
244
244
 
245
+ 配置 `crypto.encryptedCookies` 时必须同时提供 `crypto.cookieEncryptionKey`,或设置 `HAI_KIT_COOKIE_KEY`。缺少密钥会在 `createHandle()` 时立即报错;受保护 Cookie 的明文、损坏密文或解密失败都按不存在处理,加密失败也不会回退写入明文。
246
+
245
247
  ## 导出路径
246
248
 
247
249
  - `@h-ai/kit`:主入口,提供 `kit` 命名空间与类型。
package/dist/browser.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { c as createKitClient, i as installBrowserTransport, a as installBrowserTransportFetch, s as setBrowserToken, b as clearBrowserToken, d as createTokenStore } from './index-Du-3zATp.js';
2
2
  export { C as ClientTransportConfig, K as KitClient, e as KitClientConfig, f as KitConfig, g as KitConfigInput, h as KitConfigSchema, j as KitTransportConfig, k as KitTransportConfigInput, l as createSvelteKitNavAdapter, r as resolveKitConfig, m as resolveKitTransportConfig } from './index-Du-3zATp.js';
3
3
  import { d as defineCrud, s as setAllModulesLocale } from './kit-i18n-CgpNTh9G.js';
4
- export { A as ApiResponse, a as AuthOperations, b as AuthOperationsProvider, C as CorsConfig, F as FormError, c as FormValidationResult, G as GuardConfig, d as GuardResult, H as HaiRequestEvent, e as HandleA2AConfig, f as HandleA2AOperations, g as HandleAuthConfig, h as HandleConfig, i as HookCryptoConfig, M as Middleware, j as MiddlewareContext, R as RateLimitConfig, k as RouteGuard, S as SessionData, l as SessionLike, T as TransportEncryptionOptions } from './kit-types-BmWNlWpa.js';
4
+ export { A as ApiResponse, a as AuthOperations, b as AuthOperationsProvider, C as CorsConfig, F as FormError, c as FormValidationResult, G as GuardConfig, d as GuardResult, H as HaiRequestEvent, e as HandleA2AConfig, f as HandleA2AOperations, g as HandleAuthConfig, h as HandleConfig, i as HookCryptoConfig, M as Middleware, j as MiddlewareContext, R as RateLimitConfig, k as RouteGuard, S as SessionData, l as SessionLike, T as TransportEncryptionOptions } from './kit-types-BIkoLpfq.js';
5
5
  import '@h-ai/crypto';
6
6
  import '@h-ai/core';
7
7
  import '@h-ai/iam';
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import { c as createKitClient, i as installBrowserTransport, a as installBrowser
2
2
  export { C as ClientTransportConfig, K as KitClient, e as KitClientConfig, f as KitConfig, g as KitConfigInput, h as KitConfigSchema, j as KitTransportConfig, k as KitTransportConfigInput, l as createSvelteKitNavAdapter, r as resolveKitConfig, m as resolveKitTransportConfig } from './index-Du-3zATp.js';
3
3
  import { d as defineCrud, s as setAllModulesLocale } from './kit-i18n-CgpNTh9G.js';
4
4
  export { C as CrudApiDef, a as CrudFieldDef, b as CrudFieldOption, c as CrudFieldOptions, e as CrudFieldType, f as CrudFieldValidation, g as CrudFilterParams, h as CrudOperations, i as CrudPaginatedResult, j as CrudPaginationParams, k as CrudResourceDef, l as CrudTableColumn, m as CrudText, r as resolveOptions, n as resolveText } from './kit-i18n-CgpNTh9G.js';
5
- import { S as SessionData, k as RouteGuard, l as SessionLike, h as HandleConfig, C as CorsConfig, M as Middleware } from './kit-types-BmWNlWpa.js';
6
- export { A as ApiResponse, a as AuthOperations, b as AuthOperationsProvider, F as FormError, c as FormValidationResult, G as GuardConfig, d as GuardResult, H as HaiRequestEvent, e as HandleA2AConfig, f as HandleA2AOperations, g as HandleAuthConfig, i as HookCryptoConfig, m as MemoryRateLimitStore, j as MiddlewareContext, R as RateLimitConfig, n as RateLimitEntry, o as RateLimitStore, T as TransportEncryptionOptions, r as rateLimitMiddleware } from './kit-types-BmWNlWpa.js';
5
+ import { S as SessionData, k as RouteGuard, l as SessionLike, h as HandleConfig, C as CorsConfig, M as Middleware } from './kit-types-BIkoLpfq.js';
6
+ export { A as ApiResponse, a as AuthOperations, b as AuthOperationsProvider, F as FormError, c as FormValidationResult, G as GuardConfig, d as GuardResult, H as HaiRequestEvent, e as HandleA2AConfig, f as HandleA2AOperations, g as HandleAuthConfig, i as HookCryptoConfig, m as MemoryRateLimitStore, j as MiddlewareContext, R as RateLimitConfig, n as RateLimitEntry, o as RateLimitStore, T as TransportEncryptionOptions, r as rateLimitMiddleware } from './kit-types-BIkoLpfq.js';
7
7
  import { RequestEvent, Cookies, Handle, RequestHandler } from '@sveltejs/kit';
8
8
  import { CryptoFunctions } from '@h-ai/crypto';
9
9
  export { EncryptedPayload, TransportEncryptionManager, TransportKeyPair } from '@h-ai/crypto';
@@ -357,8 +357,8 @@ interface CookieProxyConfig {
357
357
  * 创建加密 Cookie 代理
358
358
  *
359
359
  * 返回一个 Proxy 包装的 Cookies 对象:
360
- * - `get(name)` —— 若 name 在加密列表中,自动解密后返回明文
361
- * - `set(name, value, opts)` —— 若 name 在加密列表中,自动加密后存储
360
+ * - `get(name)` —— 若 name 在加密列表中,自动解密后返回明文;格式或解密失败时返回 `undefined`
361
+ * - `set(name, value, opts)` —— 若 name 在加密列表中,自动加密后存储;加密失败时拒绝写入
362
362
  * - `delete(name, opts)` —— 透传,无需解密
363
363
  * - 其他方法原样透传
364
364
  *
package/dist/index.js CHANGED
@@ -257,40 +257,40 @@ function createEncryptedCookieProxy(cookies, config) {
257
257
  const raw = target.get(name, opts);
258
258
  if (!raw || !names.has(name))
259
259
  return raw;
260
- if (!raw.startsWith(ENCRYPTED_PREFIX))
261
- return raw;
260
+ if (!raw.startsWith(ENCRYPTED_PREFIX)) {
261
+ logger.warn("Encrypted cookie has invalid format", { name });
262
+ return void 0;
263
+ }
262
264
  try {
263
265
  const ciphertext = raw.slice(ENCRYPTED_PREFIX.length);
264
266
  const separatorIndex = ciphertext.indexOf(":");
265
- if (separatorIndex === -1)
266
- return raw;
267
+ if (separatorIndex === -1) {
268
+ logger.warn("Encrypted cookie has invalid format", { name });
269
+ return void 0;
270
+ }
267
271
  const iv = ciphertext.slice(0, separatorIndex);
268
272
  const encrypted = ciphertext.slice(separatorIndex + 1);
269
273
  const result = symmetric.decryptWithIV(encrypted, encryptionKey, iv);
270
274
  if (!result.success || typeof result.data !== "string") {
271
- logger.warn("Cookie decryption failed, returning raw value", { name });
272
- return raw;
275
+ logger.warn("Cookie decryption failed", { name });
276
+ return void 0;
273
277
  }
274
278
  return result.data;
275
279
  } catch {
276
- logger.warn("Cookie decryption error, returning raw value", { name });
277
- return raw;
280
+ logger.warn("Cookie decryption error", { name });
281
+ return void 0;
278
282
  }
279
283
  };
280
284
  }
281
285
  if (prop === "set") {
282
286
  return (name, value, opts) => {
283
287
  if (names.has(name)) {
284
- try {
285
- const result = symmetric.encryptWithIV(value, encryptionKey);
286
- if (result.success && result.data) {
287
- value = `${ENCRYPTED_PREFIX}${result.data.iv}:${result.data.ciphertext}`;
288
- } else {
289
- logger.warn("Cookie encryption failed, storing plaintext", { name });
290
- }
291
- } catch {
292
- logger.warn("Cookie encryption error, storing plaintext", { name });
288
+ const result = symmetric.encryptWithIV(value, encryptionKey);
289
+ if (!result.success || !result.data) {
290
+ logger.error("Cookie encryption failed", { name });
291
+ throw new Error("Cookie encryption failed");
293
292
  }
293
+ value = `${ENCRYPTED_PREFIX}${result.data.iv}:${result.data.ciphertext}`;
294
294
  }
295
295
  return target.set(name, value, opts);
296
296
  };
@@ -521,8 +521,7 @@ function buildCookieProxyConfig(cryptoConfig) {
521
521
  return null;
522
522
  const key = cryptoConfig.cookieEncryptionKey ?? (typeof process !== "undefined" ? process.env?.HAI_KIT_COOKIE_KEY : void 0);
523
523
  if (!key) {
524
- core.logger.warn("Cookie encryption configured but no key provided (set crypto.cookieEncryptionKey or HAI_KIT_COOKIE_KEY env)");
525
- return null;
524
+ throw new Error("Cookie encryption requires crypto.cookieEncryptionKey or HAI_KIT_COOKIE_KEY");
526
525
  }
527
526
  return {
528
527
  names: new Set(cryptoConfig.encryptedCookies),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/guards/kit-permission.ts","../src/kit-utils.ts","../src/middleware/kit-logging.ts","../src/middleware/kit-ratelimit.ts","../src/hooks/kit-cookie-proxy.ts","../src/hooks/kit-handle.ts","../src/kit-response.ts","../src/kit-handler.ts","../src/kit-validation.ts","../src/kit-main.ts"],"names":["core","response","error","event","zod"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @h-ai/kit — 权限守卫\n *\n * 验证用户是否具有指定权限。\n * @module kit-permission\n */\n\nimport type { GuardResult, RouteGuard, SessionLike } from '../kit-types.js'\nimport { kitM } from '../kit-i18n.js'\n\n/**\n * 权限守卫配置\n */\nexport interface PermissionGuardConfig {\n /** 需要的权限列表(默认 OR 逻辑,满足任一即通过) */\n permissions: string[]\n /** 为 `true` 时要求用户拥有 **全部** 权限(AND 逻辑) */\n requireAll?: boolean\n /** 无权限时重定向 URL(默认 `'/403'`) */\n forbiddenUrl?: string\n /** 为 `true` 时返回 JSON 403 而非重定向 */\n apiMode?: boolean\n}\n\n/**\n * 创建权限守卫\n *\n * 检查用户 `session.permissions` 是否满足配置中的权限要求。\n * 支持通配符匹配:`admin:*` 可匹配 `admin:read`、`admin:write` 等。\n * 未认证时返回 401;权限不匹配时根据 `apiMode` 返回 JSON 403 或重定向。\n *\n * @param config - 权限守卫配置\n * @returns RouteGuard 实例\n *\n * @example\n * ```ts\n * guards: [\n * { guard: kit.guard.permission({ permissions: ['user:read', 'user:write'], requireAll: true }), paths: ['/api/users/*'] },\n * ]\n * ```\n */\nexport function permissionGuard(config: PermissionGuardConfig): RouteGuard {\n const { permissions, requireAll = false, forbiddenUrl = '/403', apiMode = false } = config\n\n return (_event, session): GuardResult => {\n if (!session) {\n return {\n allowed: false,\n message: kitM('kit_authRequired'),\n status: 401,\n }\n }\n\n const userPermissions = session.permissions ?? []\n\n // 支持通配符权限,如 admin:* 匹配 admin:read, admin:write 等\n const hasPermission = requireAll\n ? permissions.every(perm => matchPermission(perm, userPermissions))\n : permissions.some(perm => matchPermission(perm, userPermissions))\n\n if (!hasPermission) {\n if (apiMode) {\n return {\n allowed: false,\n message: kitM('kit_requiredPermissions', { params: { permissions: permissions.join(', ') } }),\n status: 403,\n }\n }\n\n return {\n allowed: false,\n redirect: forbiddenUrl,\n }\n }\n\n return { allowed: true }\n }\n}\n\n/**\n * 匹配权限\n *\n * 支持通配符:\n * - `admin:*` 匹配 `admin:read`、`admin:write` 等\n * - `*` 匹配所有权限\n *\n * @param required - 需要的权限码\n * @param userPermissions - 用户已有的权限列表\n * @returns 是否匹配\n */\nexport function matchPermission(required: string, userPermissions: string[]): boolean {\n for (const userPerm of userPermissions) {\n // 完全匹配\n if (userPerm === required) {\n return true\n }\n\n // 用户有超级权限\n if (userPerm === '*') {\n return true\n }\n\n // 通配符匹配\n if (userPerm.endsWith(':*')) {\n const prefix = userPerm.slice(0, -1) // 移除 *\n if (required.startsWith(prefix)) {\n return true\n }\n }\n }\n\n return false\n}\n\n/**\n * 检查会话是否具有指定权限(布尔判断)\n *\n * 适用于条件分支场景(如菜单过滤、按钮显示等)。\n *\n * @param session - 当前会话数据,null/undefined 视为无权限\n * @param permission - 需要的权限码,如 `user:read`\n * @returns 是否拥有权限\n *\n * @example\n * ```ts\n * if (kit.guard.check(locals.session, 'user:read')) {\n * // 有权限\n * }\n * ```\n */\nexport function hasPermission(\n session: SessionLike | null | undefined,\n permission: string,\n): boolean {\n if (!session)\n return false\n return matchPermission(permission, session.permissions ?? [])\n}\n\n/**\n * 断言会话具有指定权限,不满足时返回 403 Response\n *\n * 适用于 SvelteKit API Handler 内部,不满足权限时直接返回 JSON 错误响应。\n * 调用者需检查返回值:若有返回值则表示权限不足,应直接 return。\n *\n * @param session - 当前会话数据,null/undefined 视为未认证\n * @param permission - 需要的权限码,如 `user:create`\n * @returns 权限不足时返回 Response;有权限时返回 undefined\n *\n * @example\n * ```ts\n * export const POST: RequestHandler = async ({ locals }) => {\n * const denied = kit.guard.assertPermission(locals.session, 'user:create')\n * if (denied) return denied\n * // ... 正常逻辑\n * }\n * ```\n */\nexport function assertPermission(\n session: SessionLike | null | undefined,\n permission: string,\n): Response | undefined {\n if (!session) {\n return new Response(\n JSON.stringify({ success: false, error: kitM('kit_unauthorized') }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n if (!matchPermission(permission, session.permissions ?? [])) {\n return new Response(\n JSON.stringify({ success: false, error: kitM('kit_forbidden', { params: { permission } }) }),\n { status: 403, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n return undefined\n}\n\n/**\n * 要求会话具有指定权限,不满足时 throw Response\n *\n * 利用 SvelteKit 控制流机制:throw 的 Response 对象会被框架捕获并直接作为响应返回。\n * 搭配 `kit.handler()` 使用时,无需手动检查返回值。\n *\n * @param session - 当前会话数据,null/undefined 视为未认证\n * @param permission - 需要的权限码,如 `user:create`\n * @throws Response - 未认证 401 / 无权限 403\n *\n * @example\n * ```ts\n * export const GET = kit.handler(async ({ locals }) => {\n * kit.guard.require(locals.session, 'user:read')\n * // 执行到这里说明权限已通过\n * return kit.response.ok(data)\n * })\n * ```\n */\nexport function requirePermission(\n session: SessionLike | null | undefined,\n permission: string,\n): void {\n const denied = assertPermission(session, permission)\n if (denied) {\n throw denied\n }\n}\n\n/**\n * 权限守卫高阶函数包装器\n *\n * 将权限检查从业务逻辑中提取到装饰层,handler 内部无需关心权限。\n * 未认证返回 401、无权限返回 403(均通过 SvelteKit throw 控制流抛出)。\n *\n * 适用于 page load、API handler 等所有 SvelteKit server 函数。\n *\n * @param permission - 需要的权限码,如 `'user:read'`\n * @param handler - 原始处理函数\n * @returns 包装后的处理函数(签名不变)\n *\n * @example\n * ```ts\n * // +page.server.ts\n * export const load = kit.guard.withPermission('user:read', async ({ locals }) => {\n * const result = await iam.user.listUsers()\n * return { users: result.success ? result.data.items : [] }\n * })\n *\n * // +server.ts (API handler)\n * export const GET = kit.handler(kit.guard.withPermission('user:list', async ({ locals }) => {\n * const result = await iam.user.listUsers()\n * return kit.response.ok(result.data)\n * }))\n * ```\n */\nexport function withPermission<TEvent extends { locals: Record<string, unknown> }, TReturn>(\n permission: string,\n handler: (event: TEvent) => Promise<TReturn>,\n): (event: TEvent) => Promise<TReturn> {\n return async (event: TEvent) => {\n requirePermission(event.locals.session as SessionLike | undefined, permission)\n return handler(event)\n }\n}\n","/**\n * @h-ai/kit — 内部工具函数\n *\n * 提取 Handler 与 Handle 共享的 SvelteKit 控制流检测逻辑。\n * @module kit-utils\n */\n\n/**\n * 检测是否为 Response 对象(兼容跨模块 instanceof 失效场景)\n *\n * 在 Vite 开发环境下,不同模块可能引用不同的 `Response` 构造器,\n * 导致 `instanceof Response` 返回 false。通过特征检测兜底辨识。\n *\n * @param value - 待检测值\n * @returns 是否为 Response(或 Response-like 对象)\n */\nexport function isResponseLike(value: unknown): value is Response {\n if (value instanceof Response)\n return true\n if (\n typeof value === 'object'\n && value !== null\n && 'status' in value\n && 'headers' in value\n && typeof (value as Response).text === 'function'\n && typeof (value as Response).json === 'function'\n ) {\n return true\n }\n return false\n}\n\n/**\n * 检测是否为 SvelteKit 控制流对象(redirect / error)\n *\n * SvelteKit 的 `redirect()` 和 `error()` 会抛出带 `status` 属性的特殊对象,\n * 框架在上层捕获后做控制流处理。此类对象必须继续抛出,不可吞掉。\n *\n * redirect 特征:`{ status, location }` 且 status 为 number\n * error 特征:`{ status, body }` 且 status 为 number\n *\n * @param value - 被捕获的异常\n * @returns 是否为 SvelteKit 控制流\n */\nexport function isSvelteKitControlFlow(value: unknown): boolean {\n // Response 对象不是控制流\n if (isResponseLike(value))\n return false\n if (typeof value === 'object' && value !== null && 'status' in value) {\n const status = (value as { status: unknown }).status\n return typeof status === 'number'\n }\n return false\n}\n","/**\n * @h-ai/kit — 日志中间件\n *\n * HTTP 请求日志中间件,记录请求/响应摘要(方法、路径、状态码、耗时),\n * 并自动脱敏敏感字段(password / token / secret 等)。\n * @module kit-logging\n */\n\nimport type { Middleware } from '../kit-types.js'\nimport { core } from '@h-ai/core'\n\n/**\n * 日志中间件配置\n */\nexport interface LoggingMiddlewareConfig {\n /** 为 `true` 时记录非 GET 请求体(自动脱敏) */\n logBody?: boolean\n /** 为 `true` 时记录响应头 */\n logResponse?: boolean\n /** 指定需要脱敏的字段名(默认 `['password', 'token', 'secret']`) */\n redactFields?: string[]\n}\n\n/**\n * 创建日志中间件\n *\n * 以 `core.logger.trace` 级别记录请求进出信息,包含:\n * - 请求:method / path / query / userAgent / ip\n * - 响应:status / duration\n *\n * 敏感字段会被自动替换为 `[REDACTED]`。\n *\n * @param config - 日志配置\n * @returns Middleware 实例\n *\n * @example\n * ```ts\n * middleware: [\n * kit.middleware.logging({ logBody: true, redactFields: ['password', 'creditCard'] }),\n * ]\n * ```\n */\nexport function loggingMiddleware(config: LoggingMiddlewareConfig = {}): Middleware {\n const { logBody = false, logResponse = false, redactFields = ['password', 'token', 'secret', 'authorization', 'apikey', 'api_key', 'creditcard', 'credit_card'] } = config\n\n return async (context, next) => {\n const { event, requestId } = context\n const startTime = Date.now()\n\n // 安全获取客户端 IP,处理开发环境下可能的错误\n let clientIp = 'unknown'\n try {\n clientIp = event.getClientAddress?.() ?? 'unknown'\n }\n catch {\n // 开发环境下 getClientAddress 可能抛出错误\n }\n\n const logData: Record<string, unknown> = {\n requestId,\n method: event.request.method,\n path: event.url.pathname,\n query: Object.fromEntries(event.url.searchParams),\n userAgent: event.request.headers.get('user-agent'),\n ip: clientIp,\n }\n\n if (logBody && event.request.method !== 'GET') {\n try {\n const clonedRequest = event.request.clone()\n const body = await clonedRequest.json()\n logData.body = redactObject(body, redactFields)\n }\n catch {\n // 忽略非 JSON 请求体\n }\n }\n\n core.logger.trace('Incoming request', { ...logData })\n\n const response = await next()\n\n const duration = Date.now() - startTime\n\n const responseLogData: Record<string, unknown> = {\n requestId,\n status: response.status,\n duration,\n }\n\n if (logResponse) {\n responseLogData.headers = Object.fromEntries(response.headers)\n }\n\n core.logger.trace('Request completed', { ...responseLogData })\n\n return response\n }\n}\n\n/**\n * 递归屏蔽对象中的敏感字段\n *\n * 匹配规则:字段名转小写后与 `fields` 列表比较。\n *\n * @param obj - 待处理对象\n * @param fields - 需要屏蔽的字段名列表(全小写)\n * @returns 屏蔽后的副本\n */\nfunction redactObject(obj: unknown, fields: string[]): unknown {\n return core.sanitize.sanitizeSensitiveFields(obj, { matcher: fields })\n}\n","/**\n * @h-ai/kit — 速率限制中间件\n *\n * 基于滑动窗口的请求速率限制中间件。\n * 内置内存存储(`MemoryRateLimitStore`),并支持通过 `RateLimitStore` 接入\n * Redis 等外部存储后端。\n * @module kit-ratelimit\n */\n\nimport type { Middleware, RateLimitConfig } from '../kit-types.js'\nimport { core } from '@h-ai/core'\nimport { kitM } from '../kit-i18n.js'\n\n/**\n * 速率限制存储条目\n */\nexport interface RateLimitEntry {\n /** 当前窗口内的请求次数 */\n count: number\n /** 窗口重置时间戳(ms) */\n resetAt: number\n}\n\n/**\n * 速率限制存储接口\n *\n * 内置 `MemoryRateLimitStore` 适合单进程开发;\n * 多实例部署需传入基于 Redis / @h-ai/cache 的分布式实现。\n *\n * @example\n * ```ts\n * // 自定义 Redis 存储\n * const redisStore: RateLimitStore = {\n * async get(key) { ... },\n * async set(key, entry) { ... },\n * async delete(key) { ... },\n * }\n * kit.middleware.rateLimit({ windowMs: 60_000, maxRequests: 100, store: redisStore })\n * ```\n */\nexport interface RateLimitStore {\n /** 获取指定 key 的限流条目 */\n get: (key: string) => Promise<RateLimitEntry | undefined> | RateLimitEntry | undefined\n /** 设置限流条目 */\n set: (key: string, entry: RateLimitEntry) => Promise<void> | void\n /** 删除指定 key 的限流条目 */\n delete: (key: string) => Promise<void> | void\n /**\n * 原子自增并返回当前计数和重置时间\n *\n * 实现时必须保证 get→increment→set 操作的原子性,\n * 防止并发请求在窗口切换时产生竞态绕过限流。\n * 若未实现,则退回非原子 get+set 流程。\n *\n * @param key - 限流键\n * @param windowMs - 窗口时长(ms)\n * @returns 自增后的计数和窗口重置时间\n */\n increment?: (key: string, windowMs: number) => Promise<RateLimitEntry> | RateLimitEntry\n}\n\n/**\n * 内存速率限制存储\n *\n * 基于 Map 实现,适合单进程/开发环境。\n * 多实例部署时限流上限会乘以实例数,建议使用分布式 Store。\n */\nexport class MemoryRateLimitStore implements RateLimitStore {\n private store = new Map<string, RateLimitEntry>()\n private cleanupTimer: ReturnType<typeof setInterval> | null = null\n\n /**\n * 启动定期清理过期条目\n *\n * @param intervalMs - 清理间隔(毫秒)\n */\n startCleanup(intervalMs: number): void {\n if (this.cleanupTimer)\n return\n this.cleanupTimer = setInterval(() => {\n const now = Date.now()\n for (const [key, entry] of this.store) {\n if (entry.resetAt < now) {\n this.store.delete(key)\n }\n }\n }, intervalMs)\n // 允许进程正常退出\n if (this.cleanupTimer && typeof this.cleanupTimer === 'object' && 'unref' in this.cleanupTimer) {\n this.cleanupTimer.unref()\n }\n }\n\n /**\n * 停止定期清理并释放定时器资源\n *\n * 调用后可再次 startCleanup 重启。进程退出 / 热重载 / 测试拆装场景必须调用以\n * 避免资源泄漏。\n */\n stopCleanup(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer)\n this.cleanupTimer = null\n }\n }\n\n get(key: string): RateLimitEntry | undefined {\n return this.store.get(key)\n }\n\n set(key: string, entry: RateLimitEntry): void {\n this.store.set(key, entry)\n }\n\n delete(key: string): void {\n this.store.delete(key)\n }\n\n /**\n * 原子自增(内存实现为同步操作,天然原子)\n *\n * @param key - 限流键\n * @param windowMs - 窗口时长\n * @returns 自增后的条目\n */\n increment(key: string, windowMs: number): RateLimitEntry {\n const now = Date.now()\n let entry = this.store.get(key)\n if (!entry || entry.resetAt < now) {\n entry = { count: 1, resetAt: now + windowMs }\n }\n else {\n entry.count++\n }\n this.store.set(key, entry)\n return entry\n }\n}\n\n/**\n * 创建速率限制中间件\n *\n * 基于可插拔存储的滑动窗口限流:\n * - 超限时返回 429,并在响应头中告知重置时间\n * - 正常响应附带 `X-RateLimit-*` 头\n * - 默认使用内存存储(单进程),可传入 `store` 实现分布式限流\n *\n * @param config - 限流配置\n * @returns Middleware 实例\n *\n * @example\n * ```ts\n * middleware: [\n * kit.middleware.rateLimit({ windowMs: 60_000, maxRequests: 100 }),\n * ]\n * ```\n */\nexport function rateLimitMiddleware(config: RateLimitConfig): Middleware {\n const {\n windowMs,\n maxRequests,\n keyGenerator = (event) => {\n try {\n return event.getClientAddress?.() ?? 'unknown'\n }\n catch {\n // 开发环境下 getClientAddress 可能抛出错误\n return 'unknown'\n }\n },\n onLimitReached,\n } = config\n\n // 构建存储:支持外部注入,默认内存\n const store: RateLimitStore = config.store ?? (() => {\n const memStore = new MemoryRateLimitStore()\n memStore.startCleanup(windowMs)\n return memStore\n })()\n\n return async (context, next) => {\n const { event, requestId } = context\n const key = keyGenerator(event)\n const now = Date.now()\n\n // 优先使用原子 increment,防止并发竞态\n let entry: RateLimitEntry\n if (store.increment) {\n entry = await store.increment(key, windowMs)\n }\n else {\n // 退回非原子流程(仅用于未实现 increment 的存储后端)\n const existing = await store.get(key)\n if (!existing || existing.resetAt < now) {\n entry = { count: 1, resetAt: now + windowMs }\n }\n else {\n entry = { ...existing, count: existing.count + 1 }\n }\n await store.set(key, entry)\n }\n\n // 设置速率限制头\n const remaining = Math.max(0, maxRequests - entry.count)\n const resetTime = Math.ceil(entry.resetAt / 1000)\n\n if (entry.count > maxRequests) {\n core.logger.warn('Rate limit exceeded', { key, requestId })\n\n if (onLimitReached) {\n return onLimitReached(event)\n }\n\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'RATE_LIMIT_EXCEEDED',\n message: kitM('kit_rateLimitExceeded'),\n },\n requestId,\n }),\n {\n status: 429,\n headers: {\n 'Content-Type': 'application/json',\n 'X-RateLimit-Limit': String(maxRequests),\n 'X-RateLimit-Remaining': '0',\n 'X-RateLimit-Reset': String(resetTime),\n 'Retry-After': String(Math.ceil((entry.resetAt - now) / 1000)),\n },\n },\n )\n }\n\n const response = await next()\n\n // 添加速率限制头到响应\n response.headers.set('X-RateLimit-Limit', String(maxRequests))\n response.headers.set('X-RateLimit-Remaining', String(remaining))\n response.headers.set('X-RateLimit-Reset', String(resetTime))\n\n return response\n }\n}\n","/**\n * @h-ai/kit — Cookie 加密代理\n *\n * 通过 Proxy 拦截 SvelteKit Cookies 对象的 get/set 方法, 对指定名称的 Cookie 自动进行 SM4-CBC 加解密。\n * @module kit-cookie-proxy\n */\n\nimport type { CryptoFunctions } from '@h-ai/crypto'\nimport type { Cookies } from '@sveltejs/kit'\nimport { core } from '@h-ai/core'\n\n/**\n * Cookie 加密代理配置\n */\nexport interface CookieProxyConfig {\n /** 需要加密的 Cookie 名称集合 */\n names: Set<string>\n /** 对称加密服务(SM4) */\n symmetric: CryptoFunctions['symmetric']\n /** 加密密钥(32 字符十六进制) */\n encryptionKey: string\n}\n\n/**\n * 加密 Cookie 值的前缀标记\n *\n * 用于区分已加密和未加密的 Cookie 值,\n * 避免对明文值做解密导致乱码。\n */\nconst ENCRYPTED_PREFIX = 'enc:'\n\n/**\n * 创建加密 Cookie 代理\n *\n * 返回一个 Proxy 包装的 Cookies 对象:\n * - `get(name)` —— 若 name 在加密列表中,自动解密后返回明文\n * - `set(name, value, opts)` —— 若 name 在加密列表中,自动加密后存储\n * - `delete(name, opts)` —— 透传,无需解密\n * - 其他方法原样透传\n *\n * @param cookies - SvelteKit 原始 Cookies 对象\n * @param config - 加密配置\n * @returns 代理后的 Cookies 对象(类型不变)\n */\nexport function createEncryptedCookieProxy(\n cookies: Cookies,\n config: CookieProxyConfig,\n): Cookies {\n const { names, symmetric, encryptionKey } = config\n const logger = core.logger.child({ module: 'kit', scope: 'cookie-proxy' })\n\n return new Proxy(cookies, {\n get(target, prop, receiver) {\n // 拦截 get 方法:对加密 Cookie 自动解密\n if (prop === 'get') {\n return (name: string, opts?: Parameters<Cookies['get']>[1]) => {\n const raw = target.get(name, opts)\n if (!raw || !names.has(name))\n return raw\n\n // 仅解密带有加密前缀的值\n if (!raw.startsWith(ENCRYPTED_PREFIX))\n return raw\n\n try {\n const ciphertext = raw.slice(ENCRYPTED_PREFIX.length)\n // 格式: iv:ciphertext\n const separatorIndex = ciphertext.indexOf(':')\n if (separatorIndex === -1)\n return raw\n\n const iv = ciphertext.slice(0, separatorIndex)\n const encrypted = ciphertext.slice(separatorIndex + 1)\n\n const result = symmetric.decryptWithIV(encrypted, encryptionKey, iv)\n if (!result.success || typeof result.data !== 'string') {\n logger.warn('Cookie decryption failed, returning raw value', { name })\n return raw\n }\n\n return result.data\n }\n catch {\n logger.warn('Cookie decryption error, returning raw value', { name })\n return raw\n }\n }\n }\n\n // 拦截 set 方法:对加密 Cookie 自动加密\n if (prop === 'set') {\n return (name: string, value: string, opts: Parameters<Cookies['set']>[2]) => {\n if (names.has(name)) {\n try {\n const result = symmetric.encryptWithIV(value, encryptionKey)\n if (result.success && result.data) {\n // 格式: enc:iv:ciphertext\n value = `${ENCRYPTED_PREFIX}${result.data.iv}:${result.data.ciphertext}`\n }\n else {\n logger.warn('Cookie encryption failed, storing plaintext', { name })\n }\n }\n catch {\n logger.warn('Cookie encryption error, storing plaintext', { name })\n }\n }\n\n return target.set(name, value, opts)\n }\n }\n\n // 其他方法(getAll / delete / serialize)原样透传\n return Reflect.get(target, prop, receiver)\n },\n })\n}\n","/**\n * @h-ai/kit — SvelteKit Handle Hook\n *\n * 创建 SvelteKit Handle Hook,集成请求 ID 生成、会话验证、Cookie 加密代理、\n * 路由守卫、中间件链与可选传输加密;同时提供 `sequence()` 组合多个 Handle。\n * @module kit-handle\n */\n\nimport type { Handle, RequestEvent } from '@sveltejs/kit'\nimport type { GuardConfig, GuardResult, HandleConfig, Middleware, MiddlewareContext, SessionData } from '../kit-types.js'\nimport type { CookieProxyConfig } from './kit-cookie-proxy.js'\nimport { core } from '@h-ai/core'\nimport { configureAuth, getAccessToken } from '../kit-auth.js'\nimport { kitM } from '../kit-i18n.js'\nimport { isSvelteKitControlFlow } from '../kit-utils.js'\nimport { loggingMiddleware as loggingMiddlewareFn } from '../middleware/kit-logging.js'\nimport { rateLimitMiddleware as rateLimitMiddlewareFn } from '../middleware/kit-ratelimit.js'\nimport { handleA2ARequest, resolveA2AConfig } from '../modules/a2a/kit-a2a-handle.js'\nimport { transportEncryptionMiddleware } from '../modules/crypto/kit-transport-middleware.js'\nimport { createEncryptedCookieProxy } from './kit-cookie-proxy.js'\n\n/**\n * 生成唯一请求级 ID\n *\n * 由时间戳(base36)+ 6 位随机串拼接,用于日志追踪与响应头 `X-Request-Id`。\n */\nfunction generateId(prefix: string): string {\n const timestamp = Date.now().toString(36)\n const random = crypto.randomUUID().replace(/-/g, '').substring(0, 8)\n return `${prefix}_${timestamp}${random}`\n}\n\n/**\n * 为 SvelteKit 响应补充默认安全头。\n *\n * 仅设置不会破坏页面渲染的基础头;CSP 需要应用结合 nonce / 静态资源策略单独配置。\n */\nfunction applyDefaultSecurityHeaders(response: Response): void {\n response.headers.set('X-Content-Type-Options', 'nosniff')\n response.headers.set('X-Frame-Options', 'DENY')\n response.headers.set('Referrer-Policy', 'no-referrer')\n}\n\n/**\n * 创建 hai handle hook\n *\n * 整合会话解析、路由守卫、中间件链与统一错误处理的 SvelteKit Handle 工厂。\n *\n * 执行顺序:\n * 1. 生成 `requestId` 并写入 `event.locals`\n * 2. 根据 `auth` 配置从 Bearer / Cookie 解析会话\n * 3. 根据 `auth.protectedPaths` 自动执行路由守卫 + 额外自定义守卫\n * 4. 构建中间件链(内置 logging / rateLimit + 自定义)并执行\n * 5. 调用 `resolve(event)` 获取业务响应\n * 6. 附加 `X-Request-Id` 响应头\n *\n * @param config - Handle 配置(均有合理默认值,可零配置使用)\n * @returns SvelteKit Handle 函数\n *\n * @example\n * ```ts\n * export const handle = kit.createHandle({\n * auth: {\n * verifyToken: validateSession,\n * loginUrl: '/auth/login',\n * protectedPaths: ['/admin/*', '/api/*'],\n * publicPaths: ['/api/auth/*', '/api/public/*'],\n * },\n * rateLimit: { maxRequests: 100 },\n * crypto: { crypto, transport: true },\n * })\n * ```\n */\nexport function createHandle(config: HandleConfig = {}): Handle {\n const {\n auth: authConfig,\n rateLimit: rateLimitConfig,\n logging: loggingConfig = true,\n crypto: cryptoConfig,\n onError,\n guards: customGuards = [],\n middleware: customMiddleware = [],\n a2a: a2aInput,\n } = config\n\n // ── A2A 配置解析 ──\n const a2aResolved = resolveA2AConfig(a2aInput)\n\n // ── 配置 Cookie 名 + 认证操作 ──\n if (authConfig?.cookieName || authConfig?.operations) {\n configureAuth({ cookieName: authConfig.cookieName, operations: authConfig.operations })\n }\n\n // ── 构建守卫列表(auth 自动守卫 + 自定义守卫) ──\n const guards: GuardConfig[] = []\n if (authConfig?.protectedPaths?.length) {\n guards.push({\n guard: buildAuthGuard(authConfig.verifyToken, authConfig.loginUrl),\n paths: authConfig.protectedPaths,\n exclude: authConfig.publicPaths,\n })\n }\n guards.push(...customGuards)\n\n // ── 构建中间件链 ──\n const builtinMiddleware: Middleware[] = []\n if (loggingConfig) {\n const logOpts = typeof loggingConfig === 'object' ? loggingConfig : { logBody: false }\n builtinMiddleware.push(loggingMiddlewareFn(logOpts))\n }\n if (rateLimitConfig) {\n builtinMiddleware.push(rateLimitMiddlewareFn({\n windowMs: rateLimitConfig.windowMs ?? 60000,\n maxRequests: rateLimitConfig.maxRequests ?? 100,\n }))\n }\n const allMiddleware = [...builtinMiddleware, ...customMiddleware]\n\n // ── 传输加密中间件单独包裹整个 handle 流程 ──\n const transportMiddleware = buildTransportMiddleware(cryptoConfig)\n\n // ── Cookie 加密配置预处理 ──\n const cookieProxyConfig = buildCookieProxyConfig(cryptoConfig)\n\n return async ({ event, resolve }) => {\n const requestId = generateId('req')\n const context: MiddlewareContext = {\n event,\n requestId,\n }\n\n // 注入 requestId 到 event.locals\n // Workaround:SvelteKit App.Locals 是项目侧声明的 interface,库代码无法靠模块增强检查动态 key。\n const locals = event.locals as unknown as Record<string, unknown>\n locals.requestId = requestId\n\n // ── Cookie 加密代理(透明) ──\n if (cookieProxyConfig) {\n const proxiedCookies = createEncryptedCookieProxy(event.cookies, cookieProxyConfig)\n Object.defineProperty(event, 'cookies', {\n value: proxiedCookies,\n writable: true,\n configurable: true,\n })\n }\n\n const runRequest = async (): Promise<Response> => {\n try {\n // ── A2A 端点拦截(在认证/守卫之前,A2A 有专用认证) ──\n if (a2aResolved) {\n const a2aResponse = await handleA2ARequest(event, requestId, a2aResolved)\n if (a2aResponse)\n return a2aResponse\n }\n\n // ── 会话解析 ──\n let session: SessionData | undefined\n\n if (authConfig) {\n const token = getAccessToken(event.request, event.cookies)\n if (token) {\n session = await authConfig.verifyToken(token) ?? undefined\n locals.session = session\n if (session) {\n locals.accessToken = token\n }\n }\n }\n context.session = session\n\n // ── 执行守卫 ──\n for (const guardConfig of guards) {\n const guardResult = await executeGuard(guardConfig, event, session)\n\n if (!guardResult.allowed) {\n if (guardResult.redirect) {\n return new Response(null, {\n status: 302,\n headers: { Location: guardResult.redirect },\n })\n }\n\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'FORBIDDEN',\n message: guardResult.message ?? kitM('kit_accessDenied'),\n },\n requestId,\n }),\n {\n status: guardResult.status ?? 403,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n }\n\n // ── 中间件链 ──\n const response = await executeMiddlewareChain(\n allMiddleware,\n context,\n () => resolve(event),\n )\n\n return response\n }\n catch (error) {\n // SvelteKit 控制流异常(redirect / error)必须继续抛出\n if (isSvelteKitControlFlow(error)) {\n throw error\n }\n\n core.logger.error('Request failed', { requestId, error: error instanceof Error ? error.message : error })\n\n if (onError) {\n return onError(error, event)\n }\n\n // 默认错误响应\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: kitM('kit_internalError'),\n },\n requestId,\n }),\n {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n }\n\n const response = transportMiddleware\n ? await transportMiddleware(context, runRequest)\n : await runRequest()\n\n applyDefaultSecurityHeaders(response)\n response.headers.set('X-Request-Id', requestId)\n return response\n }\n}\n\n// ─── 内部:构建 auth 守卫 ───\n\n/**\n * 根据 auth 配置构建路由守卫\n *\n * - API 路径(以 `/api/` 开头):未认证返回 401 JSON\n * - 非 API 路径:未认证时重定向到 loginUrl(若配置),否则返回 401\n */\nfunction buildAuthGuard(\n verifyToken: (token: string) => Promise<SessionData | null>,\n loginUrl?: string,\n): (event: RequestEvent, session?: SessionData) => GuardResult {\n // verifyToken 参数仅用于类型签名对齐,实际会话已在上层解析\n void verifyToken\n\n return (event, session) => {\n if (session) {\n return { allowed: true }\n }\n\n const isApiRoute = event.url.pathname.startsWith('/api/')\n\n if (isApiRoute) {\n return {\n allowed: false,\n message: kitM('kit_authRequired'),\n status: 401,\n }\n }\n\n if (loginUrl) {\n const returnUrl = encodeURIComponent(event.url.pathname + event.url.search)\n return {\n allowed: false,\n redirect: `${loginUrl}?returnUrl=${returnUrl}`,\n }\n }\n\n return {\n allowed: false,\n message: kitM('kit_authRequired'),\n status: 401,\n }\n }\n}\n\n// ─── 内部:守卫执行 ───\n\n/**\n * 执行单个守卫(含路径过滤逻辑)\n */\nasync function executeGuard(\n config: GuardConfig,\n event: RequestEvent,\n session?: SessionData,\n): Promise<GuardResult> {\n const { guard, paths, exclude } = config\n const pathname = event.url.pathname\n\n if (exclude?.some(pattern => matchPath(pathname, pattern))) {\n return { allowed: true }\n }\n\n if (paths && !paths.some(pattern => matchPath(pathname, pattern))) {\n return { allowed: true }\n }\n\n return guard(event, session)\n}\n\n// ─── 内部:中间件执行 ───\n\n/**\n * 递归执行中间件链(洋葱模型)\n */\nasync function executeMiddlewareChain(\n middleware: Middleware[],\n context: MiddlewareContext,\n final: () => Response | Promise<Response>,\n): Promise<Response> {\n if (middleware.length === 0) {\n return final()\n }\n\n const [current, ...rest] = middleware\n\n return current(context, () => executeMiddlewareChain(rest, context, final))\n}\n\n// ─── 内部:路径匹配 ───\n\n/**\n * 路径通配符匹配(`/*` `/**` 精确匹配)\n */\nfunction matchPath(pathname: string, pattern: string): boolean {\n if (pattern.endsWith('/*')) {\n const base = pattern.slice(0, -2)\n return pathname === base || pathname.startsWith(`${base}/`)\n }\n\n if (pattern.endsWith('/**')) {\n const base = pattern.slice(0, -3)\n return pathname === base || pathname.startsWith(`${base}/`)\n }\n\n return pathname === pattern\n}\n\n// ─── 内部:Crypto 配置构建 ───\n\n/**\n * 构建最终中间件链:将传输加密中间件自动插入到最外层\n */\nfunction buildTransportMiddleware(\n cryptoConfig: HandleConfig['crypto'],\n): Middleware | null {\n if (!cryptoConfig?.transport)\n return null\n\n const transportOpts = typeof cryptoConfig.transport === 'object' ? cryptoConfig.transport : {}\n\n return transportEncryptionMiddleware({\n enabled: true,\n crypto: cryptoConfig.crypto,\n keyExchangePath: transportOpts.keyExchangePath,\n excludePaths: transportOpts.excludePaths,\n encryptResponse: transportOpts.encryptResponse,\n keyStore: transportOpts.keyStore,\n maxClients: transportOpts.maxClients,\n requireEncryption: transportOpts.requireEncryption,\n })\n}\n\n/**\n * 构建 Cookie 加密代理配置\n */\nfunction buildCookieProxyConfig(\n cryptoConfig: HandleConfig['crypto'],\n): CookieProxyConfig | null {\n if (!cryptoConfig?.encryptedCookies?.length)\n return null\n\n // eslint-disable-next-line node/prefer-global/process\n const key = cryptoConfig.cookieEncryptionKey ?? (typeof process !== 'undefined' ? process.env?.HAI_KIT_COOKIE_KEY : undefined)\n if (!key) {\n core.logger.warn('Cookie encryption configured but no key provided (set crypto.cookieEncryptionKey or HAI_KIT_COOKIE_KEY env)')\n return null\n }\n\n return {\n names: new Set(cryptoConfig.encryptedCookies),\n symmetric: cryptoConfig.crypto.symmetric,\n encryptionKey: key,\n }\n}\n\n/**\n * 组合多个 SvelteKit handle 为单一 handle\n *\n * 洋葱模型:`sequence(a, b, c)` 执行顺序为 a → b → c → resolve → c → b → a。\n *\n * @param handles - 待组合的 handle 函数列表\n * @returns 组合后的单一 Handle 函数\n *\n * @example\n * ```ts\n * const haiHandle = kit.createHandle({ ... })\n * export const handle = kit.sequence(i18nHandle, haiHandle)\n * ```\n */\nexport function sequence(...handles: Handle[]): Handle {\n const filtered = handles.filter(Boolean)\n if (filtered.length === 0) {\n return ({ event, resolve }) => resolve(event)\n }\n if (filtered.length === 1) {\n return filtered[0]\n }\n return async ({ event, resolve }) => {\n return filtered.reduceRight(\n (next, handle) => (event: RequestEvent) => handle({ event, resolve: next }),\n resolve,\n )(event)\n }\n}\n","/**\n * @h-ai/kit — API 响应工具\n *\n * 标准化 API 响应工具集,统一 `{ success, data?, error?, requestId? }` 结构。\n * 提供成功响应(ok / created / noContent)、错误响应\n * (badRequest / unauthorized / forbidden / notFound / conflict / validationError / internalError)\n * 以及重定向响应。\n * @module kit-response\n */\n\nimport type { HaiError } from '@h-ai/core'\nimport type { ApiResponse } from './kit-types.js'\nimport { kitM } from './kit-i18n.js'\n\n/**\n * 创建 200 成功响应\n *\n * @param data - 响应数据,序列化为 JSON\n * @param requestId - 可选请求 ID,用于链路追踪\n * @returns `{ success: true, data, requestId }` 格式的 JSON Response\n *\n * @example\n * ```ts\n * return kit.response.ok({ id: '1', name: 'Alice' })\n * ```\n */\nexport function ok<T>(data: T, requestId?: string): Response {\n const response: ApiResponse<T> = {\n success: true,\n data,\n requestId,\n }\n\n return new Response(JSON.stringify(response), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\n/**\n * 创建 201 资源创建成功响应\n *\n * @param data - 新创建的资源数据\n * @param requestId - 可选请求 ID\n * @returns `{ success: true, data }` 格式的 JSON Response(status 201)\n *\n * @example\n * ```ts\n * return kit.response.created({ id: 'new_1' })\n * ```\n */\nexport function created<T>(data: T, requestId?: string): Response {\n const response: ApiResponse<T> = {\n success: true,\n data,\n requestId,\n }\n\n return new Response(JSON.stringify(response), {\n status: 201,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\n/**\n * 创建 204 无内容响应\n *\n * 通常用于 DELETE 成功或无返回值的更新操作。\n *\n * @returns 空 body、status 204 的 Response\n */\nexport function noContent(): Response {\n return new Response(null, { status: 204 })\n}\n\n/**\n * 创建自定义错误响应\n *\n * @param code - 错误码(如 `'CUSTOM_ERROR'`)\n * @param message - 人可读错误消息\n * @param status - HTTP 状态码,默认 400\n * @param requestId - 可选请求 ID\n * @param details - 可选额外详情\n * @returns `{ success: false, error: { code, message, details } }` 格式的 JSON Response\n *\n * @example\n * ```ts\n * return kit.response.error('QUOTA_EXCEEDED', '配额已用尽', 429)\n * ```\n */\nexport function error(\n code: string,\n message: string,\n status = 400,\n requestId?: string,\n details?: unknown,\n): Response {\n const response: ApiResponse = {\n success: false,\n error: {\n code,\n message,\n details,\n },\n requestId,\n }\n\n return new Response(JSON.stringify(response), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\n/**\n * 创建 400 Bad Request 响应\n *\n * @param message - 错误消息\n * @param requestId - 可选请求 ID\n * @param details - 可选额外详情\n * @returns error code 为 `'BAD_REQUEST'` 的 JSON Response\n */\nexport function badRequest(message: string, requestId?: string, details?: unknown): Response {\n return error('BAD_REQUEST', message, 400, requestId, details)\n}\n\n/**\n * 创建 401 Unauthorized 响应\n *\n * @param message - 错误消息,默认 `'Authentication required'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'UNAUTHORIZED'` 的 JSON Response\n */\nexport function unauthorized(message?: string, requestId?: string): Response {\n return error('UNAUTHORIZED', message ?? kitM('kit_authRequired'), 401, requestId)\n}\n\n/**\n * 创建 403 Forbidden 响应\n *\n * @param message - 错误消息,默认 `'Access denied'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'FORBIDDEN'` 的 JSON Response\n */\nexport function forbidden(message?: string, requestId?: string): Response {\n return error('FORBIDDEN', message ?? kitM('kit_accessDenied'), 403, requestId)\n}\n\n/**\n * 创建 404 Not Found 响应\n *\n * @param message - 错误消息,默认 `'Resource not found'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'NOT_FOUND'` 的 JSON Response\n */\nexport function notFound(message?: string, requestId?: string): Response {\n return error('NOT_FOUND', message ?? kitM('kit_resourceNotFound'), 404, requestId)\n}\n\n/**\n * 创建 409 Conflict 响应\n *\n * @param message - 冲突描述(如重复创建等)\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'CONFLICT'` 的 JSON Response\n */\nexport function conflict(message: string, requestId?: string): Response {\n return error('CONFLICT', message, 409, requestId)\n}\n\n/**\n * 创建 422 Unprocessable Entity 响应(验证错误)\n *\n * @param errors - 字段级别的验证错误列表\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'VALIDATION_ERROR'`,details 包含 `errors` 数组\n *\n * @example\n * ```ts\n * return kit.response.validationError([\n * { field: 'email', message: '格式无效' },\n * ])\n * ```\n */\nexport function validationError(\n errors: Array<{ field: string, message: string }>,\n requestId?: string,\n): Response {\n return error('VALIDATION_ERROR', kitM('kit_validationFailed'), 422, requestId, { errors })\n}\n\n/**\n * 创建 500 Internal Server Error 响应\n *\n * @param message - 错误消息,默认 `'Internal server error'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'INTERNAL_ERROR'` 的 JSON Response\n */\nexport function internalError(message?: string, requestId?: string): Response {\n return error('INTERNAL_ERROR', message ?? kitM('kit_internalError'), 500, requestId)\n}\n\n/**\n * 创建重定向响应\n *\n * @param url - 目标 URL\n * @param status - HTTP 状态码,默认 302;常用 303(POST 后重定向)\n * @returns 带 `Location` 头的空 body Response\n *\n * @example\n * ```ts\n * return kit.response.redirect('/dashboard', 303)\n * ```\n */\nexport function redirect(url: string, status: 301 | 302 | 303 | 307 | 308 = 302): Response {\n return new Response(null, {\n status,\n headers: { Location: url },\n })\n}\n\n// ─── HaiResult → Response 转换 ───\n\n/**\n * 将 HaiResult<T> 转换为标准 API Response\n *\n * 成功时返回 200 ok(data),失败时从 error 对象中提取 code、message,\n * 并根据 httpStatusMap 映射 HTTP 状态码(未命中时默认 400)。\n *\n * @param result - core HaiResult 对象({ success, data } 或 { success: false, error })\n * @param httpStatusMap - 模块导出的错误码 → HTTP 状态码映射表(如 IamErrorHttpStatus)\n * @param requestId - 可选请求 ID,用于链路追踪\n * @returns 标准化 JSON Response\n *\n * @example\n * ```ts\n * // 无映射(默认 400)\n * return kit.response.fromResult(result)\n *\n * // 带模块错误码映射\n * return kit.response.fromResult(result, IamErrorHttpStatus)\n * ```\n */\nexport function fromResult<T>(\n result: { success: true, data: T } | { success: false, error: { code: number | string, message: string, [key: string]: unknown } },\n httpStatusMap?: Record<number | string, number>,\n requestId?: string,\n): Response {\n if (result.success) {\n return ok(result.data, requestId)\n }\n\n const { code, message } = result.error\n const status = httpStatusMap?.[code] ?? 400\n return error(String(code), message, status, requestId)\n}\n\nexport function fromError(\n haiError: HaiError,\n requestId?: string,\n): Response {\n return error(String(haiError.code), haiError.message, haiError.httpStatus ?? 400, requestId)\n}\n","/**\n * @h-ai/kit — API Handler 包装器\n *\n * 统一封装 SvelteKit API Handler 的错误处理逻辑。\n * @module kit-handler\n */\n\nimport type { RequestEvent, RequestHandler } from '@sveltejs/kit'\nimport { core } from '@h-ai/core'\nimport { internalError } from './kit-response.js'\nimport { isResponseLike, isSvelteKitControlFlow } from './kit-utils.js'\n\n/**\n * 创建 API Handler 包装器\n *\n * 将业务逻辑包裹在统一的异常边界中:\n * 1. 正常执行 `fn(event)` 返回 Response\n * 2. 若 `fn` throw 了 `Response`(如 `kit.guard.require` / `kit.validate.body`),直接返回该 Response\n * 3. 若 `fn` throw 了 SvelteKit 控制流(`redirect()` / `error()`),继续抛出\n * 4. 其他异常:记录日志 → 返回 `kit.response.internalError()`\n *\n * @param fn - 业务处理函数\n * @returns SvelteKit RequestHandler\n *\n * @example\n * ```ts\n * export const GET = kit.handler(async ({ locals }) => {\n * kit.guard.require(locals.session, 'user:read')\n * return kit.response.ok(await getUsers())\n * })\n * ```\n */\nexport function handler(fn: (event: RequestEvent) => Promise<Response> | Response): RequestHandler {\n return async (event) => {\n try {\n return await fn(event)\n }\n catch (error) {\n // validate.body / guard.require 等场景会 throw Response,直接返回即可\n // 使用 isResponseLike 兼容 Vite 开发环境下跨模块 instanceof 失效\n if (isResponseLike(error)) {\n return error\n }\n\n // redirect/error 等 SvelteKit 控制流必须继续抛出\n if (isSvelteKitControlFlow(error)) {\n throw error\n }\n\n const normalizedError = error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n cause: error.cause,\n }\n : error\n\n core.logger.error('Request handler error', {\n error: normalizedError,\n path: event.url.pathname,\n method: event.request.method,\n })\n\n return internalError()\n }\n }\n}\n","/**\n * @h-ai/kit — 请求数据验证\n *\n * 基于 Zod 的请求数据验证工具,支持表单/JSON Body、URL 查询参数与路由参数。\n * Zod 默认错误消息的本地化规则委托给 `core.zodValidation`,避免 kit / serv\n * 等模块重复维护同一套 issue 解析与消息映射逻辑;模块前缀映射也统一交给\n * `core.zodValidation.createPrefixedZodMessageGetter()` 处理。\n * 每种数据源都提供两类 API:\n * - 安全返回:`FormValidationResult`\n * - 失败抛出:`OrFail`(抛出 `Response` 以走 SvelteKit 控制流)\n * @module kit-validation\n */\n\nimport type { z } from 'zod'\nimport type { FormValidationResult } from './kit-types.js'\nimport { core } from '@h-ai/core'\nimport { z as zod } from 'zod'\nimport { kitM } from './kit-i18n.js'\nimport { badRequest } from './kit-response.js'\n\n// ─── 内部工具 ───\n\n/**\n * 构造与 kit 消息表对齐的 `ZodMessageGetter`。\n *\n * 统一复用 `core.zodValidation` 的 Zod issue 解析与默认消息识别逻辑,\n * kit 仅提供自己的消息获取器。\n */\nconst getKitZodMessage = core.zodValidation.createPrefixedZodMessageGetter<Parameters<typeof kitM>[0]>(\n 'kit',\n (messageKey, params) => kitM(messageKey, { params }),\n)\n\nfunction validateParsedData<T extends z.ZodType>(\n data: unknown,\n schema: T,\n): FormValidationResult<z.infer<T>> {\n const result = schema.safeParse(data)\n if (result.success)\n return { valid: true, data: result.data, errors: [] }\n return {\n valid: false,\n errors: core.zodValidation.mapZodErrorToFormErrors(result.error, getKitZodMessage),\n }\n}\n\nfunction unwrapValidationResultOrThrow<T>(result: FormValidationResult<T>): T {\n if (result.valid && result.data !== undefined)\n return result.data\n\n throw badRequest(\n result.errors[0]?.message ?? kitM('kit_validationFailed'),\n undefined,\n { errors: result.errors },\n )\n}\n\n// ─── 公共验证函数 ───\n\n/**\n * 从 Request 解析并验证表单数据\n *\n * 支持 `application/json` 和 `multipart/form-data` / `application/x-www-form-urlencoded`。\n * 其他 Content-Type 返回全局错误 `{ field: '_', message: 'Unsupported content type' }`。\n *\n * @param request - SvelteKit 请求对象\n * @param schema - Zod Schema\n * @returns 验证结果;成功时 `valid: true` 且 `data` 类型安全\n *\n * @example\n * ```ts\n * const { valid, data, errors } = await kit.validate.form(event.request, CreateUserSchema)\n * if (!valid) return kit.response.validationError(errors)\n * ```\n */\nexport async function validateForm<T extends z.ZodType>(\n request: Request,\n schema: T,\n): Promise<FormValidationResult<z.infer<T>>> {\n try {\n const contentType = request.headers.get('content-type') ?? ''\n\n let data: unknown\n\n if (contentType.includes('application/json')) {\n data = await request.json()\n }\n else if (contentType.includes('application/x-www-form-urlencoded') || contentType.includes('multipart/form-data')) {\n const formData = await request.formData()\n data = Object.fromEntries(formData)\n }\n else {\n return {\n valid: false,\n errors: [{ field: '_', message: kitM('kit_unsupportedContentType') }],\n }\n }\n\n return validateParsedData(data, schema)\n }\n catch {\n return {\n valid: false,\n errors: [{ field: '_', message: kitM('kit_parseBodyFailed') }],\n }\n }\n}\n\n/**\n * 从 URL 查询参数验证\n *\n * 将 `url.searchParams` 转为普通对象后交给 Zod 校验。\n * 适用于 GET 请求的分页、搜索等场景。\n *\n * @param url - 请求 URL 对象\n * @param schema - Zod Schema\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const { valid, data } = kit.validate.query(event.url, PaginationSchema)\n * ```\n */\nexport function validateQuery<T extends z.ZodType>(\n url: URL,\n schema: T,\n): FormValidationResult<z.infer<T>> {\n const data = Object.fromEntries(url.searchParams)\n return validateParsedData(data, schema)\n}\n\n/**\n * 验证路径参数\n *\n * 将 SvelteKit 路由 `params` 交给 Zod 校验,适用于动态路由段的类型安全校验。\n *\n * @param params - SvelteKit 路由参数(`event.params`)\n * @param schema - Zod Schema\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const { valid, data } = kit.validate.params(event.params, z.object({ id: z.string().uuid() }))\n * ```\n */\nexport function validateParams<T extends z.ZodType>(\n params: Record<string, string>,\n schema: T,\n): FormValidationResult<z.infer<T>> {\n return validateParsedData(params, schema)\n}\n\n// ─── OrFail 变体 — 校验失败时抛出 Response(SvelteKit 控制流) ───\n\n/**\n * 从 Request 解析并验证表单数据,失败时 throw Response\n *\n * 与 `validateForm` 功能相同,但校验失败时 throw 400 Response(SvelteKit 控制流),\n * 搭配 `kit.handler()` 使用可精简 handler 代码。\n *\n * @param request - SvelteKit 请求对象\n * @param schema - Zod Schema\n * @returns 校验通过的数据(类型安全)\n * @throws Response - 400 BadRequest(含首条错误消息)\n *\n * @example\n * ```ts\n * export const POST = kit.handler(async ({ request }) => {\n * const data = await kit.validate.body(request, CreateUserSchema)\n * // data 类型安全,校验已通过\n * })\n * ```\n */\nexport async function validateFormOrFail<T extends z.ZodType>(\n request: Request,\n schema: T,\n): Promise<z.infer<T>> {\n return unwrapValidationResultOrThrow(await validateForm(request, schema))\n}\n\n/**\n * 从 URL 查询参数验证,失败时 throw Response\n *\n * @param url - 请求 URL 对象\n * @param schema - Zod Schema\n * @returns 校验通过的数据\n * @throws Response - 400 BadRequest\n *\n * @example\n * ```ts\n * const query = kit.validate.query(event.url, PaginationSchema)\n * ```\n */\nexport function validateQueryOrFail<T extends z.ZodType>(\n url: URL,\n schema: T,\n): z.infer<T> {\n return unwrapValidationResultOrThrow(validateQuery(url, schema))\n}\n\n/**\n * 验证路径参数,失败时 throw Response\n *\n * @param params - SvelteKit 路由参数\n * @param schema - Zod Schema\n * @returns 校验通过的数据\n * @throws Response - 400 BadRequest\n *\n * @example\n * ```ts\n * const { id } = kit.validate.params(event.params, IdParamSchema)\n * ```\n */\nexport function validateParamsOrFail<T extends z.ZodType>(\n params: Record<string, string>,\n schema: T,\n): z.infer<T> {\n return unwrapValidationResultOrThrow(validateParams(params, schema))\n}\n\n// ─── 通用 Schema ───\n\n/**\n * 路径参数 id 校验 Schema\n *\n * 验证 `event.params.id` 为非空字符串。\n *\n * @example\n * ```ts\n * const { id } = kit.validate.params(event.params, IdParamSchema)\n * ```\n */\nexport const IdParamSchema = zod.object({\n id: zod.string().min(1, kitM('kit_idRequired')),\n})\n\n/** 分页 pageSize 上限 */\nconst MAX_PAGE_SIZE = 100\n\n/**\n * 通用分页查询参数 Schema\n *\n * 包含 page(默认 1)、pageSize(默认 20,上限 100)、search(可选)。\n * 可通过 `.extend()` 扩展业务字段。\n *\n * @example\n * ```ts\n * // 直接使用\n * const { page, pageSize, search } = kit.validate.query(url, PaginationQuerySchema)\n *\n * // 扩展业务字段\n * const ListUsersSchema = PaginationQuerySchema.extend({\n * enabled: z.enum(['true', 'false']).transform(v => v === 'true').optional(),\n * })\n * ```\n */\nexport const PaginationQuerySchema = zod.object({\n page: zod.coerce.number().int().min(1).default(1),\n pageSize: zod.coerce.number().int().min(1).max(MAX_PAGE_SIZE).default(20),\n search: zod.string().optional(),\n})\n","/**\n * @h-ai/kit — 服务对象主入口\n *\n * SvelteKit 集成模块的统一命名空间出口。 所有功能通过 kit 对象访问:\n * @module kit-main\n */\n\nimport { createKitClient, installBrowserTransport, installBrowserTransportFetch } from './client/kit-client.js'\nimport { defineCrud } from './crud/kit-crud.js'\nimport { hasPermission, requirePermission } from './guards/kit-permission.js'\nimport { createHandle, sequence } from './hooks/kit-handle.js'\nimport {\n clearBrowserToken,\n createTokenStore,\n login,\n loginWithApiKey,\n loginWithLdap,\n loginWithOtp,\n logout,\n registerAndLogin,\n setBrowserToken,\n} from './kit-auth.js'\nimport { KitConfigSchema, resolveKitConfig, resolveKitTransportConfig } from './kit-config.js'\nimport { handler } from './kit-handler.js'\nimport { setAllModulesLocale } from './kit-i18n.js'\nimport { badRequest, conflict, created, error, forbidden, fromError, fromResult, internalError, noContent, notFound, ok, redirect, unauthorized, validationError } from './kit-response.js'\nimport { IdParamSchema, PaginationQuerySchema, validateFormOrFail, validateParamsOrFail, validateQueryOrFail } from './kit-validation.js'\n\nexport { KitConfigSchema, resolveKitConfig, resolveKitTransportConfig }\n\n/**\n * Kit 模块统一出口。\n *\n * 作为纯工具模块,kit 不需要 init/close 生命周期,\n * 所有功能均为无状态工厂函数或工具函数。\n */\nexport const kit = {\n // ─── Handle Hook ───\n\n /** 创建 SvelteKit Handle Hook(含 auth / logging / rateLimit 内置配置) */\n createHandle,\n /** 组合多个 Handle */\n sequence,\n /** API Handler 包装器(自动错误边界) */\n handler,\n\n // ─── 路由守卫 ───\n\n guard: {\n /** 要求权限,不满足时 throw Response(SvelteKit 控制流) */\n require: requirePermission,\n /** 检查会话是否具有指定权限(布尔) */\n check: hasPermission,\n },\n\n // ─── API 响应 ───\n\n response: {\n /** 200 成功 */\n ok,\n /** 201 创建成功 */\n created,\n /** 204 无内容 */\n noContent,\n /** 自定义错误响应 */\n error,\n /** 400 BadRequest */\n badRequest,\n /** 401 Unauthorized */\n unauthorized,\n /** 403 Forbidden */\n forbidden,\n /** 404 NotFound */\n notFound,\n /** 409 Conflict */\n conflict,\n /** 422 验证错误 */\n validationError,\n /** 500 InternalError */\n internalError,\n /** 重定向 */\n redirect,\n /** 将 HaiResult<T> 转为标准 API Response(支持 httpStatusMap) */\n fromResult,\n /** 将模块错误码映射为标准 HTTP Response */\n fromError,\n },\n\n // ─── 验证 ───\n\n validate: {\n /** 验证请求体(JSON/表单),失败 throw Response */\n body: validateFormOrFail,\n /** 验证查询参数,失败 throw Response */\n query: validateQueryOrFail,\n /** 验证路径参数,失败 throw Response */\n params: validateParamsOrFail,\n /** 路径参数 id Schema({id: string}) */\n IdParamSchema,\n /** 通用分页查询 Schema(page / pageSize / search) */\n PaginationQuerySchema,\n },\n\n // ─── 客户端工具 ───\n\n client: {\n /** 创建统一客户端(CSRF + 传输加密透明合并) */\n create: createKitClient,\n /**\n * 用解析后的 {@link KitConfig} 一键安装浏览器端传输加密\n * (应用层推荐入口;内部预热 crypto 并调用 installBrowserTransportFetch)\n */\n installBrowserTransport,\n /** 底层入口:直接传 transport 配置安装浏览器全局 fetch 包装 */\n installBrowserTransportFetch,\n },\n\n // ─── 认证工具 ───\n\n auth: {\n /** 服务端登录(密码):内部调用 iam.auth.login + 自动写入 Token Cookie */\n login,\n /** 服务端登录(OTP 验证码):内部调用 iam.auth.loginWithOtp + 自动写入 Token Cookie */\n loginWithOtp,\n /** 服务端登录(LDAP):内部调用 iam.auth.loginWithLdap + 自动写入 Token Cookie */\n loginWithLdap,\n /** 服务端登录(API Key):内部调用 iam.auth.loginWithApiKey + 自动写入 Token Cookie */\n loginWithApiKey,\n /** 服务端注册并登录:内部调用 iam.auth.registerAndLogin + 自动写入 Token Cookie */\n registerAndLogin,\n /** 服务端登出:内部调用 iam.auth.logout + 清除 Token Cookie */\n logout,\n /** 写入浏览器端 Access Token(客户端 login/register 用) */\n setBrowserToken,\n /** 清除浏览器端 Access Token(客户端 logout 用) */\n clearBrowserToken,\n /** 创建浏览器端 Token 存储器(自定义 key 时使用) */\n createTokenStore,\n },\n\n // ─── CRUD ───\n\n crud: {\n /** 定义 CRUD 资源(声明式配置 → 操作对象) */\n define: defineCrud,\n },\n\n // ─── i18n ───\n\n i18n: {\n /** 统一设置所有 hai 模块的默认语言 */\n setLocale: setAllModulesLocale,\n },\n}\n"]}
1
+ {"version":3,"sources":["../src/guards/kit-permission.ts","../src/kit-utils.ts","../src/middleware/kit-logging.ts","../src/middleware/kit-ratelimit.ts","../src/hooks/kit-cookie-proxy.ts","../src/hooks/kit-handle.ts","../src/kit-response.ts","../src/kit-handler.ts","../src/kit-validation.ts","../src/kit-main.ts"],"names":["core","response","error","event","zod"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @h-ai/kit — 权限守卫\n *\n * 验证用户是否具有指定权限。\n * @module kit-permission\n */\n\nimport type { GuardResult, RouteGuard, SessionLike } from '../kit-types.js'\nimport { kitM } from '../kit-i18n.js'\n\n/**\n * 权限守卫配置\n */\nexport interface PermissionGuardConfig {\n /** 需要的权限列表(默认 OR 逻辑,满足任一即通过) */\n permissions: string[]\n /** 为 `true` 时要求用户拥有 **全部** 权限(AND 逻辑) */\n requireAll?: boolean\n /** 无权限时重定向 URL(默认 `'/403'`) */\n forbiddenUrl?: string\n /** 为 `true` 时返回 JSON 403 而非重定向 */\n apiMode?: boolean\n}\n\n/**\n * 创建权限守卫\n *\n * 检查用户 `session.permissions` 是否满足配置中的权限要求。\n * 支持通配符匹配:`admin:*` 可匹配 `admin:read`、`admin:write` 等。\n * 未认证时返回 401;权限不匹配时根据 `apiMode` 返回 JSON 403 或重定向。\n *\n * @param config - 权限守卫配置\n * @returns RouteGuard 实例\n *\n * @example\n * ```ts\n * guards: [\n * { guard: kit.guard.permission({ permissions: ['user:read', 'user:write'], requireAll: true }), paths: ['/api/users/*'] },\n * ]\n * ```\n */\nexport function permissionGuard(config: PermissionGuardConfig): RouteGuard {\n const { permissions, requireAll = false, forbiddenUrl = '/403', apiMode = false } = config\n\n return (_event, session): GuardResult => {\n if (!session) {\n return {\n allowed: false,\n message: kitM('kit_authRequired'),\n status: 401,\n }\n }\n\n const userPermissions = session.permissions ?? []\n\n // 支持通配符权限,如 admin:* 匹配 admin:read, admin:write 等\n const hasPermission = requireAll\n ? permissions.every(perm => matchPermission(perm, userPermissions))\n : permissions.some(perm => matchPermission(perm, userPermissions))\n\n if (!hasPermission) {\n if (apiMode) {\n return {\n allowed: false,\n message: kitM('kit_requiredPermissions', { params: { permissions: permissions.join(', ') } }),\n status: 403,\n }\n }\n\n return {\n allowed: false,\n redirect: forbiddenUrl,\n }\n }\n\n return { allowed: true }\n }\n}\n\n/**\n * 匹配权限\n *\n * 支持通配符:\n * - `admin:*` 匹配 `admin:read`、`admin:write` 等\n * - `*` 匹配所有权限\n *\n * @param required - 需要的权限码\n * @param userPermissions - 用户已有的权限列表\n * @returns 是否匹配\n */\nexport function matchPermission(required: string, userPermissions: string[]): boolean {\n for (const userPerm of userPermissions) {\n // 完全匹配\n if (userPerm === required) {\n return true\n }\n\n // 用户有超级权限\n if (userPerm === '*') {\n return true\n }\n\n // 通配符匹配\n if (userPerm.endsWith(':*')) {\n const prefix = userPerm.slice(0, -1) // 移除 *\n if (required.startsWith(prefix)) {\n return true\n }\n }\n }\n\n return false\n}\n\n/**\n * 检查会话是否具有指定权限(布尔判断)\n *\n * 适用于条件分支场景(如菜单过滤、按钮显示等)。\n *\n * @param session - 当前会话数据,null/undefined 视为无权限\n * @param permission - 需要的权限码,如 `user:read`\n * @returns 是否拥有权限\n *\n * @example\n * ```ts\n * if (kit.guard.check(locals.session, 'user:read')) {\n * // 有权限\n * }\n * ```\n */\nexport function hasPermission(\n session: SessionLike | null | undefined,\n permission: string,\n): boolean {\n if (!session)\n return false\n return matchPermission(permission, session.permissions ?? [])\n}\n\n/**\n * 断言会话具有指定权限,不满足时返回 403 Response\n *\n * 适用于 SvelteKit API Handler 内部,不满足权限时直接返回 JSON 错误响应。\n * 调用者需检查返回值:若有返回值则表示权限不足,应直接 return。\n *\n * @param session - 当前会话数据,null/undefined 视为未认证\n * @param permission - 需要的权限码,如 `user:create`\n * @returns 权限不足时返回 Response;有权限时返回 undefined\n *\n * @example\n * ```ts\n * export const POST: RequestHandler = async ({ locals }) => {\n * const denied = kit.guard.assertPermission(locals.session, 'user:create')\n * if (denied) return denied\n * // ... 正常逻辑\n * }\n * ```\n */\nexport function assertPermission(\n session: SessionLike | null | undefined,\n permission: string,\n): Response | undefined {\n if (!session) {\n return new Response(\n JSON.stringify({ success: false, error: kitM('kit_unauthorized') }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n if (!matchPermission(permission, session.permissions ?? [])) {\n return new Response(\n JSON.stringify({ success: false, error: kitM('kit_forbidden', { params: { permission } }) }),\n { status: 403, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n return undefined\n}\n\n/**\n * 要求会话具有指定权限,不满足时 throw Response\n *\n * 利用 SvelteKit 控制流机制:throw 的 Response 对象会被框架捕获并直接作为响应返回。\n * 搭配 `kit.handler()` 使用时,无需手动检查返回值。\n *\n * @param session - 当前会话数据,null/undefined 视为未认证\n * @param permission - 需要的权限码,如 `user:create`\n * @throws Response - 未认证 401 / 无权限 403\n *\n * @example\n * ```ts\n * export const GET = kit.handler(async ({ locals }) => {\n * kit.guard.require(locals.session, 'user:read')\n * // 执行到这里说明权限已通过\n * return kit.response.ok(data)\n * })\n * ```\n */\nexport function requirePermission(\n session: SessionLike | null | undefined,\n permission: string,\n): void {\n const denied = assertPermission(session, permission)\n if (denied) {\n throw denied\n }\n}\n\n/**\n * 权限守卫高阶函数包装器\n *\n * 将权限检查从业务逻辑中提取到装饰层,handler 内部无需关心权限。\n * 未认证返回 401、无权限返回 403(均通过 SvelteKit throw 控制流抛出)。\n *\n * 适用于 page load、API handler 等所有 SvelteKit server 函数。\n *\n * @param permission - 需要的权限码,如 `'user:read'`\n * @param handler - 原始处理函数\n * @returns 包装后的处理函数(签名不变)\n *\n * @example\n * ```ts\n * // +page.server.ts\n * export const load = kit.guard.withPermission('user:read', async ({ locals }) => {\n * const result = await iam.user.listUsers()\n * return { users: result.success ? result.data.items : [] }\n * })\n *\n * // +server.ts (API handler)\n * export const GET = kit.handler(kit.guard.withPermission('user:list', async ({ locals }) => {\n * const result = await iam.user.listUsers()\n * return kit.response.ok(result.data)\n * }))\n * ```\n */\nexport function withPermission<TEvent extends { locals: Record<string, unknown> }, TReturn>(\n permission: string,\n handler: (event: TEvent) => Promise<TReturn>,\n): (event: TEvent) => Promise<TReturn> {\n return async (event: TEvent) => {\n requirePermission(event.locals.session as SessionLike | undefined, permission)\n return handler(event)\n }\n}\n","/**\n * @h-ai/kit — 内部工具函数\n *\n * 提取 Handler 与 Handle 共享的 SvelteKit 控制流检测逻辑。\n * @module kit-utils\n */\n\n/**\n * 检测是否为 Response 对象(兼容跨模块 instanceof 失效场景)\n *\n * 在 Vite 开发环境下,不同模块可能引用不同的 `Response` 构造器,\n * 导致 `instanceof Response` 返回 false。通过特征检测兜底辨识。\n *\n * @param value - 待检测值\n * @returns 是否为 Response(或 Response-like 对象)\n */\nexport function isResponseLike(value: unknown): value is Response {\n if (value instanceof Response)\n return true\n if (\n typeof value === 'object'\n && value !== null\n && 'status' in value\n && 'headers' in value\n && typeof (value as Response).text === 'function'\n && typeof (value as Response).json === 'function'\n ) {\n return true\n }\n return false\n}\n\n/**\n * 检测是否为 SvelteKit 控制流对象(redirect / error)\n *\n * SvelteKit 的 `redirect()` 和 `error()` 会抛出带 `status` 属性的特殊对象,\n * 框架在上层捕获后做控制流处理。此类对象必须继续抛出,不可吞掉。\n *\n * redirect 特征:`{ status, location }` 且 status 为 number\n * error 特征:`{ status, body }` 且 status 为 number\n *\n * @param value - 被捕获的异常\n * @returns 是否为 SvelteKit 控制流\n */\nexport function isSvelteKitControlFlow(value: unknown): boolean {\n // Response 对象不是控制流\n if (isResponseLike(value))\n return false\n if (typeof value === 'object' && value !== null && 'status' in value) {\n const status = (value as { status: unknown }).status\n return typeof status === 'number'\n }\n return false\n}\n","/**\n * @h-ai/kit — 日志中间件\n *\n * HTTP 请求日志中间件,记录请求/响应摘要(方法、路径、状态码、耗时),\n * 并自动脱敏敏感字段(password / token / secret 等)。\n * @module kit-logging\n */\n\nimport type { Middleware } from '../kit-types.js'\nimport { core } from '@h-ai/core'\n\n/**\n * 日志中间件配置\n */\nexport interface LoggingMiddlewareConfig {\n /** 为 `true` 时记录非 GET 请求体(自动脱敏) */\n logBody?: boolean\n /** 为 `true` 时记录响应头 */\n logResponse?: boolean\n /** 指定需要脱敏的字段名(默认 `['password', 'token', 'secret']`) */\n redactFields?: string[]\n}\n\n/**\n * 创建日志中间件\n *\n * 以 `core.logger.trace` 级别记录请求进出信息,包含:\n * - 请求:method / path / query / userAgent / ip\n * - 响应:status / duration\n *\n * 敏感字段会被自动替换为 `[REDACTED]`。\n *\n * @param config - 日志配置\n * @returns Middleware 实例\n *\n * @example\n * ```ts\n * middleware: [\n * kit.middleware.logging({ logBody: true, redactFields: ['password', 'creditCard'] }),\n * ]\n * ```\n */\nexport function loggingMiddleware(config: LoggingMiddlewareConfig = {}): Middleware {\n const { logBody = false, logResponse = false, redactFields = ['password', 'token', 'secret', 'authorization', 'apikey', 'api_key', 'creditcard', 'credit_card'] } = config\n\n return async (context, next) => {\n const { event, requestId } = context\n const startTime = Date.now()\n\n // 安全获取客户端 IP,处理开发环境下可能的错误\n let clientIp = 'unknown'\n try {\n clientIp = event.getClientAddress?.() ?? 'unknown'\n }\n catch {\n // 开发环境下 getClientAddress 可能抛出错误\n }\n\n const logData: Record<string, unknown> = {\n requestId,\n method: event.request.method,\n path: event.url.pathname,\n query: Object.fromEntries(event.url.searchParams),\n userAgent: event.request.headers.get('user-agent'),\n ip: clientIp,\n }\n\n if (logBody && event.request.method !== 'GET') {\n try {\n const clonedRequest = event.request.clone()\n const body = await clonedRequest.json()\n logData.body = redactObject(body, redactFields)\n }\n catch {\n // 忽略非 JSON 请求体\n }\n }\n\n core.logger.trace('Incoming request', { ...logData })\n\n const response = await next()\n\n const duration = Date.now() - startTime\n\n const responseLogData: Record<string, unknown> = {\n requestId,\n status: response.status,\n duration,\n }\n\n if (logResponse) {\n responseLogData.headers = Object.fromEntries(response.headers)\n }\n\n core.logger.trace('Request completed', { ...responseLogData })\n\n return response\n }\n}\n\n/**\n * 递归屏蔽对象中的敏感字段\n *\n * 匹配规则:字段名转小写后与 `fields` 列表比较。\n *\n * @param obj - 待处理对象\n * @param fields - 需要屏蔽的字段名列表(全小写)\n * @returns 屏蔽后的副本\n */\nfunction redactObject(obj: unknown, fields: string[]): unknown {\n return core.sanitize.sanitizeSensitiveFields(obj, { matcher: fields })\n}\n","/**\n * @h-ai/kit — 速率限制中间件\n *\n * 基于滑动窗口的请求速率限制中间件。\n * 内置内存存储(`MemoryRateLimitStore`),并支持通过 `RateLimitStore` 接入\n * Redis 等外部存储后端。\n * @module kit-ratelimit\n */\n\nimport type { Middleware, RateLimitConfig } from '../kit-types.js'\nimport { core } from '@h-ai/core'\nimport { kitM } from '../kit-i18n.js'\n\n/**\n * 速率限制存储条目\n */\nexport interface RateLimitEntry {\n /** 当前窗口内的请求次数 */\n count: number\n /** 窗口重置时间戳(ms) */\n resetAt: number\n}\n\n/**\n * 速率限制存储接口\n *\n * 内置 `MemoryRateLimitStore` 适合单进程开发;\n * 多实例部署需传入基于 Redis / @h-ai/cache 的分布式实现。\n *\n * @example\n * ```ts\n * // 自定义 Redis 存储\n * const redisStore: RateLimitStore = {\n * async get(key) { ... },\n * async set(key, entry) { ... },\n * async delete(key) { ... },\n * }\n * kit.middleware.rateLimit({ windowMs: 60_000, maxRequests: 100, store: redisStore })\n * ```\n */\nexport interface RateLimitStore {\n /** 获取指定 key 的限流条目 */\n get: (key: string) => Promise<RateLimitEntry | undefined> | RateLimitEntry | undefined\n /** 设置限流条目 */\n set: (key: string, entry: RateLimitEntry) => Promise<void> | void\n /** 删除指定 key 的限流条目 */\n delete: (key: string) => Promise<void> | void\n /**\n * 原子自增并返回当前计数和重置时间\n *\n * 实现时必须保证 get→increment→set 操作的原子性,\n * 防止并发请求在窗口切换时产生竞态绕过限流。\n * 若未实现,则退回非原子 get+set 流程。\n *\n * @param key - 限流键\n * @param windowMs - 窗口时长(ms)\n * @returns 自增后的计数和窗口重置时间\n */\n increment?: (key: string, windowMs: number) => Promise<RateLimitEntry> | RateLimitEntry\n}\n\n/**\n * 内存速率限制存储\n *\n * 基于 Map 实现,适合单进程/开发环境。\n * 多实例部署时限流上限会乘以实例数,建议使用分布式 Store。\n */\nexport class MemoryRateLimitStore implements RateLimitStore {\n private store = new Map<string, RateLimitEntry>()\n private cleanupTimer: ReturnType<typeof setInterval> | null = null\n\n /**\n * 启动定期清理过期条目\n *\n * @param intervalMs - 清理间隔(毫秒)\n */\n startCleanup(intervalMs: number): void {\n if (this.cleanupTimer)\n return\n this.cleanupTimer = setInterval(() => {\n const now = Date.now()\n for (const [key, entry] of this.store) {\n if (entry.resetAt < now) {\n this.store.delete(key)\n }\n }\n }, intervalMs)\n // 允许进程正常退出\n if (this.cleanupTimer && typeof this.cleanupTimer === 'object' && 'unref' in this.cleanupTimer) {\n this.cleanupTimer.unref()\n }\n }\n\n /**\n * 停止定期清理并释放定时器资源\n *\n * 调用后可再次 startCleanup 重启。进程退出 / 热重载 / 测试拆装场景必须调用以\n * 避免资源泄漏。\n */\n stopCleanup(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer)\n this.cleanupTimer = null\n }\n }\n\n get(key: string): RateLimitEntry | undefined {\n return this.store.get(key)\n }\n\n set(key: string, entry: RateLimitEntry): void {\n this.store.set(key, entry)\n }\n\n delete(key: string): void {\n this.store.delete(key)\n }\n\n /**\n * 原子自增(内存实现为同步操作,天然原子)\n *\n * @param key - 限流键\n * @param windowMs - 窗口时长\n * @returns 自增后的条目\n */\n increment(key: string, windowMs: number): RateLimitEntry {\n const now = Date.now()\n let entry = this.store.get(key)\n if (!entry || entry.resetAt < now) {\n entry = { count: 1, resetAt: now + windowMs }\n }\n else {\n entry.count++\n }\n this.store.set(key, entry)\n return entry\n }\n}\n\n/**\n * 创建速率限制中间件\n *\n * 基于可插拔存储的滑动窗口限流:\n * - 超限时返回 429,并在响应头中告知重置时间\n * - 正常响应附带 `X-RateLimit-*` 头\n * - 默认使用内存存储(单进程),可传入 `store` 实现分布式限流\n *\n * @param config - 限流配置\n * @returns Middleware 实例\n *\n * @example\n * ```ts\n * middleware: [\n * kit.middleware.rateLimit({ windowMs: 60_000, maxRequests: 100 }),\n * ]\n * ```\n */\nexport function rateLimitMiddleware(config: RateLimitConfig): Middleware {\n const {\n windowMs,\n maxRequests,\n keyGenerator = (event) => {\n try {\n return event.getClientAddress?.() ?? 'unknown'\n }\n catch {\n // 开发环境下 getClientAddress 可能抛出错误\n return 'unknown'\n }\n },\n onLimitReached,\n } = config\n\n // 构建存储:支持外部注入,默认内存\n const store: RateLimitStore = config.store ?? (() => {\n const memStore = new MemoryRateLimitStore()\n memStore.startCleanup(windowMs)\n return memStore\n })()\n\n return async (context, next) => {\n const { event, requestId } = context\n const key = keyGenerator(event)\n const now = Date.now()\n\n // 优先使用原子 increment,防止并发竞态\n let entry: RateLimitEntry\n if (store.increment) {\n entry = await store.increment(key, windowMs)\n }\n else {\n // 退回非原子流程(仅用于未实现 increment 的存储后端)\n const existing = await store.get(key)\n if (!existing || existing.resetAt < now) {\n entry = { count: 1, resetAt: now + windowMs }\n }\n else {\n entry = { ...existing, count: existing.count + 1 }\n }\n await store.set(key, entry)\n }\n\n // 设置速率限制头\n const remaining = Math.max(0, maxRequests - entry.count)\n const resetTime = Math.ceil(entry.resetAt / 1000)\n\n if (entry.count > maxRequests) {\n core.logger.warn('Rate limit exceeded', { key, requestId })\n\n if (onLimitReached) {\n return onLimitReached(event)\n }\n\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'RATE_LIMIT_EXCEEDED',\n message: kitM('kit_rateLimitExceeded'),\n },\n requestId,\n }),\n {\n status: 429,\n headers: {\n 'Content-Type': 'application/json',\n 'X-RateLimit-Limit': String(maxRequests),\n 'X-RateLimit-Remaining': '0',\n 'X-RateLimit-Reset': String(resetTime),\n 'Retry-After': String(Math.ceil((entry.resetAt - now) / 1000)),\n },\n },\n )\n }\n\n const response = await next()\n\n // 添加速率限制头到响应\n response.headers.set('X-RateLimit-Limit', String(maxRequests))\n response.headers.set('X-RateLimit-Remaining', String(remaining))\n response.headers.set('X-RateLimit-Reset', String(resetTime))\n\n return response\n }\n}\n","/**\n * @h-ai/kit — Cookie 加密代理\n *\n * 通过 Proxy 拦截 SvelteKit Cookies 对象的 get/set 方法, 对指定名称的 Cookie 自动进行 SM4-CBC 加解密。\n * @module kit-cookie-proxy\n */\n\nimport type { CryptoFunctions } from '@h-ai/crypto'\nimport type { Cookies } from '@sveltejs/kit'\nimport { core } from '@h-ai/core'\n\n/**\n * Cookie 加密代理配置\n */\nexport interface CookieProxyConfig {\n /** 需要加密的 Cookie 名称集合 */\n names: Set<string>\n /** 对称加密服务(SM4) */\n symmetric: CryptoFunctions['symmetric']\n /** 加密密钥(32 字符十六进制) */\n encryptionKey: string\n}\n\n/**\n * 加密 Cookie 值的前缀标记\n *\n * 用于区分已加密和未加密的 Cookie 值,\n * 避免对明文值做解密导致乱码。\n */\nconst ENCRYPTED_PREFIX = 'enc:'\n\n/**\n * 创建加密 Cookie 代理\n *\n * 返回一个 Proxy 包装的 Cookies 对象:\n * - `get(name)` —— 若 name 在加密列表中,自动解密后返回明文;格式或解密失败时返回 `undefined`\n * - `set(name, value, opts)` —— 若 name 在加密列表中,自动加密后存储;加密失败时拒绝写入\n * - `delete(name, opts)` —— 透传,无需解密\n * - 其他方法原样透传\n *\n * @param cookies - SvelteKit 原始 Cookies 对象\n * @param config - 加密配置\n * @returns 代理后的 Cookies 对象(类型不变)\n */\nexport function createEncryptedCookieProxy(\n cookies: Cookies,\n config: CookieProxyConfig,\n): Cookies {\n const { names, symmetric, encryptionKey } = config\n const logger = core.logger.child({ module: 'kit', scope: 'cookie-proxy' })\n\n return new Proxy(cookies, {\n get(target, prop, receiver) {\n // 拦截 get 方法:对加密 Cookie 自动解密\n if (prop === 'get') {\n return (name: string, opts?: Parameters<Cookies['get']>[1]) => {\n const raw = target.get(name, opts)\n if (!raw || !names.has(name))\n return raw\n\n // 受保护 Cookie 不接受明文,避免攻击者绕过加密边界注入伪造值。\n if (!raw.startsWith(ENCRYPTED_PREFIX)) {\n logger.warn('Encrypted cookie has invalid format', { name })\n return undefined\n }\n\n try {\n const ciphertext = raw.slice(ENCRYPTED_PREFIX.length)\n // 格式: iv:ciphertext\n const separatorIndex = ciphertext.indexOf(':')\n if (separatorIndex === -1) {\n logger.warn('Encrypted cookie has invalid format', { name })\n return undefined\n }\n\n const iv = ciphertext.slice(0, separatorIndex)\n const encrypted = ciphertext.slice(separatorIndex + 1)\n\n const result = symmetric.decryptWithIV(encrypted, encryptionKey, iv)\n if (!result.success || typeof result.data !== 'string') {\n logger.warn('Cookie decryption failed', { name })\n return undefined\n }\n\n return result.data\n }\n catch {\n logger.warn('Cookie decryption error', { name })\n return undefined\n }\n }\n }\n\n // 拦截 set 方法:对加密 Cookie 自动加密\n if (prop === 'set') {\n return (name: string, value: string, opts: Parameters<Cookies['set']>[2]) => {\n if (names.has(name)) {\n const result = symmetric.encryptWithIV(value, encryptionKey)\n if (!result.success || !result.data) {\n logger.error('Cookie encryption failed', { name })\n throw new Error('Cookie encryption failed')\n }\n // 格式: enc:iv:ciphertext\n value = `${ENCRYPTED_PREFIX}${result.data.iv}:${result.data.ciphertext}`\n }\n\n return target.set(name, value, opts)\n }\n }\n\n // 其他方法(getAll / delete / serialize)原样透传\n return Reflect.get(target, prop, receiver)\n },\n })\n}\n","/**\n * @h-ai/kit — SvelteKit Handle Hook\n *\n * 创建 SvelteKit Handle Hook,集成请求 ID 生成、会话验证、Cookie 加密代理、\n * 路由守卫、中间件链与可选传输加密;同时提供 `sequence()` 组合多个 Handle。\n * @module kit-handle\n */\n\nimport type { Handle, RequestEvent } from '@sveltejs/kit'\nimport type { GuardConfig, GuardResult, HandleConfig, Middleware, MiddlewareContext, SessionData } from '../kit-types.js'\nimport type { CookieProxyConfig } from './kit-cookie-proxy.js'\nimport { core } from '@h-ai/core'\nimport { configureAuth, getAccessToken } from '../kit-auth.js'\nimport { kitM } from '../kit-i18n.js'\nimport { isSvelteKitControlFlow } from '../kit-utils.js'\nimport { loggingMiddleware as loggingMiddlewareFn } from '../middleware/kit-logging.js'\nimport { rateLimitMiddleware as rateLimitMiddlewareFn } from '../middleware/kit-ratelimit.js'\nimport { handleA2ARequest, resolveA2AConfig } from '../modules/a2a/kit-a2a-handle.js'\nimport { transportEncryptionMiddleware } from '../modules/crypto/kit-transport-middleware.js'\nimport { createEncryptedCookieProxy } from './kit-cookie-proxy.js'\n\n/**\n * 生成唯一请求级 ID\n *\n * 由时间戳(base36)+ 6 位随机串拼接,用于日志追踪与响应头 `X-Request-Id`。\n */\nfunction generateId(prefix: string): string {\n const timestamp = Date.now().toString(36)\n const random = crypto.randomUUID().replace(/-/g, '').substring(0, 8)\n return `${prefix}_${timestamp}${random}`\n}\n\n/**\n * 为 SvelteKit 响应补充默认安全头。\n *\n * 仅设置不会破坏页面渲染的基础头;CSP 需要应用结合 nonce / 静态资源策略单独配置。\n */\nfunction applyDefaultSecurityHeaders(response: Response): void {\n response.headers.set('X-Content-Type-Options', 'nosniff')\n response.headers.set('X-Frame-Options', 'DENY')\n response.headers.set('Referrer-Policy', 'no-referrer')\n}\n\n/**\n * 创建 hai handle hook\n *\n * 整合会话解析、路由守卫、中间件链与统一错误处理的 SvelteKit Handle 工厂。\n *\n * 执行顺序:\n * 1. 生成 `requestId` 并写入 `event.locals`\n * 2. 根据 `auth` 配置从 Bearer / Cookie 解析会话\n * 3. 根据 `auth.protectedPaths` 自动执行路由守卫 + 额外自定义守卫\n * 4. 构建中间件链(内置 logging / rateLimit + 自定义)并执行\n * 5. 调用 `resolve(event)` 获取业务响应\n * 6. 附加 `X-Request-Id` 响应头\n *\n * @param config - Handle 配置(均有合理默认值,可零配置使用)\n * @returns SvelteKit Handle 函数\n *\n * @example\n * ```ts\n * export const handle = kit.createHandle({\n * auth: {\n * verifyToken: validateSession,\n * loginUrl: '/auth/login',\n * protectedPaths: ['/admin/*', '/api/*'],\n * publicPaths: ['/api/auth/*', '/api/public/*'],\n * },\n * rateLimit: { maxRequests: 100 },\n * crypto: { crypto, transport: true },\n * })\n * ```\n */\nexport function createHandle(config: HandleConfig = {}): Handle {\n const {\n auth: authConfig,\n rateLimit: rateLimitConfig,\n logging: loggingConfig = true,\n crypto: cryptoConfig,\n onError,\n guards: customGuards = [],\n middleware: customMiddleware = [],\n a2a: a2aInput,\n } = config\n\n // ── A2A 配置解析 ──\n const a2aResolved = resolveA2AConfig(a2aInput)\n\n // ── 配置 Cookie 名 + 认证操作 ──\n if (authConfig?.cookieName || authConfig?.operations) {\n configureAuth({ cookieName: authConfig.cookieName, operations: authConfig.operations })\n }\n\n // ── 构建守卫列表(auth 自动守卫 + 自定义守卫) ──\n const guards: GuardConfig[] = []\n if (authConfig?.protectedPaths?.length) {\n guards.push({\n guard: buildAuthGuard(authConfig.verifyToken, authConfig.loginUrl),\n paths: authConfig.protectedPaths,\n exclude: authConfig.publicPaths,\n })\n }\n guards.push(...customGuards)\n\n // ── 构建中间件链 ──\n const builtinMiddleware: Middleware[] = []\n if (loggingConfig) {\n const logOpts = typeof loggingConfig === 'object' ? loggingConfig : { logBody: false }\n builtinMiddleware.push(loggingMiddlewareFn(logOpts))\n }\n if (rateLimitConfig) {\n builtinMiddleware.push(rateLimitMiddlewareFn({\n windowMs: rateLimitConfig.windowMs ?? 60000,\n maxRequests: rateLimitConfig.maxRequests ?? 100,\n }))\n }\n const allMiddleware = [...builtinMiddleware, ...customMiddleware]\n\n // ── 传输加密中间件单独包裹整个 handle 流程 ──\n const transportMiddleware = buildTransportMiddleware(cryptoConfig)\n\n // ── Cookie 加密配置预处理 ──\n const cookieProxyConfig = buildCookieProxyConfig(cryptoConfig)\n\n return async ({ event, resolve }) => {\n const requestId = generateId('req')\n const context: MiddlewareContext = {\n event,\n requestId,\n }\n\n // 注入 requestId 到 event.locals\n // Workaround:SvelteKit App.Locals 是项目侧声明的 interface,库代码无法靠模块增强检查动态 key。\n const locals = event.locals as unknown as Record<string, unknown>\n locals.requestId = requestId\n\n // ── Cookie 加密代理(透明) ──\n if (cookieProxyConfig) {\n const proxiedCookies = createEncryptedCookieProxy(event.cookies, cookieProxyConfig)\n Object.defineProperty(event, 'cookies', {\n value: proxiedCookies,\n writable: true,\n configurable: true,\n })\n }\n\n const runRequest = async (): Promise<Response> => {\n try {\n // ── A2A 端点拦截(在认证/守卫之前,A2A 有专用认证) ──\n if (a2aResolved) {\n const a2aResponse = await handleA2ARequest(event, requestId, a2aResolved)\n if (a2aResponse)\n return a2aResponse\n }\n\n // ── 会话解析 ──\n let session: SessionData | undefined\n\n if (authConfig) {\n const token = getAccessToken(event.request, event.cookies)\n if (token) {\n session = await authConfig.verifyToken(token) ?? undefined\n locals.session = session\n if (session) {\n locals.accessToken = token\n }\n }\n }\n context.session = session\n\n // ── 执行守卫 ──\n for (const guardConfig of guards) {\n const guardResult = await executeGuard(guardConfig, event, session)\n\n if (!guardResult.allowed) {\n if (guardResult.redirect) {\n return new Response(null, {\n status: 302,\n headers: { Location: guardResult.redirect },\n })\n }\n\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'FORBIDDEN',\n message: guardResult.message ?? kitM('kit_accessDenied'),\n },\n requestId,\n }),\n {\n status: guardResult.status ?? 403,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n }\n\n // ── 中间件链 ──\n const response = await executeMiddlewareChain(\n allMiddleware,\n context,\n () => resolve(event),\n )\n\n return response\n }\n catch (error) {\n // SvelteKit 控制流异常(redirect / error)必须继续抛出\n if (isSvelteKitControlFlow(error)) {\n throw error\n }\n\n core.logger.error('Request failed', { requestId, error: error instanceof Error ? error.message : error })\n\n if (onError) {\n return onError(error, event)\n }\n\n // 默认错误响应\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: kitM('kit_internalError'),\n },\n requestId,\n }),\n {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n }\n\n const response = transportMiddleware\n ? await transportMiddleware(context, runRequest)\n : await runRequest()\n\n applyDefaultSecurityHeaders(response)\n response.headers.set('X-Request-Id', requestId)\n return response\n }\n}\n\n// ─── 内部:构建 auth 守卫 ───\n\n/**\n * 根据 auth 配置构建路由守卫\n *\n * - API 路径(以 `/api/` 开头):未认证返回 401 JSON\n * - 非 API 路径:未认证时重定向到 loginUrl(若配置),否则返回 401\n */\nfunction buildAuthGuard(\n verifyToken: (token: string) => Promise<SessionData | null>,\n loginUrl?: string,\n): (event: RequestEvent, session?: SessionData) => GuardResult {\n // verifyToken 参数仅用于类型签名对齐,实际会话已在上层解析\n void verifyToken\n\n return (event, session) => {\n if (session) {\n return { allowed: true }\n }\n\n const isApiRoute = event.url.pathname.startsWith('/api/')\n\n if (isApiRoute) {\n return {\n allowed: false,\n message: kitM('kit_authRequired'),\n status: 401,\n }\n }\n\n if (loginUrl) {\n const returnUrl = encodeURIComponent(event.url.pathname + event.url.search)\n return {\n allowed: false,\n redirect: `${loginUrl}?returnUrl=${returnUrl}`,\n }\n }\n\n return {\n allowed: false,\n message: kitM('kit_authRequired'),\n status: 401,\n }\n }\n}\n\n// ─── 内部:守卫执行 ───\n\n/**\n * 执行单个守卫(含路径过滤逻辑)\n */\nasync function executeGuard(\n config: GuardConfig,\n event: RequestEvent,\n session?: SessionData,\n): Promise<GuardResult> {\n const { guard, paths, exclude } = config\n const pathname = event.url.pathname\n\n if (exclude?.some(pattern => matchPath(pathname, pattern))) {\n return { allowed: true }\n }\n\n if (paths && !paths.some(pattern => matchPath(pathname, pattern))) {\n return { allowed: true }\n }\n\n return guard(event, session)\n}\n\n// ─── 内部:中间件执行 ───\n\n/**\n * 递归执行中间件链(洋葱模型)\n */\nasync function executeMiddlewareChain(\n middleware: Middleware[],\n context: MiddlewareContext,\n final: () => Response | Promise<Response>,\n): Promise<Response> {\n if (middleware.length === 0) {\n return final()\n }\n\n const [current, ...rest] = middleware\n\n return current(context, () => executeMiddlewareChain(rest, context, final))\n}\n\n// ─── 内部:路径匹配 ───\n\n/**\n * 路径通配符匹配(`/*` `/**` 精确匹配)\n */\nfunction matchPath(pathname: string, pattern: string): boolean {\n if (pattern.endsWith('/*')) {\n const base = pattern.slice(0, -2)\n return pathname === base || pathname.startsWith(`${base}/`)\n }\n\n if (pattern.endsWith('/**')) {\n const base = pattern.slice(0, -3)\n return pathname === base || pathname.startsWith(`${base}/`)\n }\n\n return pathname === pattern\n}\n\n// ─── 内部:Crypto 配置构建 ───\n\n/**\n * 构建最终中间件链:将传输加密中间件自动插入到最外层\n */\nfunction buildTransportMiddleware(\n cryptoConfig: HandleConfig['crypto'],\n): Middleware | null {\n if (!cryptoConfig?.transport)\n return null\n\n const transportOpts = typeof cryptoConfig.transport === 'object' ? cryptoConfig.transport : {}\n\n return transportEncryptionMiddleware({\n enabled: true,\n crypto: cryptoConfig.crypto,\n keyExchangePath: transportOpts.keyExchangePath,\n excludePaths: transportOpts.excludePaths,\n encryptResponse: transportOpts.encryptResponse,\n keyStore: transportOpts.keyStore,\n maxClients: transportOpts.maxClients,\n requireEncryption: transportOpts.requireEncryption,\n })\n}\n\n/**\n * 构建 Cookie 加密代理配置\n */\nfunction buildCookieProxyConfig(\n cryptoConfig: HandleConfig['crypto'],\n): CookieProxyConfig | null {\n if (!cryptoConfig?.encryptedCookies?.length)\n return null\n\n // eslint-disable-next-line node/prefer-global/process\n const key = cryptoConfig.cookieEncryptionKey ?? (typeof process !== 'undefined' ? process.env?.HAI_KIT_COOKIE_KEY : undefined)\n if (!key) {\n throw new Error('Cookie encryption requires crypto.cookieEncryptionKey or HAI_KIT_COOKIE_KEY')\n }\n\n return {\n names: new Set(cryptoConfig.encryptedCookies),\n symmetric: cryptoConfig.crypto.symmetric,\n encryptionKey: key,\n }\n}\n\n/**\n * 组合多个 SvelteKit handle 为单一 handle\n *\n * 洋葱模型:`sequence(a, b, c)` 执行顺序为 a → b → c → resolve → c → b → a。\n *\n * @param handles - 待组合的 handle 函数列表\n * @returns 组合后的单一 Handle 函数\n *\n * @example\n * ```ts\n * const haiHandle = kit.createHandle({ ... })\n * export const handle = kit.sequence(i18nHandle, haiHandle)\n * ```\n */\nexport function sequence(...handles: Handle[]): Handle {\n const filtered = handles.filter(Boolean)\n if (filtered.length === 0) {\n return ({ event, resolve }) => resolve(event)\n }\n if (filtered.length === 1) {\n return filtered[0]\n }\n return async ({ event, resolve }) => {\n return filtered.reduceRight(\n (next, handle) => (event: RequestEvent) => handle({ event, resolve: next }),\n resolve,\n )(event)\n }\n}\n","/**\n * @h-ai/kit — API 响应工具\n *\n * 标准化 API 响应工具集,统一 `{ success, data?, error?, requestId? }` 结构。\n * 提供成功响应(ok / created / noContent)、错误响应\n * (badRequest / unauthorized / forbidden / notFound / conflict / validationError / internalError)\n * 以及重定向响应。\n * @module kit-response\n */\n\nimport type { HaiError } from '@h-ai/core'\nimport type { ApiResponse } from './kit-types.js'\nimport { kitM } from './kit-i18n.js'\n\n/**\n * 创建 200 成功响应\n *\n * @param data - 响应数据,序列化为 JSON\n * @param requestId - 可选请求 ID,用于链路追踪\n * @returns `{ success: true, data, requestId }` 格式的 JSON Response\n *\n * @example\n * ```ts\n * return kit.response.ok({ id: '1', name: 'Alice' })\n * ```\n */\nexport function ok<T>(data: T, requestId?: string): Response {\n const response: ApiResponse<T> = {\n success: true,\n data,\n requestId,\n }\n\n return new Response(JSON.stringify(response), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\n/**\n * 创建 201 资源创建成功响应\n *\n * @param data - 新创建的资源数据\n * @param requestId - 可选请求 ID\n * @returns `{ success: true, data }` 格式的 JSON Response(status 201)\n *\n * @example\n * ```ts\n * return kit.response.created({ id: 'new_1' })\n * ```\n */\nexport function created<T>(data: T, requestId?: string): Response {\n const response: ApiResponse<T> = {\n success: true,\n data,\n requestId,\n }\n\n return new Response(JSON.stringify(response), {\n status: 201,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\n/**\n * 创建 204 无内容响应\n *\n * 通常用于 DELETE 成功或无返回值的更新操作。\n *\n * @returns 空 body、status 204 的 Response\n */\nexport function noContent(): Response {\n return new Response(null, { status: 204 })\n}\n\n/**\n * 创建自定义错误响应\n *\n * @param code - 错误码(如 `'CUSTOM_ERROR'`)\n * @param message - 人可读错误消息\n * @param status - HTTP 状态码,默认 400\n * @param requestId - 可选请求 ID\n * @param details - 可选额外详情\n * @returns `{ success: false, error: { code, message, details } }` 格式的 JSON Response\n *\n * @example\n * ```ts\n * return kit.response.error('QUOTA_EXCEEDED', '配额已用尽', 429)\n * ```\n */\nexport function error(\n code: string,\n message: string,\n status = 400,\n requestId?: string,\n details?: unknown,\n): Response {\n const response: ApiResponse = {\n success: false,\n error: {\n code,\n message,\n details,\n },\n requestId,\n }\n\n return new Response(JSON.stringify(response), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\n/**\n * 创建 400 Bad Request 响应\n *\n * @param message - 错误消息\n * @param requestId - 可选请求 ID\n * @param details - 可选额外详情\n * @returns error code 为 `'BAD_REQUEST'` 的 JSON Response\n */\nexport function badRequest(message: string, requestId?: string, details?: unknown): Response {\n return error('BAD_REQUEST', message, 400, requestId, details)\n}\n\n/**\n * 创建 401 Unauthorized 响应\n *\n * @param message - 错误消息,默认 `'Authentication required'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'UNAUTHORIZED'` 的 JSON Response\n */\nexport function unauthorized(message?: string, requestId?: string): Response {\n return error('UNAUTHORIZED', message ?? kitM('kit_authRequired'), 401, requestId)\n}\n\n/**\n * 创建 403 Forbidden 响应\n *\n * @param message - 错误消息,默认 `'Access denied'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'FORBIDDEN'` 的 JSON Response\n */\nexport function forbidden(message?: string, requestId?: string): Response {\n return error('FORBIDDEN', message ?? kitM('kit_accessDenied'), 403, requestId)\n}\n\n/**\n * 创建 404 Not Found 响应\n *\n * @param message - 错误消息,默认 `'Resource not found'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'NOT_FOUND'` 的 JSON Response\n */\nexport function notFound(message?: string, requestId?: string): Response {\n return error('NOT_FOUND', message ?? kitM('kit_resourceNotFound'), 404, requestId)\n}\n\n/**\n * 创建 409 Conflict 响应\n *\n * @param message - 冲突描述(如重复创建等)\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'CONFLICT'` 的 JSON Response\n */\nexport function conflict(message: string, requestId?: string): Response {\n return error('CONFLICT', message, 409, requestId)\n}\n\n/**\n * 创建 422 Unprocessable Entity 响应(验证错误)\n *\n * @param errors - 字段级别的验证错误列表\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'VALIDATION_ERROR'`,details 包含 `errors` 数组\n *\n * @example\n * ```ts\n * return kit.response.validationError([\n * { field: 'email', message: '格式无效' },\n * ])\n * ```\n */\nexport function validationError(\n errors: Array<{ field: string, message: string }>,\n requestId?: string,\n): Response {\n return error('VALIDATION_ERROR', kitM('kit_validationFailed'), 422, requestId, { errors })\n}\n\n/**\n * 创建 500 Internal Server Error 响应\n *\n * @param message - 错误消息,默认 `'Internal server error'`\n * @param requestId - 可选请求 ID\n * @returns error code 为 `'INTERNAL_ERROR'` 的 JSON Response\n */\nexport function internalError(message?: string, requestId?: string): Response {\n return error('INTERNAL_ERROR', message ?? kitM('kit_internalError'), 500, requestId)\n}\n\n/**\n * 创建重定向响应\n *\n * @param url - 目标 URL\n * @param status - HTTP 状态码,默认 302;常用 303(POST 后重定向)\n * @returns 带 `Location` 头的空 body Response\n *\n * @example\n * ```ts\n * return kit.response.redirect('/dashboard', 303)\n * ```\n */\nexport function redirect(url: string, status: 301 | 302 | 303 | 307 | 308 = 302): Response {\n return new Response(null, {\n status,\n headers: { Location: url },\n })\n}\n\n// ─── HaiResult → Response 转换 ───\n\n/**\n * 将 HaiResult<T> 转换为标准 API Response\n *\n * 成功时返回 200 ok(data),失败时从 error 对象中提取 code、message,\n * 并根据 httpStatusMap 映射 HTTP 状态码(未命中时默认 400)。\n *\n * @param result - core HaiResult 对象({ success, data } 或 { success: false, error })\n * @param httpStatusMap - 模块导出的错误码 → HTTP 状态码映射表(如 IamErrorHttpStatus)\n * @param requestId - 可选请求 ID,用于链路追踪\n * @returns 标准化 JSON Response\n *\n * @example\n * ```ts\n * // 无映射(默认 400)\n * return kit.response.fromResult(result)\n *\n * // 带模块错误码映射\n * return kit.response.fromResult(result, IamErrorHttpStatus)\n * ```\n */\nexport function fromResult<T>(\n result: { success: true, data: T } | { success: false, error: { code: number | string, message: string, [key: string]: unknown } },\n httpStatusMap?: Record<number | string, number>,\n requestId?: string,\n): Response {\n if (result.success) {\n return ok(result.data, requestId)\n }\n\n const { code, message } = result.error\n const status = httpStatusMap?.[code] ?? 400\n return error(String(code), message, status, requestId)\n}\n\nexport function fromError(\n haiError: HaiError,\n requestId?: string,\n): Response {\n return error(String(haiError.code), haiError.message, haiError.httpStatus ?? 400, requestId)\n}\n","/**\n * @h-ai/kit — API Handler 包装器\n *\n * 统一封装 SvelteKit API Handler 的错误处理逻辑。\n * @module kit-handler\n */\n\nimport type { RequestEvent, RequestHandler } from '@sveltejs/kit'\nimport { core } from '@h-ai/core'\nimport { internalError } from './kit-response.js'\nimport { isResponseLike, isSvelteKitControlFlow } from './kit-utils.js'\n\n/**\n * 创建 API Handler 包装器\n *\n * 将业务逻辑包裹在统一的异常边界中:\n * 1. 正常执行 `fn(event)` 返回 Response\n * 2. 若 `fn` throw 了 `Response`(如 `kit.guard.require` / `kit.validate.body`),直接返回该 Response\n * 3. 若 `fn` throw 了 SvelteKit 控制流(`redirect()` / `error()`),继续抛出\n * 4. 其他异常:记录日志 → 返回 `kit.response.internalError()`\n *\n * @param fn - 业务处理函数\n * @returns SvelteKit RequestHandler\n *\n * @example\n * ```ts\n * export const GET = kit.handler(async ({ locals }) => {\n * kit.guard.require(locals.session, 'user:read')\n * return kit.response.ok(await getUsers())\n * })\n * ```\n */\nexport function handler(fn: (event: RequestEvent) => Promise<Response> | Response): RequestHandler {\n return async (event) => {\n try {\n return await fn(event)\n }\n catch (error) {\n // validate.body / guard.require 等场景会 throw Response,直接返回即可\n // 使用 isResponseLike 兼容 Vite 开发环境下跨模块 instanceof 失效\n if (isResponseLike(error)) {\n return error\n }\n\n // redirect/error 等 SvelteKit 控制流必须继续抛出\n if (isSvelteKitControlFlow(error)) {\n throw error\n }\n\n const normalizedError = error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n cause: error.cause,\n }\n : error\n\n core.logger.error('Request handler error', {\n error: normalizedError,\n path: event.url.pathname,\n method: event.request.method,\n })\n\n return internalError()\n }\n }\n}\n","/**\n * @h-ai/kit — 请求数据验证\n *\n * 基于 Zod 的请求数据验证工具,支持表单/JSON Body、URL 查询参数与路由参数。\n * Zod 默认错误消息的本地化规则委托给 `core.zodValidation`,避免 kit / serv\n * 等模块重复维护同一套 issue 解析与消息映射逻辑;模块前缀映射也统一交给\n * `core.zodValidation.createPrefixedZodMessageGetter()` 处理。\n * 每种数据源都提供两类 API:\n * - 安全返回:`FormValidationResult`\n * - 失败抛出:`OrFail`(抛出 `Response` 以走 SvelteKit 控制流)\n * @module kit-validation\n */\n\nimport type { z } from 'zod'\nimport type { FormValidationResult } from './kit-types.js'\nimport { core } from '@h-ai/core'\nimport { z as zod } from 'zod'\nimport { kitM } from './kit-i18n.js'\nimport { badRequest } from './kit-response.js'\n\n// ─── 内部工具 ───\n\n/**\n * 构造与 kit 消息表对齐的 `ZodMessageGetter`。\n *\n * 统一复用 `core.zodValidation` 的 Zod issue 解析与默认消息识别逻辑,\n * kit 仅提供自己的消息获取器。\n */\nconst getKitZodMessage = core.zodValidation.createPrefixedZodMessageGetter<Parameters<typeof kitM>[0]>(\n 'kit',\n (messageKey, params) => kitM(messageKey, { params }),\n)\n\nfunction validateParsedData<T extends z.ZodType>(\n data: unknown,\n schema: T,\n): FormValidationResult<z.infer<T>> {\n const result = schema.safeParse(data)\n if (result.success)\n return { valid: true, data: result.data, errors: [] }\n return {\n valid: false,\n errors: core.zodValidation.mapZodErrorToFormErrors(result.error, getKitZodMessage),\n }\n}\n\nfunction unwrapValidationResultOrThrow<T>(result: FormValidationResult<T>): T {\n if (result.valid && result.data !== undefined)\n return result.data\n\n throw badRequest(\n result.errors[0]?.message ?? kitM('kit_validationFailed'),\n undefined,\n { errors: result.errors },\n )\n}\n\n// ─── 公共验证函数 ───\n\n/**\n * 从 Request 解析并验证表单数据\n *\n * 支持 `application/json` 和 `multipart/form-data` / `application/x-www-form-urlencoded`。\n * 其他 Content-Type 返回全局错误 `{ field: '_', message: 'Unsupported content type' }`。\n *\n * @param request - SvelteKit 请求对象\n * @param schema - Zod Schema\n * @returns 验证结果;成功时 `valid: true` 且 `data` 类型安全\n *\n * @example\n * ```ts\n * const { valid, data, errors } = await kit.validate.form(event.request, CreateUserSchema)\n * if (!valid) return kit.response.validationError(errors)\n * ```\n */\nexport async function validateForm<T extends z.ZodType>(\n request: Request,\n schema: T,\n): Promise<FormValidationResult<z.infer<T>>> {\n try {\n const contentType = request.headers.get('content-type') ?? ''\n\n let data: unknown\n\n if (contentType.includes('application/json')) {\n data = await request.json()\n }\n else if (contentType.includes('application/x-www-form-urlencoded') || contentType.includes('multipart/form-data')) {\n const formData = await request.formData()\n data = Object.fromEntries(formData)\n }\n else {\n return {\n valid: false,\n errors: [{ field: '_', message: kitM('kit_unsupportedContentType') }],\n }\n }\n\n return validateParsedData(data, schema)\n }\n catch {\n return {\n valid: false,\n errors: [{ field: '_', message: kitM('kit_parseBodyFailed') }],\n }\n }\n}\n\n/**\n * 从 URL 查询参数验证\n *\n * 将 `url.searchParams` 转为普通对象后交给 Zod 校验。\n * 适用于 GET 请求的分页、搜索等场景。\n *\n * @param url - 请求 URL 对象\n * @param schema - Zod Schema\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const { valid, data } = kit.validate.query(event.url, PaginationSchema)\n * ```\n */\nexport function validateQuery<T extends z.ZodType>(\n url: URL,\n schema: T,\n): FormValidationResult<z.infer<T>> {\n const data = Object.fromEntries(url.searchParams)\n return validateParsedData(data, schema)\n}\n\n/**\n * 验证路径参数\n *\n * 将 SvelteKit 路由 `params` 交给 Zod 校验,适用于动态路由段的类型安全校验。\n *\n * @param params - SvelteKit 路由参数(`event.params`)\n * @param schema - Zod Schema\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const { valid, data } = kit.validate.params(event.params, z.object({ id: z.string().uuid() }))\n * ```\n */\nexport function validateParams<T extends z.ZodType>(\n params: Record<string, string>,\n schema: T,\n): FormValidationResult<z.infer<T>> {\n return validateParsedData(params, schema)\n}\n\n// ─── OrFail 变体 — 校验失败时抛出 Response(SvelteKit 控制流) ───\n\n/**\n * 从 Request 解析并验证表单数据,失败时 throw Response\n *\n * 与 `validateForm` 功能相同,但校验失败时 throw 400 Response(SvelteKit 控制流),\n * 搭配 `kit.handler()` 使用可精简 handler 代码。\n *\n * @param request - SvelteKit 请求对象\n * @param schema - Zod Schema\n * @returns 校验通过的数据(类型安全)\n * @throws Response - 400 BadRequest(含首条错误消息)\n *\n * @example\n * ```ts\n * export const POST = kit.handler(async ({ request }) => {\n * const data = await kit.validate.body(request, CreateUserSchema)\n * // data 类型安全,校验已通过\n * })\n * ```\n */\nexport async function validateFormOrFail<T extends z.ZodType>(\n request: Request,\n schema: T,\n): Promise<z.infer<T>> {\n return unwrapValidationResultOrThrow(await validateForm(request, schema))\n}\n\n/**\n * 从 URL 查询参数验证,失败时 throw Response\n *\n * @param url - 请求 URL 对象\n * @param schema - Zod Schema\n * @returns 校验通过的数据\n * @throws Response - 400 BadRequest\n *\n * @example\n * ```ts\n * const query = kit.validate.query(event.url, PaginationSchema)\n * ```\n */\nexport function validateQueryOrFail<T extends z.ZodType>(\n url: URL,\n schema: T,\n): z.infer<T> {\n return unwrapValidationResultOrThrow(validateQuery(url, schema))\n}\n\n/**\n * 验证路径参数,失败时 throw Response\n *\n * @param params - SvelteKit 路由参数\n * @param schema - Zod Schema\n * @returns 校验通过的数据\n * @throws Response - 400 BadRequest\n *\n * @example\n * ```ts\n * const { id } = kit.validate.params(event.params, IdParamSchema)\n * ```\n */\nexport function validateParamsOrFail<T extends z.ZodType>(\n params: Record<string, string>,\n schema: T,\n): z.infer<T> {\n return unwrapValidationResultOrThrow(validateParams(params, schema))\n}\n\n// ─── 通用 Schema ───\n\n/**\n * 路径参数 id 校验 Schema\n *\n * 验证 `event.params.id` 为非空字符串。\n *\n * @example\n * ```ts\n * const { id } = kit.validate.params(event.params, IdParamSchema)\n * ```\n */\nexport const IdParamSchema = zod.object({\n id: zod.string().min(1, kitM('kit_idRequired')),\n})\n\n/** 分页 pageSize 上限 */\nconst MAX_PAGE_SIZE = 100\n\n/**\n * 通用分页查询参数 Schema\n *\n * 包含 page(默认 1)、pageSize(默认 20,上限 100)、search(可选)。\n * 可通过 `.extend()` 扩展业务字段。\n *\n * @example\n * ```ts\n * // 直接使用\n * const { page, pageSize, search } = kit.validate.query(url, PaginationQuerySchema)\n *\n * // 扩展业务字段\n * const ListUsersSchema = PaginationQuerySchema.extend({\n * enabled: z.enum(['true', 'false']).transform(v => v === 'true').optional(),\n * })\n * ```\n */\nexport const PaginationQuerySchema = zod.object({\n page: zod.coerce.number().int().min(1).default(1),\n pageSize: zod.coerce.number().int().min(1).max(MAX_PAGE_SIZE).default(20),\n search: zod.string().optional(),\n})\n","/**\n * @h-ai/kit — 服务对象主入口\n *\n * SvelteKit 集成模块的统一命名空间出口。 所有功能通过 kit 对象访问:\n * @module kit-main\n */\n\nimport { createKitClient, installBrowserTransport, installBrowserTransportFetch } from './client/kit-client.js'\nimport { defineCrud } from './crud/kit-crud.js'\nimport { hasPermission, requirePermission } from './guards/kit-permission.js'\nimport { createHandle, sequence } from './hooks/kit-handle.js'\nimport {\n clearBrowserToken,\n createTokenStore,\n login,\n loginWithApiKey,\n loginWithLdap,\n loginWithOtp,\n logout,\n registerAndLogin,\n setBrowserToken,\n} from './kit-auth.js'\nimport { KitConfigSchema, resolveKitConfig, resolveKitTransportConfig } from './kit-config.js'\nimport { handler } from './kit-handler.js'\nimport { setAllModulesLocale } from './kit-i18n.js'\nimport { badRequest, conflict, created, error, forbidden, fromError, fromResult, internalError, noContent, notFound, ok, redirect, unauthorized, validationError } from './kit-response.js'\nimport { IdParamSchema, PaginationQuerySchema, validateFormOrFail, validateParamsOrFail, validateQueryOrFail } from './kit-validation.js'\n\nexport { KitConfigSchema, resolveKitConfig, resolveKitTransportConfig }\n\n/**\n * Kit 模块统一出口。\n *\n * 作为纯工具模块,kit 不需要 init/close 生命周期,\n * 所有功能均为无状态工厂函数或工具函数。\n */\nexport const kit = {\n // ─── Handle Hook ───\n\n /** 创建 SvelteKit Handle Hook(含 auth / logging / rateLimit 内置配置) */\n createHandle,\n /** 组合多个 Handle */\n sequence,\n /** API Handler 包装器(自动错误边界) */\n handler,\n\n // ─── 路由守卫 ───\n\n guard: {\n /** 要求权限,不满足时 throw Response(SvelteKit 控制流) */\n require: requirePermission,\n /** 检查会话是否具有指定权限(布尔) */\n check: hasPermission,\n },\n\n // ─── API 响应 ───\n\n response: {\n /** 200 成功 */\n ok,\n /** 201 创建成功 */\n created,\n /** 204 无内容 */\n noContent,\n /** 自定义错误响应 */\n error,\n /** 400 BadRequest */\n badRequest,\n /** 401 Unauthorized */\n unauthorized,\n /** 403 Forbidden */\n forbidden,\n /** 404 NotFound */\n notFound,\n /** 409 Conflict */\n conflict,\n /** 422 验证错误 */\n validationError,\n /** 500 InternalError */\n internalError,\n /** 重定向 */\n redirect,\n /** 将 HaiResult<T> 转为标准 API Response(支持 httpStatusMap) */\n fromResult,\n /** 将模块错误码映射为标准 HTTP Response */\n fromError,\n },\n\n // ─── 验证 ───\n\n validate: {\n /** 验证请求体(JSON/表单),失败 throw Response */\n body: validateFormOrFail,\n /** 验证查询参数,失败 throw Response */\n query: validateQueryOrFail,\n /** 验证路径参数,失败 throw Response */\n params: validateParamsOrFail,\n /** 路径参数 id Schema({id: string}) */\n IdParamSchema,\n /** 通用分页查询 Schema(page / pageSize / search) */\n PaginationQuerySchema,\n },\n\n // ─── 客户端工具 ───\n\n client: {\n /** 创建统一客户端(CSRF + 传输加密透明合并) */\n create: createKitClient,\n /**\n * 用解析后的 {@link KitConfig} 一键安装浏览器端传输加密\n * (应用层推荐入口;内部预热 crypto 并调用 installBrowserTransportFetch)\n */\n installBrowserTransport,\n /** 底层入口:直接传 transport 配置安装浏览器全局 fetch 包装 */\n installBrowserTransportFetch,\n },\n\n // ─── 认证工具 ───\n\n auth: {\n /** 服务端登录(密码):内部调用 iam.auth.login + 自动写入 Token Cookie */\n login,\n /** 服务端登录(OTP 验证码):内部调用 iam.auth.loginWithOtp + 自动写入 Token Cookie */\n loginWithOtp,\n /** 服务端登录(LDAP):内部调用 iam.auth.loginWithLdap + 自动写入 Token Cookie */\n loginWithLdap,\n /** 服务端登录(API Key):内部调用 iam.auth.loginWithApiKey + 自动写入 Token Cookie */\n loginWithApiKey,\n /** 服务端注册并登录:内部调用 iam.auth.registerAndLogin + 自动写入 Token Cookie */\n registerAndLogin,\n /** 服务端登出:内部调用 iam.auth.logout + 清除 Token Cookie */\n logout,\n /** 写入浏览器端 Access Token(客户端 login/register 用) */\n setBrowserToken,\n /** 清除浏览器端 Access Token(客户端 logout 用) */\n clearBrowserToken,\n /** 创建浏览器端 Token 存储器(自定义 key 时使用) */\n createTokenStore,\n },\n\n // ─── CRUD ───\n\n crud: {\n /** 定义 CRUD 资源(声明式配置 → 操作对象) */\n define: defineCrud,\n },\n\n // ─── i18n ───\n\n i18n: {\n /** 统一设置所有 hai 模块的默认语言 */\n setLocale: setAllModulesLocale,\n },\n}\n"]}
@@ -500,7 +500,8 @@ interface HookCryptoConfig {
500
500
  * Cookie 加密密钥(32 字符十六进制 = 16 字节 SM4 密钥)
501
501
  *
502
502
  * 如不提供,则从环境变量 `HAI_KIT_COOKIE_KEY` 读取。
503
- * 两者都未设置时 Cookie 加密不生效并输出警告。
503
+ * 配置了 `encryptedCookies` 但两者都未设置时,`kit.createHandle()` 会立即抛出配置错误,
504
+ * 避免受保护 Cookie 静默降级为明文。
504
505
  */
505
506
  cookieEncryptionKey?: string;
506
507
  }
@@ -1,5 +1,5 @@
1
1
  import { RequestEvent, RequestHandler } from '@sveltejs/kit';
2
- import { f as HandleA2AOperations, h as HandleConfig } from '../../kit-types-BmWNlWpa.js';
2
+ import { f as HandleA2AOperations, h as HandleConfig } from '../../kit-types-BIkoLpfq.js';
3
3
  import '@h-ai/crypto';
4
4
  import '@h-ai/iam';
5
5
 
@@ -1,7 +1,7 @@
1
1
  import { RequestEvent, Cookies } from '@sveltejs/kit';
2
2
  import { CryptoFunctions, TransportKeyStore } from '@h-ai/crypto';
3
3
  export { EncryptedPayload, TransportEncryptionManager, TransportKeyPair } from '@h-ai/crypto';
4
- import { M as Middleware } from '../../kit-types-BmWNlWpa.js';
4
+ import { M as Middleware } from '../../kit-types-BIkoLpfq.js';
5
5
  import '@h-ai/iam';
6
6
 
7
7
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/kit",
3
3
  "type": "module",
4
- "version": "0.1.0-alpha.36",
4
+ "version": "0.1.0-alpha.38",
5
5
  "description": "Hai Framework SvelteKit integration module.",
6
6
  "license": "Apache-2.0",
7
7
  "exports": {
@@ -56,9 +56,9 @@
56
56
  },
57
57
  "dependencies": {
58
58
  "zod": "^4.4.3",
59
- "@h-ai/core": "0.1.0-alpha.36",
60
- "@h-ai/crypto": "0.1.0-alpha.36",
61
- "@h-ai/iam": "0.1.0-alpha.36"
59
+ "@h-ai/crypto": "0.1.0-alpha.38",
60
+ "@h-ai/iam": "0.1.0-alpha.38",
61
+ "@h-ai/core": "0.1.0-alpha.38"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@sveltejs/kit": "^2.61.1",