@enkaku/server 0.12.3 → 0.13.0

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.
@@ -1,5 +1,12 @@
1
1
  import type { SignedToken } from '@enkaku/token';
2
- export type ProcedureAccessRecord = Record<string, boolean | Array<string>>;
2
+ export type EncryptionPolicy = 'required' | 'optional' | 'none';
3
+ export type ProcedureAccessConfig = {
4
+ allow?: boolean | Array<string>;
5
+ encryption?: EncryptionPolicy;
6
+ };
7
+ export type ProcedureAccessValue = boolean | Array<string> | ProcedureAccessConfig;
8
+ export type ProcedureAccessRecord = Record<string, ProcedureAccessValue>;
9
+ export declare function resolveEncryptionPolicy(procedure: string, record: ProcedureAccessRecord | undefined, globalPolicy: EncryptionPolicy): EncryptionPolicy;
3
10
  export type ProcedureAccessPayload = {
4
11
  iss: string;
5
12
  sub?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"access-control.d.ts","sourceRoot":"","sources":["../src/access-control.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;AAE3E,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,EAC1C,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
1
+ {"version":3,"file":"access-control.d.ts","sourceRoot":"","sources":["../src/access-control.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAE/D,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,qBAAqB,CAAA;AAElF,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;AAgBxE,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,qBAAqB,GAAG,SAAS,EACzC,YAAY,EAAE,gBAAgB,GAC7B,gBAAgB,CAYlB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,EAC1C,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
@@ -1,23 +1,49 @@
1
1
  import { assertNonExpired, checkCapability, hasPartsMatch } from '@enkaku/capability';
2
+ function getAllowValue(access) {
3
+ if (typeof access === 'boolean' || Array.isArray(access)) {
4
+ return access;
5
+ }
6
+ return access.allow ?? false;
7
+ }
8
+ function getEncryptionPolicy(access) {
9
+ if (typeof access === 'boolean' || Array.isArray(access)) {
10
+ return undefined;
11
+ }
12
+ return access.encryption;
13
+ }
14
+ export function resolveEncryptionPolicy(procedure, record, globalPolicy) {
15
+ if (record != null) {
16
+ for (const [pattern, accessValue] of Object.entries(record)){
17
+ if (hasPartsMatch(procedure, pattern)) {
18
+ const procedurePolicy = getEncryptionPolicy(accessValue);
19
+ if (procedurePolicy != null) {
20
+ return procedurePolicy;
21
+ }
22
+ }
23
+ }
24
+ }
25
+ return globalPolicy;
26
+ }
2
27
  export async function checkProcedureAccess(serverID, record, token, atTime) {
3
28
  const payload = token.payload;
4
29
  if (payload.prc == null) {
5
30
  throw new Error('No procedure to check');
6
31
  }
7
- for (const [procedure, access] of Object.entries(record)){
32
+ for (const [procedure, accessValue] of Object.entries(record)){
8
33
  if (hasPartsMatch(payload.prc, procedure)) {
9
- if (access === true) {
34
+ const allow = getAllowValue(accessValue);
35
+ if (allow === true) {
10
36
  // Procedure can be publicly accessed
11
37
  return;
12
38
  }
13
- if (access === false) {
39
+ if (allow === false) {
14
40
  continue;
15
41
  }
16
- if (access.includes(payload.iss)) {
42
+ if (allow.includes(payload.iss)) {
17
43
  // Issuer is allowed directly
18
44
  return;
19
45
  }
20
- if (payload.sub == null || !access.includes(payload.sub)) {
46
+ if (payload.sub == null || !allow.includes(payload.sub)) {
21
47
  continue;
22
48
  }
23
49
  try {
package/lib/error.d.ts CHANGED
@@ -1,4 +1,14 @@
1
1
  import type { ErrorReplyPayload } from '@enkaku/protocol';
2
+ /**
3
+ * Error codes:
4
+ * - EK01: Handler execution failed
5
+ * - EK02: Access denied (authorization failure)
6
+ * - EK03: Server controller limit reached
7
+ * - EK04: Server handler concurrency limit reached
8
+ * - EK05: Request timeout (controller expired)
9
+ * - EK06: Message exceeds maximum size
10
+ * - EK07: Encryption required but message is not encrypted
11
+ */
2
12
  export type HandlerErrorParams<Code extends string = string, Data extends Record<string, unknown> = Record<string, unknown>> = {
3
13
  cause?: unknown;
4
14
  code: Code;
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,MAAM,MAAM,kBAAkB,CAC5B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5D;IACF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,YAAY,CACvB,IAAI,SAAS,MAAM,EACnB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC9D,SAAQ,KAAK;;IACb,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7F,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,GACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;gBAWf,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC;IAOlD,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;CAStD"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD;;;;;;;;;GASG;AAEH,MAAM,MAAM,kBAAkB,CAC5B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5D;IACF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,YAAY,CACvB,IAAI,SAAS,MAAM,EACnB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC9D,SAAQ,KAAK;;IACb,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7F,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,GACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;gBAWf,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC;IAOlD,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;CAStD"}
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/handlers/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAGV,cAAc,EAGf,MAAM,aAAa,CAAA;AAGpB,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DvB"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/handlers/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAGV,cAAc,EAGf,MAAM,aAAa,CAAA;AAGpB,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEvB"}
@@ -46,6 +46,17 @@ export function handleChannel(ctx, msg) {
46
46
  signal: controller.signal,
47
47
  writable: receiveStream.writable
48
48
  };
49
- // @ts-expect-error context and handler types
50
- return executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
49
+ // Wrap execution to ensure stream cleanup on handler crash
50
+ return (async ()=>{
51
+ try {
52
+ // @ts-expect-error context and handler types
53
+ await executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
54
+ } finally{
55
+ try {
56
+ await receiveStream.writable.close();
57
+ } catch {
58
+ // Stream may already be closed
59
+ }
60
+ }
61
+ })();
51
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/handlers/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,kBAAkB,EAClB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAA;AAG7E,MAAM,MAAM,eAAe,CACzB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAElE,wBAAgB,YAAY,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCjG"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/handlers/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,kBAAkB,EAClB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAA;AAG7E,MAAM,MAAM,eAAe,CACzB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAElE,wBAAgB,YAAY,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDjG"}
@@ -32,6 +32,17 @@ export function handleStream(ctx, msg) {
32
32
  signal: controller.signal,
33
33
  writable: receiveStream.writable
34
34
  };
35
- // @ts-expect-error context and handler types
36
- return executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
35
+ // Wrap execution to ensure stream cleanup on handler crash
36
+ return (async ()=>{
37
+ try {
38
+ // @ts-expect-error context and handler types
39
+ await executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
40
+ } finally{
41
+ try {
42
+ await receiveStream.writable.close();
43
+ } catch {
44
+ // Stream may already be closed
45
+ }
46
+ }
47
+ })();
37
48
  }
package/lib/index.d.ts CHANGED
@@ -9,7 +9,9 @@
9
9
  *
10
10
  * @module server
11
11
  */
12
- export type { ProcedureAccessRecord } from './access-control.js';
12
+ export type { EncryptionPolicy, ProcedureAccessConfig, ProcedureAccessRecord, ProcedureAccessValue, } from './access-control.js';
13
+ export { resolveEncryptionPolicy } from './access-control.js';
14
+ export { createResourceLimiter, DEFAULT_RESOURCE_LIMITS, type ResourceLimiter, type ResourceLimits, } from './limits.js';
13
15
  export { type ServeParams, Server, type ServerParams, serve } from './server.js';
14
16
  export type { ChannelHandler, ChannelHandlerContext, EventHandler, EventHandlerContext, HandlerReturn, ProcedureHandlers, RequestHandler, RequestHandlerContext, ServerEmitter, ServerEvents, StreamHandler, StreamHandlerContext, } from './types.js';
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAChF,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAChF,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAA"}
package/lib/index.js CHANGED
@@ -8,4 +8,6 @@
8
8
  * ```
9
9
  *
10
10
  * @module server
11
- */ export { Server, serve } from './server.js';
11
+ */ export { resolveEncryptionPolicy } from './access-control.js';
12
+ export { createResourceLimiter, DEFAULT_RESOURCE_LIMITS } from './limits.js';
13
+ export { Server, serve } from './server.js';
@@ -0,0 +1,26 @@
1
+ export type ResourceLimits = {
2
+ /** Maximum number of concurrent controllers (in-flight requests). Default: 10000 */
3
+ maxControllers: number;
4
+ /** Maximum number of concurrent handler executions. Default: 100 */
5
+ maxConcurrentHandlers: number;
6
+ /** Controller timeout in milliseconds. Default: 300000 (5 min) */
7
+ controllerTimeoutMs: number;
8
+ /** Cleanup timeout in milliseconds when disposing. Default: 30000 (30 sec) */
9
+ cleanupTimeoutMs: number;
10
+ /** Maximum size in bytes for any individual message payload. Default: 10485760 (10 MB) */
11
+ maxMessageSize: number;
12
+ };
13
+ export declare const DEFAULT_RESOURCE_LIMITS: ResourceLimits;
14
+ export type ResourceLimiter = {
15
+ limits: ResourceLimits;
16
+ controllerCount: number;
17
+ activeHandlers: number;
18
+ canAddController: () => boolean;
19
+ addController: (rid: string) => void;
20
+ removeController: (rid: string) => void;
21
+ getExpiredControllers: () => Array<string>;
22
+ acquireHandler: () => boolean;
23
+ releaseHandler: () => void;
24
+ };
25
+ export declare function createResourceLimiter(options?: Partial<ResourceLimits>): ResourceLimiter;
26
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,oFAAoF;IACpF,cAAc,EAAE,MAAM,CAAA;IACtB,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAA;IAC7B,kEAAkE;IAClE,mBAAmB,EAAE,MAAM,CAAA;IAC3B,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAA;IACxB,0FAA0F;IAC1F,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,cAMrC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,MAAM,OAAO,CAAA;IAC/B,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,qBAAqB,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1C,cAAc,EAAE,MAAM,OAAO,CAAA;IAC7B,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B,CAAA;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,eAAe,CAiDxF"}
package/lib/limits.js ADDED
@@ -0,0 +1,56 @@
1
+ export const DEFAULT_RESOURCE_LIMITS = {
2
+ maxControllers: 10000,
3
+ maxConcurrentHandlers: 100,
4
+ controllerTimeoutMs: 300000,
5
+ cleanupTimeoutMs: 30000,
6
+ maxMessageSize: 10485760
7
+ };
8
+ export function createResourceLimiter(options) {
9
+ const limits = {
10
+ ...DEFAULT_RESOURCE_LIMITS,
11
+ ...options
12
+ };
13
+ const controllers = new Map() // rid -> timestamp
14
+ ;
15
+ let handlerCount = 0;
16
+ return {
17
+ limits,
18
+ get controllerCount () {
19
+ return controllers.size;
20
+ },
21
+ get activeHandlers () {
22
+ return handlerCount;
23
+ },
24
+ canAddController () {
25
+ return controllers.size < limits.maxControllers;
26
+ },
27
+ addController (rid) {
28
+ controllers.set(rid, Date.now());
29
+ },
30
+ removeController (rid) {
31
+ controllers.delete(rid);
32
+ },
33
+ getExpiredControllers () {
34
+ const now = Date.now();
35
+ const expired = [];
36
+ for (const [rid, timestamp] of controllers){
37
+ if (now - timestamp > limits.controllerTimeoutMs) {
38
+ expired.push(rid);
39
+ }
40
+ }
41
+ return expired;
42
+ },
43
+ acquireHandler () {
44
+ if (handlerCount >= limits.maxConcurrentHandlers) {
45
+ return false;
46
+ }
47
+ handlerCount++;
48
+ return true;
49
+ },
50
+ releaseHandler () {
51
+ if (handlerCount > 0) {
52
+ handlerCount--;
53
+ }
54
+ }
55
+ };
56
+ }
package/lib/server.d.ts CHANGED
@@ -2,9 +2,11 @@ import { Disposer } from '@enkaku/async';
2
2
  import { type Logger } from '@enkaku/log';
3
3
  import { type AnyClientMessageOf, type ProtocolDefinition, type ServerTransportOf } from '@enkaku/protocol';
4
4
  import { type Validator } from '@enkaku/schema';
5
- import { type ProcedureAccessRecord } from './access-control.js';
5
+ import { type Identity } from '@enkaku/token';
6
+ import { type EncryptionPolicy, type ProcedureAccessRecord } from './access-control.js';
7
+ import { type ResourceLimiter, type ResourceLimits } from './limits.js';
6
8
  import type { ProcedureHandlers, ServerEmitter } from './types.js';
7
- export type AccessControlParams = {
9
+ export type AccessControlParams = ({
8
10
  public: true;
9
11
  serverID?: string;
10
12
  access?: ProcedureAccessRecord;
@@ -12,10 +14,13 @@ export type AccessControlParams = {
12
14
  public: false;
13
15
  serverID: string;
14
16
  access: ProcedureAccessRecord;
17
+ }) & {
18
+ encryptionPolicy?: EncryptionPolicy;
15
19
  };
16
20
  export type HandleMessagesParams<Protocol extends ProtocolDefinition> = AccessControlParams & {
17
21
  events: ServerEmitter;
18
22
  handlers: ProcedureHandlers<Protocol>;
23
+ limiter: ResourceLimiter;
19
24
  logger: Logger;
20
25
  signal: AbortSignal;
21
26
  transport: ServerTransportOf<Protocol>;
@@ -23,8 +28,10 @@ export type HandleMessagesParams<Protocol extends ProtocolDefinition> = AccessCo
23
28
  };
24
29
  export type ServerParams<Protocol extends ProtocolDefinition> = {
25
30
  access?: ProcedureAccessRecord;
31
+ encryptionPolicy?: EncryptionPolicy;
26
32
  handlers: ProcedureHandlers<Protocol>;
27
- id?: string;
33
+ identity?: Identity;
34
+ limits?: Partial<ResourceLimits>;
28
35
  logger?: Logger;
29
36
  protocol?: Protocol;
30
37
  public?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EACL,KAAK,kBAAkB,EAGvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAMlF,OAAO,KAAK,EAIV,iBAAiB,EACjB,aAAa,EAEd,MAAM,YAAY,CAAA;AAQnB,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,qBAAqB,CAAA;CAAE,GACnE;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAA;CAAE,CAAA;AAEtE,MAAM,MAAM,oBAAoB,CAAC,QAAQ,SAAS,kBAAkB,IAAI,mBAAmB,GAAG;IAC5F,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACtC,SAAS,CAAC,EAAE,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAA;CACpD,CAAA;AAyJD,MAAM,MAAM,YAAY,CAAC,QAAQ,SAAS,kBAAkB,IAAI;IAC9D,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAEjG,qBAAa,MAAM,CAAC,QAAQ,SAAS,kBAAkB,CAAE,SAAQ,QAAQ;;gBAS3D,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC;IAgD1C,IAAI,MAAM,IAAI,aAAa,CAE1B;IAED,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;CAiC3F;AAED,MAAM,MAAM,WAAW,CAAC,QAAQ,SAAS,kBAAkB,IAAI,IAAI,CACjE,YAAY,CAAC,QAAQ,CAAC,EACtB,YAAY,CACb,GAAG;IACF,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;CACvC,CAAA;AAED,wBAAgB,KAAK,CAAC,QAAQ,SAAS,kBAAkB,EACvD,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,GAC5B,MAAM,CAAC,QAAQ,CAAC,CAGlB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EACL,KAAK,kBAAkB,EAGvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAEL,KAAK,QAAQ,EAId,MAAM,eAAe,CAAA;AAEtB,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAE3B,MAAM,qBAAqB,CAAA;AAM5B,OAAO,EAAyB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,KAAK,EAIV,iBAAiB,EACjB,aAAa,EAEd,MAAM,YAAY,CAAA;AAQnB,MAAM,MAAM,mBAAmB,GAAG,CAC9B;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,qBAAqB,CAAA;CAAE,GACnE;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAA;CAAE,CACrE,GAAG;IAAE,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAA;AAE3C,MAAM,MAAM,oBAAoB,CAAC,QAAQ,SAAS,kBAAkB,IAAI,mBAAmB,GAAG;IAC5F,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,OAAO,EAAE,eAAe,CAAA;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACtC,SAAS,CAAC,EAAE,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAA;CACpD,CAAA;AA6SD,MAAM,MAAM,YAAY,CAAC,QAAQ,SAAS,kBAAkB,IAAI;IAC9D,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAEjG,qBAAa,MAAM,CAAC,QAAQ,SAAS,kBAAkB,CAAE,SAAQ,QAAQ;;gBAU3D,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC;IAgF1C,IAAI,MAAM,IAAI,aAAa,CAE1B;IAED,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;CAoC3F;AAED,MAAM,MAAM,WAAW,CAAC,QAAQ,SAAS,kBAAkB,IAAI,IAAI,CACjE,YAAY,CAAC,QAAQ,CAAC,EACtB,YAAY,CACb,GAAG;IACF,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;CACvC,CAAA;AAED,wBAAgB,KAAK,CAAC,QAAQ,SAAS,kBAAkB,EACvD,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,GAC5B,MAAM,CAAC,QAAQ,CAAC,CAGlB"}
package/lib/server.js CHANGED
@@ -4,14 +4,15 @@ import { getEnkakuLogger } from '@enkaku/log';
4
4
  import { createClientMessageSchema } from '@enkaku/protocol';
5
5
  import { createValidator, ValidationError } from '@enkaku/schema';
6
6
  import { createUnsignedToken, isSignedToken } from '@enkaku/token';
7
- import { checkClientToken } from './access-control.js';
7
+ import { checkClientToken, resolveEncryptionPolicy } from './access-control.js';
8
8
  import { HandlerError } from './error.js';
9
9
  import { handleChannel } from './handlers/channel.js';
10
10
  import { handleEvent } from './handlers/event.js';
11
11
  import { handleRequest } from './handlers/request.js';
12
12
  import { handleStream } from './handlers/stream.js';
13
+ import { createResourceLimiter } from './limits.js';
13
14
  async function handleMessages(params) {
14
- const { events, handlers, logger, signal, transport, validator } = params;
15
+ const { events, handlers, limiter, logger, signal, transport, validator } = params;
15
16
  const controllers = Object.create(null);
16
17
  const context = {
17
18
  controllers,
@@ -21,8 +22,34 @@ async function handleMessages(params) {
21
22
  send: (payload)=>transport.write(createUnsignedToken(payload))
22
23
  };
23
24
  const running = Object.create(null);
25
+ const encoder = new TextEncoder();
26
+ // Periodic cleanup of expired controllers
27
+ const cleanupInterval = setInterval(()=>{
28
+ const expired = limiter.getExpiredControllers();
29
+ for (const rid of expired){
30
+ const controller = controllers[rid];
31
+ if (controller != null) {
32
+ controller.abort('Timeout');
33
+ const error = new HandlerError({
34
+ code: 'EK05',
35
+ message: 'Request timeout'
36
+ });
37
+ context.send(error.toPayload(rid));
38
+ events.emit('handlerTimeout', {
39
+ rid
40
+ });
41
+ limiter.removeController(rid);
42
+ limiter.releaseHandler();
43
+ delete controllers[rid];
44
+ delete running[rid];
45
+ } else {
46
+ limiter.removeController(rid);
47
+ }
48
+ }
49
+ }, Math.min(limiter.limits.controllerTimeoutMs, 10000));
24
50
  const disposer = new Disposer({
25
51
  dispose: async ()=>{
52
+ clearInterval(cleanupInterval);
26
53
  const interruption = new DisposeInterruption();
27
54
  // Abort all currently running handlers
28
55
  for (const controller of Object.values(controllers)){
@@ -54,8 +81,43 @@ async function handleMessages(params) {
54
81
  return result.value;
55
82
  } : (message)=>message;
56
83
  function processHandler(message, handle) {
84
+ const rid = message.payload.typ === 'event' ? Math.random().toString(36).slice(2) : message.payload.rid;
85
+ // Check controller limit
86
+ if (!limiter.canAddController()) {
87
+ const error = new HandlerError({
88
+ code: 'EK03',
89
+ message: 'Server controller limit reached'
90
+ });
91
+ if (message.payload.typ !== 'event') {
92
+ context.send(error.toPayload(rid));
93
+ }
94
+ events.emit('handlerError', {
95
+ error,
96
+ payload: message.payload
97
+ });
98
+ return;
99
+ }
100
+ // Check handler concurrency (synchronous fast path)
101
+ if (limiter.activeHandlers >= limiter.limits.maxConcurrentHandlers) {
102
+ const error = new HandlerError({
103
+ code: 'EK04',
104
+ message: 'Server handler limit reached'
105
+ });
106
+ if (message.payload.typ !== 'event') {
107
+ context.send(error.toPayload(rid));
108
+ }
109
+ events.emit('handlerError', {
110
+ error,
111
+ payload: message.payload
112
+ });
113
+ return;
114
+ }
115
+ limiter.addController(rid);
116
+ limiter.acquireHandler();
57
117
  const returned = handle();
58
118
  if (returned instanceof Error) {
119
+ limiter.removeController(rid);
120
+ limiter.releaseHandler();
59
121
  events.emit('handlerError', {
60
122
  error: HandlerError.from(returned, {
61
123
  code: 'EK01'
@@ -63,14 +125,52 @@ async function handleMessages(params) {
63
125
  payload: message.payload
64
126
  });
65
127
  } else {
66
- const id = message.payload.typ === 'event' ? Math.random().toString(36).slice(2) : message.payload.rid;
67
- running[id] = returned;
128
+ running[rid] = returned;
68
129
  returned.then(()=>{
69
- delete running[id];
130
+ // Guard against double-release if timeout cleanup already handled this rid
131
+ if (running[rid] === returned) {
132
+ limiter.removeController(rid);
133
+ limiter.releaseHandler();
134
+ delete running[rid];
135
+ }
70
136
  });
71
137
  }
72
138
  }
73
- const process = params.public ? processHandler : async (message, handle)=>{
139
+ function checkMessageEncryption(message) {
140
+ const globalPolicy = params.encryptionPolicy ?? 'none';
141
+ if (globalPolicy === 'none') {
142
+ return true;
143
+ }
144
+ const procedure = message.payload.prc;
145
+ const effectivePolicy = procedure != null ? resolveEncryptionPolicy(procedure, params.access, globalPolicy) : globalPolicy;
146
+ if (effectivePolicy !== 'required') {
147
+ return true;
148
+ }
149
+ // Detect if message was encrypted: jwe-in-jws mode has a 'jwe' field in the payload
150
+ const payload = message.payload;
151
+ return 'jwe' in payload && typeof payload.jwe === 'string';
152
+ }
153
+ function handleEncryptionViolation(message) {
154
+ const error = new HandlerError({
155
+ code: 'EK07',
156
+ message: 'Encryption required but message is not encrypted'
157
+ });
158
+ if (message.payload.typ === 'event') {
159
+ events.emit('handlerError', {
160
+ error,
161
+ payload: message.payload
162
+ });
163
+ } else {
164
+ context.send(error.toPayload(message.payload.rid));
165
+ }
166
+ }
167
+ const process = params.public ? (message, handle)=>{
168
+ if (!checkMessageEncryption(message)) {
169
+ handleEncryptionViolation(message);
170
+ return;
171
+ }
172
+ processHandler(message, handle);
173
+ } : async (message, handle)=>{
74
174
  try {
75
175
  if (!params.public) {
76
176
  if (!isSignedToken(message)) {
@@ -85,6 +185,10 @@ async function handleMessages(params) {
85
185
  message: cause.message ?? 'Access denied'
86
186
  });
87
187
  if (message.payload.typ === 'event') {
188
+ events.emit('eventAuthError', {
189
+ error,
190
+ payload: message.payload
191
+ });
88
192
  events.emit('handlerError', {
89
193
  error,
90
194
  payload: message.payload
@@ -94,6 +198,10 @@ async function handleMessages(params) {
94
198
  }
95
199
  return;
96
200
  }
201
+ if (!checkMessageEncryption(message)) {
202
+ handleEncryptionViolation(message);
203
+ return;
204
+ }
97
205
  processHandler(message, handle);
98
206
  };
99
207
  async function handleNext() {
@@ -104,6 +212,22 @@ async function handleMessages(params) {
104
212
  }
105
213
  const msg = processMessage(next.value);
106
214
  if (msg != null) {
215
+ const msgSize = encoder.encode(JSON.stringify(msg.payload)).byteLength;
216
+ if (msgSize > limiter.limits.maxMessageSize) {
217
+ const error = new HandlerError({
218
+ code: 'EK06',
219
+ message: 'Message exceeds maximum size'
220
+ });
221
+ if ('rid' in msg.payload && msg.payload.rid != null) {
222
+ context.send(error.toPayload(msg.payload.rid));
223
+ }
224
+ events.emit('handlerError', {
225
+ error,
226
+ payload: msg.payload
227
+ });
228
+ handleNext();
229
+ return;
230
+ }
107
231
  switch(msg.payload.typ){
108
232
  case 'abort':
109
233
  controllers[msg.payload.rid]?.abort(msg.payload.rsn);
@@ -129,7 +253,35 @@ async function handleMessages(params) {
129
253
  case 'send':
130
254
  {
131
255
  const controller = controllers[msg.payload.rid];
132
- controller?.writer.write(msg.payload.val);
256
+ if (controller == null) {
257
+ logger.debug('received send for unknown channel {rid}', {
258
+ rid: msg.payload.rid
259
+ });
260
+ break;
261
+ }
262
+ // In non-public mode, validate send messages
263
+ if (!params.public) {
264
+ if (!isSignedToken(msg)) {
265
+ const error = new HandlerError({
266
+ code: 'EK02',
267
+ message: 'Channel send message must be signed'
268
+ });
269
+ context.send(error.toPayload(msg.payload.rid));
270
+ break;
271
+ }
272
+ try {
273
+ await checkClientToken(params.serverID, params.access, msg);
274
+ } catch (cause) {
275
+ const error = new HandlerError({
276
+ cause,
277
+ code: 'EK02',
278
+ message: cause.message ?? 'Send authorization denied'
279
+ });
280
+ context.send(error.toPayload(msg.payload.rid));
281
+ break;
282
+ }
283
+ }
284
+ controller.writer.write(msg.payload.val);
133
285
  break;
134
286
  }
135
287
  case 'stream':
@@ -151,6 +303,7 @@ export class Server extends Disposer {
151
303
  #events;
152
304
  #handlers;
153
305
  #handling = [];
306
+ #limiter;
154
307
  #logger;
155
308
  #validator;
156
309
  constructor(params){
@@ -158,40 +311,63 @@ export class Server extends Disposer {
158
311
  dispose: async ()=>{
159
312
  // Signal messages handler to stop execution and run cleanup logic
160
313
  this.#abortController.abort();
161
- // Dispose of all handling transports
162
- await Promise.all(this.#handling.map(async (handling)=>{
163
- // Wait until all handlers are done - they might still need to flush messages to the transport
164
- await handling.done;
165
- // Dispose transport
166
- await handling.transport.dispose();
167
- }));
314
+ const cleanupTimeout = this.#limiter.limits.cleanupTimeoutMs;
315
+ const timeoutPromise = new Promise((resolve)=>{
316
+ setTimeout(resolve, cleanupTimeout);
317
+ });
318
+ // Race between graceful cleanup and timeout
319
+ const gracefulDone = await Promise.race([
320
+ Promise.all(this.#handling.map(async (handling)=>{
321
+ // Wait until all handlers are done - they might still need to flush messages to the transport
322
+ await handling.done;
323
+ // Dispose transport
324
+ await handling.transport.dispose();
325
+ })).then(()=>true),
326
+ timeoutPromise.then(()=>false)
327
+ ]);
328
+ // Force dispose any remaining transports only if timed out
329
+ if (!gracefulDone) {
330
+ for (const handling of this.#handling){
331
+ try {
332
+ await handling.transport.dispose();
333
+ } catch {
334
+ // Ignore errors during forced cleanup
335
+ }
336
+ }
337
+ }
168
338
  },
169
339
  signal: params.signal
170
340
  });
171
341
  this.#abortController = new AbortController();
172
342
  this.#events = new EventEmitter();
173
343
  this.#handlers = params.handlers;
344
+ const serverID = params.identity?.id;
174
345
  this.#logger = params.logger ?? getEnkakuLogger('server', {
175
- serverID: params.id ?? crypto.randomUUID()
346
+ serverID: serverID ?? crypto.randomUUID()
176
347
  });
177
- if (params.id == null) {
348
+ if (serverID == null) {
178
349
  if (params.public) {
179
350
  this.#accessControl = {
180
351
  public: true,
181
- access: params.access
352
+ access: params.access,
353
+ encryptionPolicy: params.encryptionPolicy
182
354
  };
183
355
  } else {
184
- throw new Error('Invalid server parameters: either the server "id" must be provided or the "public" parameter must be set to true');
356
+ throw new Error('Invalid server parameters: either the server "identity" must be provided or the "public" parameter must be set to true');
185
357
  }
186
358
  } else {
187
359
  this.#accessControl = {
188
360
  public: !!params.public,
189
- serverID: params.id,
190
- access: params.access ?? {}
361
+ serverID,
362
+ access: params.access ?? {},
363
+ encryptionPolicy: params.encryptionPolicy
191
364
  };
192
365
  }
366
+ this.#limiter = createResourceLimiter(params.limits);
193
367
  if (params.protocol != null) {
194
368
  this.#validator = createValidator(createClientMessageSchema(params.protocol));
369
+ } else {
370
+ this.#logger.warn('No protocol provided: message validation is disabled. Pass a protocol definition to enable runtime type checking.');
195
371
  }
196
372
  for (const transport of params.transports ?? []){
197
373
  this.handle(transport);
@@ -206,11 +382,13 @@ export class Server extends Disposer {
206
382
  const logger = options.logger ?? this.#logger.getChild('handler').with({
207
383
  transportID: crypto.randomUUID()
208
384
  });
385
+ const encryptionPolicy = this.#accessControl.encryptionPolicy;
209
386
  let accessControl;
210
387
  if (publicAccess) {
211
388
  accessControl = {
212
389
  public: true,
213
- access
390
+ access,
391
+ encryptionPolicy
214
392
  };
215
393
  } else {
216
394
  const serverID = this.#accessControl.serverID;
@@ -220,12 +398,14 @@ export class Server extends Disposer {
220
398
  accessControl = {
221
399
  public: false,
222
400
  serverID,
223
- access
401
+ access,
402
+ encryptionPolicy
224
403
  };
225
404
  }
226
405
  const done = handleMessages({
227
406
  events: this.#events,
228
407
  handlers: this.#handlers,
408
+ limiter: this.#limiter,
229
409
  logger,
230
410
  signal: this.#abortController.signal,
231
411
  transport,
package/lib/types.d.ts CHANGED
@@ -36,6 +36,10 @@ export type ReceiveType<Protocol extends ProtocolDefinition, Procedure extends k
36
36
  export type ResultType<Protocol extends ProtocolDefinition, Procedure extends keyof Protocol & string> = Protocol[Procedure] extends AnyRequestProcedureDefinition ? DataOf<Protocol[Procedure]['result']> : never;
37
37
  export type SendType<Protocol extends ProtocolDefinition, Procedure extends keyof Protocol & string> = Protocol[Procedure] extends ChannelProcedureDefinition ? DataOf<Protocol[Procedure]['send']> : never;
38
38
  export type ServerEvents = {
39
+ eventAuthError: {
40
+ error: HandlerError<string>;
41
+ payload: Record<string, unknown>;
42
+ };
39
43
  handlerAbort: {
40
44
  rid: string;
41
45
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/lib/utils.js CHANGED
@@ -24,7 +24,7 @@ export async function executeHandler(context, payload, execute) {
24
24
  } catch (cause) {
25
25
  const error = HandlerError.from(cause, {
26
26
  code: 'EK01',
27
- message: cause.message ?? 'Handler execution failed'
27
+ message: 'Handler execution failed'
28
28
  });
29
29
  if (canSend(controller.signal)) {
30
30
  context.logger.trace('send error to {type} {procedure} with ID {rid}', {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enkaku/server",
3
- "version": "0.12.3",
3
+ "version": "0.13.0",
4
4
  "license": "MIT",
5
5
  "homepage": "https://enkaku.dev",
6
6
  "description": "Server logic for Enkaku RPC",
@@ -25,17 +25,17 @@
25
25
  ],
26
26
  "sideEffects": false,
27
27
  "dependencies": {
28
- "@enkaku/async": "^0.12.2",
29
- "@enkaku/event": "^0.12.1",
30
- "@enkaku/log": "^0.12.1",
31
- "@enkaku/capability": "^0.12.1",
32
- "@enkaku/protocol": "^0.12.1",
33
- "@enkaku/stream": "^0.12.4",
34
- "@enkaku/token": "^0.12.3",
35
- "@enkaku/schema": "^0.12.1"
28
+ "@enkaku/capability": "^0.13.0",
29
+ "@enkaku/async": "^0.13.0",
30
+ "@enkaku/protocol": "^0.13.0",
31
+ "@enkaku/log": "^0.13.0",
32
+ "@enkaku/event": "^0.13.0",
33
+ "@enkaku/schema": "^0.13.0",
34
+ "@enkaku/token": "^0.13.0",
35
+ "@enkaku/stream": "^0.13.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@enkaku/transport": "^0.12.0"
38
+ "@enkaku/transport": "^0.13.0"
39
39
  },
40
40
  "scripts": {
41
41
  "build:clean": "del lib",