@conduitplatform/module-tools 0.17.0-alpha.7 → 0.17.0-alpha.9

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/dist/index.esm.js CHANGED
@@ -402,9 +402,9 @@ var GrpcServer = class {
402
402
  import path2 from "path";
403
403
  import { EventEmitter } from "events";
404
404
  import { camelCase } from "lodash-es";
405
- import { status as status3 } from "@grpc/grpc-js";
405
+ import { status as status5 } from "@grpc/grpc-js";
406
406
  import {
407
- ConduitGrpcSdk as ConduitGrpcSdk4,
407
+ ConduitGrpcSdk as ConduitGrpcSdk6,
408
408
  HealthCheckResponse_ServingStatus,
409
409
  HealthCheckStatus
410
410
  } from "@conduitplatform/grpc-sdk";
@@ -487,6 +487,16 @@ var RouteBuilder = class {
487
487
  this._options.captureRawHeaders = capture;
488
488
  return this;
489
489
  }
490
+ /**
491
+ * Whether module-tools hydrates `context.user` from `context.userId` on routes with
492
+ * `authMiddleware` / `authMiddleware?` (default true).
493
+ * @deprecated The default flips to false in the next major; call
494
+ * `grpcSdk.authentication.getUser(userId)` explicitly instead.
495
+ */
496
+ hydrateUser(hydrate) {
497
+ this._options.hydrateUser = hydrate;
498
+ return this;
499
+ }
490
500
  return(name, fields) {
491
501
  this._returns = new ConduitRouteReturnDefinition(name, fields);
492
502
  return this;
@@ -520,45 +530,105 @@ var RouteBuilder = class {
520
530
 
521
531
  // src/routing/wrapRouterFunctions.ts
522
532
  import {
523
- ConduitGrpcSdk as ConduitGrpcSdk3
533
+ ConduitGrpcSdk as ConduitGrpcSdk4
524
534
  } from "@conduitplatform/grpc-sdk";
535
+ import { status as status3 } from "@grpc/grpc-js";
536
+
537
+ // src/routing/hydrateUser.ts
538
+ import { ConduitGrpcSdk as ConduitGrpcSdk3, GrpcError as GrpcError2 } from "@conduitplatform/grpc-sdk";
525
539
  import { status as status2 } from "@grpc/grpc-js";
540
+ function middlewareList(routeOptions) {
541
+ const m = routeOptions?.middlewares;
542
+ if (Array.isArray(m)) return m.filter((x) => typeof x === "string");
543
+ if (typeof m === "string") return [m];
544
+ return [];
545
+ }
546
+ function getAuthMiddlewareKind(routeOptions) {
547
+ const list = middlewareList(routeOptions);
548
+ if (list.includes("authMiddleware")) return "required";
549
+ if (list.includes("authMiddleware?")) return "optional";
550
+ return void 0;
551
+ }
552
+ function shouldHydrateUser(routeOptions, context) {
553
+ if (!routeOptions || !context) return false;
554
+ if (routeOptions.hydrateUser === false) return false;
555
+ if (!getAuthMiddlewareKind(routeOptions)) return false;
556
+ return typeof context.userId === "string" && !!context.userId && !context.user;
557
+ }
558
+ function createUserHydrator(routeOptions, resolve) {
559
+ if (!routeOptions) return void 0;
560
+ const kind = getAuthMiddlewareKind(routeOptions);
561
+ if (!kind || routeOptions.hydrateUser === false) return void 0;
562
+ return {
563
+ optional: kind === "optional",
564
+ getUser: async (userId) => {
565
+ const resolver = resolve();
566
+ if (!resolver) throw new GrpcError2(status2.UNAVAILABLE, "User lookup unavailable");
567
+ return resolver(userId);
568
+ }
569
+ };
570
+ }
571
+ function mapHydrationErrorCode(error) {
572
+ const code = error?.code;
573
+ if (typeof code !== "number" || code === status2.OK) return status2.INTERNAL;
574
+ if (code === status2.NOT_FOUND) return status2.UNAUTHENTICATED;
575
+ return code;
576
+ }
577
+ async function hydrateContextUser(routeOptions, context, hydrator) {
578
+ if (!shouldHydrateUser(routeOptions, context)) return;
579
+ try {
580
+ context.user = await hydrator.getUser(context.userId);
581
+ } catch (e) {
582
+ ConduitGrpcSdk3.Logger.warn(
583
+ `User hydration failed: ${e?.message ?? String(e)}`
584
+ );
585
+ if (!hydrator.optional) {
586
+ const code = mapHydrationErrorCode(e);
587
+ throw new GrpcError2(
588
+ code,
589
+ code === status2.UNAUTHENTICATED ? "Unauthorized" : "User lookup failed"
590
+ );
591
+ }
592
+ }
593
+ }
594
+
595
+ // src/routing/wrapRouterFunctions.ts
526
596
  var mapGrpcStatusToHttp = (code) => {
527
597
  if (!code) return "200 (OK)";
528
598
  switch (code) {
529
- case status2.OK:
599
+ case status3.OK:
530
600
  return `200 (OK)`;
531
- case status2.CANCELLED:
601
+ case status3.CANCELLED:
532
602
  return `499 (Cancelled)`;
533
- case status2.INVALID_ARGUMENT:
603
+ case status3.INVALID_ARGUMENT:
534
604
  return `400 (Invalid Argument)`;
535
- case status2.DEADLINE_EXCEEDED:
605
+ case status3.DEADLINE_EXCEEDED:
536
606
  return `504 (Deadline Exceeded)`;
537
- case status2.NOT_FOUND:
607
+ case status3.NOT_FOUND:
538
608
  return `404 (Not Found)`;
539
- case status2.ALREADY_EXISTS:
609
+ case status3.ALREADY_EXISTS:
540
610
  return `409 (Already Exists)`;
541
- case status2.PERMISSION_DENIED:
611
+ case status3.PERMISSION_DENIED:
542
612
  return `403 (Permission Denied)`;
543
- case status2.UNAUTHENTICATED:
613
+ case status3.UNAUTHENTICATED:
544
614
  return `401 (Unauthenticated)`;
545
- case status2.OUT_OF_RANGE:
615
+ case status3.OUT_OF_RANGE:
546
616
  return `416 (Out of Range)`;
547
- case status2.FAILED_PRECONDITION:
617
+ case status3.FAILED_PRECONDITION:
548
618
  return `412 (Failed Precondition)`;
549
- case status2.ABORTED:
619
+ case status3.ABORTED:
550
620
  return `409 (Aborted)`;
551
- case status2.INTERNAL:
621
+ case status3.INTERNAL:
552
622
  return `416 (Internal)`;
553
- case status2.UNAVAILABLE:
623
+ case status3.UNAVAILABLE:
554
624
  return `503 (Service Unavailable)`;
555
- case status2.DATA_LOSS:
625
+ case status3.DATA_LOSS:
556
626
  return `500 (Data Loss)`;
557
627
  default:
558
628
  return `500 (Unknown)`;
559
629
  }
560
630
  };
561
- function generateLog(routerType, routerRequest, requestReceive, call, status6) {
631
+ function generateLog(routerType, routerRequest, requestReceive, call, status10) {
562
632
  let log = "";
563
633
  const latency = Date.now() - requestReceive;
564
634
  if (routerRequest) {
@@ -568,15 +638,15 @@ function generateLog(routerType, routerRequest, requestReceive, call, status6) {
568
638
  const socketLabel = socketReq.socketId ?? socketReq.socket;
569
639
  log += `(${routerType}) Socket: ${socketReq.event} socket: ${socketLabel}`;
570
640
  }
571
- log += ` ${mapGrpcStatusToHttp(status6) ?? "200"} ${latency}ms`;
572
- ConduitGrpcSdk3.Logger.log(log);
573
- ConduitGrpcSdk3.Metrics?.set("grpc_request_latency_seconds", latency / 1e3);
574
- ConduitGrpcSdk3.Metrics?.set(
641
+ log += ` ${mapGrpcStatusToHttp(status10) ?? "200"} ${latency}ms`;
642
+ ConduitGrpcSdk4.Logger.log(log);
643
+ ConduitGrpcSdk4.Metrics?.set("grpc_request_latency_seconds", latency / 1e3);
644
+ ConduitGrpcSdk4.Metrics?.set(
575
645
  `${routerType}_grpc_request_latency_seconds`,
576
646
  latency / 1e3
577
647
  );
578
- const successStatus = !status6 || status6.toString().startsWith("2");
579
- ConduitGrpcSdk3.Metrics?.increment(`${routerType}_grpc_response_statuses_total`, 1, {
648
+ const successStatus = !status10 || status10.toString().startsWith("2");
649
+ ConduitGrpcSdk4.Metrics?.increment(`${routerType}_grpc_response_statuses_total`, 1, {
580
650
  success: successStatus ? "true" : "false"
581
651
  });
582
652
  }
@@ -592,7 +662,7 @@ function parseResponseData(r, routerRequest, requestReceive, call, callback, res
592
662
  responded.did = true;
593
663
  if (!r) {
594
664
  callback({
595
- code: status2.INTERNAL,
665
+ code: status3.INTERNAL,
596
666
  message: "Handler did not return a response"
597
667
  });
598
668
  }
@@ -623,11 +693,11 @@ function parseResponseData(r, routerRequest, requestReceive, call, callback, res
623
693
  }
624
694
  generateLog(routerType, routerRequest, requestReceive, call, void 0);
625
695
  }
626
- function wrapRouterGrpcFunction(fun, routerType) {
696
+ function wrapRouterGrpcFunction(fun, routerType, hydration) {
627
697
  return (call, callback) => {
628
698
  const requestReceive = Date.now();
629
699
  let routerRequest = true;
630
- ConduitGrpcSdk3.Metrics?.increment(`${routerType}_grpc_requests_total`);
700
+ ConduitGrpcSdk4.Metrics?.increment(`${routerType}_grpc_requests_total`);
631
701
  try {
632
702
  call.request.context = parseRequestData(call.request.context);
633
703
  call.request.params = parseRequestData(call.request.params);
@@ -646,16 +716,16 @@ function wrapRouterGrpcFunction(fun, routerType) {
646
716
  }
647
717
  }
648
718
  } catch (e) {
649
- ConduitGrpcSdk3.Metrics?.increment(`${routerType}_grpc_errors_total`);
650
- generateLog(routerType, routerRequest, requestReceive, call, status2.INTERNAL);
651
- ConduitGrpcSdk3.Logger.error(e.message ?? "Something went wrong");
719
+ ConduitGrpcSdk4.Metrics?.increment(`${routerType}_grpc_errors_total`);
720
+ generateLog(routerType, routerRequest, requestReceive, call, status3.INTERNAL);
721
+ ConduitGrpcSdk4.Logger.error(e.message ?? "Something went wrong");
652
722
  return callback({
653
- code: status2.INTERNAL,
723
+ code: status3.INTERNAL,
654
724
  message: e.message ?? "Something went wrong"
655
725
  });
656
726
  }
657
727
  const responded = { did: false };
658
- fun(call, (r) => {
728
+ const invoke = () => fun(call, (r) => {
659
729
  parseResponseData(
660
730
  r,
661
731
  routerRequest,
@@ -665,7 +735,13 @@ function wrapRouterGrpcFunction(fun, routerType) {
665
735
  responded,
666
736
  routerType
667
737
  );
668
- }).then(
738
+ });
739
+ const needsHydration = hydration && shouldHydrateUser(hydration.options, call.request.context);
740
+ (needsHydration ? hydrateContextUser(
741
+ hydration.options,
742
+ call.request.context,
743
+ hydration.hydrator
744
+ ).then(invoke) : invoke()).then(
669
745
  (r) => parseResponseData(
670
746
  r,
671
747
  routerRequest,
@@ -676,19 +752,19 @@ function wrapRouterGrpcFunction(fun, routerType) {
676
752
  routerType
677
753
  )
678
754
  ).catch((error) => {
679
- ConduitGrpcSdk3.Metrics?.increment(`${routerType}_grpc_errors_total`);
755
+ ConduitGrpcSdk4.Metrics?.increment(`${routerType}_grpc_errors_total`);
680
756
  generateLog(
681
757
  routerType,
682
758
  routerRequest,
683
759
  requestReceive,
684
760
  call,
685
- error.code ?? status2.INTERNAL
761
+ error.code ?? status3.INTERNAL
686
762
  );
687
- ConduitGrpcSdk3.Logger.error(
763
+ ConduitGrpcSdk4.Logger.error(
688
764
  error.debugLogInfo ?? error.message ?? "Something went wrong"
689
765
  );
690
766
  callback({
691
- code: error.code ?? status2.INTERNAL,
767
+ code: error.code ?? status3.INTERNAL,
692
768
  message: error.details ?? error.message ?? "Something went wrong"
693
769
  });
694
770
  });
@@ -696,10 +772,14 @@ function wrapRouterGrpcFunction(fun, routerType) {
696
772
  }
697
773
 
698
774
  // src/routing/RoutingUtilities.ts
699
- function wrapFunctionsAsync(functions, routerType) {
775
+ function wrapFunctionsAsync(functions, routerType, hydrations = {}) {
700
776
  const modifiedFunctions = {};
701
777
  Object.keys(functions).forEach((key) => {
702
- modifiedFunctions[key] = wrapRouterGrpcFunction(functions[key], routerType);
778
+ modifiedFunctions[key] = wrapRouterGrpcFunction(
779
+ functions[key],
780
+ routerType,
781
+ hydrations[key]
782
+ );
703
783
  });
704
784
  return modifiedFunctions;
705
785
  }
@@ -707,8 +787,11 @@ function wrapFunctionsAsync(functions, routerType) {
707
787
  // src/routing/RoutingManager.ts
708
788
  import {
709
789
  Admin,
710
- ConduitRouteActions as ConduitRouteActions2
790
+ ConduitRouteActions as ConduitRouteActions2,
791
+ ConduitGrpcSdk as ConduitGrpcSdk5,
792
+ GrpcError as GrpcError3
711
793
  } from "@conduitplatform/grpc-sdk";
794
+ import { status as status4 } from "@grpc/grpc-js";
712
795
  var RoutingManager = class _RoutingManager {
713
796
  constructor(_router, _server) {
714
797
  this._router = _router;
@@ -722,6 +805,30 @@ var RoutingManager = class _RoutingManager {
722
805
  _moduleRoutes = {};
723
806
  static ClientController;
724
807
  static AdminController;
808
+ /** Set by ManagedModule; used to hydrate context.user on client routes. */
809
+ static grpcSdk;
810
+ static userResolver;
811
+ static warnedNoResolver = false;
812
+ /**
813
+ * Overrides how users are fetched for hydration (default: grpcSdk.authentication.getUser).
814
+ * Intended for the module that owns the users: the authentication module has no gRPC
815
+ * client to itself and will register a local resolver here.
816
+ */
817
+ static setUserResolver(resolver) {
818
+ _RoutingManager.userResolver = resolver;
819
+ }
820
+ static resolveUser() {
821
+ if (_RoutingManager.userResolver) return _RoutingManager.userResolver;
822
+ const sdk = _RoutingManager.grpcSdk;
823
+ if (!sdk) return void 0;
824
+ return async (userId) => {
825
+ const auth = sdk.authentication;
826
+ if (!auth) {
827
+ throw new GrpcError3(status4.UNAVAILABLE, "authentication module unavailable");
828
+ }
829
+ return auth.getUser(userId);
830
+ };
831
+ }
725
832
  _routeHandlers = {};
726
833
  isAdmin = false;
727
834
  get(path5) {
@@ -788,7 +895,27 @@ var RoutingManager = class _RoutingManager {
788
895
  }
789
896
  async registerRoutes() {
790
897
  if (Object.keys(this._routeHandlers).length === 0) return;
791
- const modifiedFunctions = wrapFunctionsAsync(this._routeHandlers, this.isAdmin ? "admin" : "client");
898
+ const hydrations = {};
899
+ if (!this.isAdmin) {
900
+ for (const [name, route] of Object.entries(this._moduleRoutes)) {
901
+ const options = route.options;
902
+ const hydrator = createUserHydrator(options, _RoutingManager.resolveUser);
903
+ if (!hydrator) continue;
904
+ const names = "events" in route ? Object.keys(JSON.parse(route.events || "{}")) : [name];
905
+ for (const n of names) hydrations[n] = { options, hydrator };
906
+ if (!_RoutingManager.grpcSdk && !_RoutingManager.userResolver && !_RoutingManager.warnedNoResolver) {
907
+ _RoutingManager.warnedNoResolver = true;
908
+ ConduitGrpcSdk5.Logger.warn(
909
+ "User hydration is needed but RoutingManager.grpcSdk is not set; hydration will fail"
910
+ );
911
+ }
912
+ }
913
+ }
914
+ const modifiedFunctions = wrapFunctionsAsync(
915
+ this._routeHandlers,
916
+ this.isAdmin ? "admin" : "client",
917
+ hydrations
918
+ );
792
919
  if (this.isAdmin) {
793
920
  _RoutingManager.AdminController.setRoutes(modifiedFunctions);
794
921
  } else {
@@ -867,7 +994,7 @@ var ConduitServiceModule = class {
867
994
  );
868
995
  }
869
996
  if (!init) {
870
- ConduitGrpcSdk4.Metrics?.set(
997
+ ConduitGrpcSdk6.Metrics?.set(
871
998
  "module_health_state",
872
999
  state === HealthCheckStatus.SERVING ? 1 : 0
873
1000
  );
@@ -910,9 +1037,9 @@ var ConduitServiceModule = class {
910
1037
  } else {
911
1038
  this.events.on(
912
1039
  `grpc-health-change:${this._serviceName}`,
913
- (status6) => {
1040
+ (status10) => {
914
1041
  call.write({
915
- status: status6
1042
+ status: status10
916
1043
  });
917
1044
  }
918
1045
  );
@@ -935,7 +1062,7 @@ var ConduitServiceModule = class {
935
1062
  const resources = this.getExportableResources();
936
1063
  callback(null, { resources: JSON.stringify(resources) });
937
1064
  } catch (e) {
938
- callback({ code: status3.INTERNAL, message: e.message });
1065
+ callback({ code: status5.INTERNAL, message: e.message });
939
1066
  }
940
1067
  }
941
1068
  async exportResourcesHandler(call, callback) {
@@ -944,7 +1071,7 @@ var ConduitServiceModule = class {
944
1071
  const data = await this.exportResources(resourceTypes);
945
1072
  callback(null, { data: JSON.stringify(data) });
946
1073
  } catch (e) {
947
- callback({ code: status3.INTERNAL, message: e.message });
1074
+ callback({ code: status5.INTERNAL, message: e.message });
948
1075
  }
949
1076
  }
950
1077
  async importResourcesHandler(call, callback) {
@@ -956,11 +1083,11 @@ var ConduitServiceModule = class {
956
1083
  const err = e;
957
1084
  if (err instanceof SyntaxError) {
958
1085
  callback({
959
- code: status3.INVALID_ARGUMENT,
1086
+ code: status5.INVALID_ARGUMENT,
960
1087
  message: "Invalid JSON in import data"
961
1088
  });
962
1089
  } else {
963
- callback({ code: status3.INTERNAL, message: err.message });
1090
+ callback({ code: status5.INTERNAL, message: err.message });
964
1091
  }
965
1092
  }
966
1093
  }
@@ -1033,7 +1160,7 @@ var ConfigController = class _ConfigController {
1033
1160
 
1034
1161
  // src/ManagedModule.ts
1035
1162
  import { kebabCase } from "lodash-es";
1036
- import { status as status5 } from "@grpc/grpc-js";
1163
+ import { status as status9 } from "@grpc/grpc-js";
1037
1164
  import convict from "convict";
1038
1165
 
1039
1166
  // src/interfaces/ModuleLifecycleStage.ts
@@ -1048,18 +1175,18 @@ var ModuleLifecycleStage = /* @__PURE__ */ ((ModuleLifecycleStage2) => {
1048
1175
 
1049
1176
  // src/ManagedModule.ts
1050
1177
  import {
1051
- ConduitGrpcSdk as ConduitGrpcSdk8
1178
+ ConduitGrpcSdk as ConduitGrpcSdk11
1052
1179
  } from "@conduitplatform/grpc-sdk";
1053
1180
 
1054
1181
  // src/utilities/initializeSdk.ts
1055
1182
  import {
1056
- ConduitGrpcSdk as ConduitGrpcSdk7,
1183
+ ConduitGrpcSdk as ConduitGrpcSdk9,
1057
1184
  HealthCheckStatus as HealthCheckStatus2
1058
1185
  } from "@conduitplatform/grpc-sdk";
1059
1186
 
1060
1187
  // src/logging/index.ts
1061
1188
  import {
1062
- ConduitGrpcSdk as ConduitGrpcSdk5
1189
+ ConduitGrpcSdk as ConduitGrpcSdk7
1063
1190
  } from "@conduitplatform/grpc-sdk";
1064
1191
  import winston, { format } from "winston";
1065
1192
  import { isEmpty } from "lodash-es";
@@ -1217,7 +1344,7 @@ async function setupLoki(module, instance) {
1217
1344
  if (lokiUrl.endsWith("/")) lokiUrl = lokiUrl.slice(0, -1);
1218
1345
  const onTry = async () => {
1219
1346
  return await lokiReadyCheck(lokiUrl).then(() => {
1220
- ConduitGrpcSdk5.Logger.addTransport(
1347
+ ConduitGrpcSdk7.Logger.addTransport(
1221
1348
  new LokiTransport({
1222
1349
  level: "debug",
1223
1350
  host: lokiUrl,
@@ -1236,15 +1363,90 @@ async function setupLoki(module, instance) {
1236
1363
  }).catch(() => true);
1237
1364
  };
1238
1365
  const onFailure = () => {
1239
- ConduitGrpcSdk5.Logger.error(`Failed to connect to Loki on '${lokiUrl}'`);
1366
+ ConduitGrpcSdk7.Logger.error(`Failed to connect to Loki on '${lokiUrl}'`);
1240
1367
  };
1241
1368
  await linearBackoffTimeoutAsync(onTry, 250, 15, onFailure, true);
1242
1369
  }
1243
1370
  }
1244
1371
 
1245
- // src/utilities/initializeSdk.ts
1246
- import winston2 from "winston";
1372
+ // src/logging/fileTransports.ts
1373
+ import fs from "fs";
1374
+ import os from "os";
1247
1375
  import path3 from "path";
1376
+ import winston2 from "winston";
1377
+ import DailyRotateFile from "winston-daily-rotate-file";
1378
+ var DEFAULT_RETENTION_DAYS = 3;
1379
+ var DEFAULT_MAX_SIZE = "20m";
1380
+ var SIZE_STRING = /^(?:0\.)?\d+[kmg]$/i;
1381
+ function positiveIntFromEnv(raw, fallback) {
1382
+ if (raw === void 0) return fallback;
1383
+ const trimmed = raw.trim();
1384
+ if (!/^[0-9]+$/.test(trimmed)) return fallback;
1385
+ const value = Number(trimmed);
1386
+ if (!Number.isSafeInteger(value) || value <= 0) return fallback;
1387
+ return value;
1388
+ }
1389
+ function logFileMaxSize() {
1390
+ const raw = process.env.LOG_FILE_MAX_SIZE?.trim();
1391
+ if (!raw) return DEFAULT_MAX_SIZE;
1392
+ if (SIZE_STRING.test(raw)) return raw.toLowerCase();
1393
+ if (/^[0-9]+$/.test(raw)) {
1394
+ const bytes = Number(raw);
1395
+ if (Number.isSafeInteger(bytes) && bytes > 0) return bytes;
1396
+ }
1397
+ return DEFAULT_MAX_SIZE;
1398
+ }
1399
+ function formatMeta(meta) {
1400
+ if (Array.isArray(meta)) {
1401
+ if (meta.length === 0) return "";
1402
+ return meta.map((item) => JSON.stringify(item)).join(" ");
1403
+ }
1404
+ if (meta !== null && typeof meta === "object") {
1405
+ if (Object.keys(meta).length === 0) return "";
1406
+ return JSON.stringify(meta);
1407
+ }
1408
+ return "";
1409
+ }
1410
+ function createFileFormat() {
1411
+ return winston2.format.combine(
1412
+ winston2.format.errors({ stack: true }),
1413
+ winston2.format.timestamp({
1414
+ format: "YYYY-MM-DD HH:mm:ss"
1415
+ }),
1416
+ winston2.format.printf((info) => {
1417
+ const metaText = formatMeta(info.meta);
1418
+ const line = `[${info.timestamp}] [${info.level.toUpperCase()}]: ${info.message}`;
1419
+ if (info.stack) {
1420
+ return `${line} ${info.stack}`;
1421
+ }
1422
+ return metaText ? `${line} ${metaText}` : line;
1423
+ })
1424
+ );
1425
+ }
1426
+ function rotateTransport(logDir, name, level) {
1427
+ return new DailyRotateFile({
1428
+ dirname: logDir,
1429
+ filename: `${name}-%DATE%.log`,
1430
+ datePattern: "YYYY-MM-DD",
1431
+ level,
1432
+ maxFiles: `${positiveIntFromEnv(process.env.LOG_RETENTION_DAYS, DEFAULT_RETENTION_DAYS)}d`,
1433
+ maxSize: logFileMaxSize(),
1434
+ zippedArchive: false,
1435
+ auditFile: path3.join(logDir, `.${name}-audit.json`),
1436
+ format: createFileFormat()
1437
+ });
1438
+ }
1439
+ function createFileLogTransports() {
1440
+ if (process.env.LOG_TO_FILE?.trim() === "false") {
1441
+ return [];
1442
+ }
1443
+ const logDir = process.env.LOG_FILE_DIR?.trim() || path3.join(os.tmpdir(), "conduit-logs");
1444
+ fs.mkdirSync(logDir, { recursive: true });
1445
+ return [
1446
+ rotateTransport(logDir, "combined", "info"),
1447
+ rotateTransport(logDir, "errors", "error")
1448
+ ];
1449
+ }
1248
1450
 
1249
1451
  // src/metrics/index.ts
1250
1452
  import {
@@ -1259,7 +1461,7 @@ import {
1259
1461
  // src/metrics/MetricsServer.ts
1260
1462
  import { createServer as createServer2 } from "http";
1261
1463
  import { isNaN } from "lodash-es";
1262
- import { ConduitGrpcSdk as ConduitGrpcSdk6 } from "@conduitplatform/grpc-sdk";
1464
+ import { ConduitGrpcSdk as ConduitGrpcSdk8 } from "@conduitplatform/grpc-sdk";
1263
1465
  var MetricsServer = class {
1264
1466
  moduleName;
1265
1467
  instance;
@@ -1274,7 +1476,7 @@ var MetricsServer = class {
1274
1476
  const url = "0.0.0.0:" + port.toString();
1275
1477
  const server = createServer2(this.requestHandler.bind(this));
1276
1478
  server.listen(port, () => {
1277
- ConduitGrpcSdk6.Logger.info(`Metrics server listening on: ${url}`);
1479
+ ConduitGrpcSdk8.Logger.info(`Metrics server listening on: ${url}`);
1278
1480
  });
1279
1481
  return server;
1280
1482
  }
@@ -1296,12 +1498,12 @@ var MetricsServer = class {
1296
1498
  getHttpPort() {
1297
1499
  const value = process.env["METRICS_PORT"];
1298
1500
  if (!value) {
1299
- ConduitGrpcSdk6.Logger.error(`Metrics HTTP port not set`);
1501
+ ConduitGrpcSdk8.Logger.error(`Metrics HTTP port not set`);
1300
1502
  process.exit(-1);
1301
1503
  }
1302
1504
  const port = parseInt(value, 10);
1303
1505
  if (isNaN(port) || port < 1 || port > 65535) {
1304
- ConduitGrpcSdk6.Logger.error(`Invalid HTTP port value: ${port}`);
1506
+ ConduitGrpcSdk8.Logger.error(`Invalid HTTP port value: ${port}`);
1305
1507
  process.exit(-1);
1306
1508
  }
1307
1509
  return port;
@@ -1593,7 +1795,7 @@ function clientMiddleware() {
1593
1795
  clientStartedMetric.inc(labels);
1594
1796
  const stopTimer = clientHandlingSecondsMetric.startTimer(labels);
1595
1797
  let settled = false;
1596
- let status6 = Status.OK;
1798
+ let status10 = Status.OK;
1597
1799
  try {
1598
1800
  let request;
1599
1801
  if (!call.requestStream) {
@@ -1619,21 +1821,21 @@ function clientMiddleware() {
1619
1821
  } catch (err) {
1620
1822
  settled = true;
1621
1823
  if (err instanceof ClientError) {
1622
- status6 = err.code;
1824
+ status10 = err.code;
1623
1825
  } else if (isAbortError(err)) {
1624
- status6 = Status.ABORTED;
1826
+ status10 = Status.ABORTED;
1625
1827
  } else {
1626
- status6 = Status.UNKNOWN;
1828
+ status10 = Status.UNKNOWN;
1627
1829
  }
1628
1830
  throw err;
1629
1831
  } finally {
1630
1832
  if (!settled) {
1631
- status6 = Status.CANCELLED;
1833
+ status10 = Status.CANCELLED;
1632
1834
  }
1633
- stopTimer({ [codeLabel]: Status[status6] });
1835
+ stopTimer({ [codeLabel]: Status[status10] });
1634
1836
  clientHandledMetric.inc({
1635
1837
  ...labels,
1636
- [codeLabel]: Status[status6]
1838
+ [codeLabel]: Status[status10]
1637
1839
  });
1638
1840
  }
1639
1841
  };
@@ -1643,20 +1845,12 @@ function clientMiddleware() {
1643
1845
  var initializeSdk = (coreUrl, moduleName, watchModules = true, serviceHealthStatusGetter = () => HealthCheckStatus2.SERVING) => {
1644
1846
  let logger;
1645
1847
  try {
1646
- logger = new ConduitLogger([
1647
- new winston2.transports.File({
1648
- filename: path3.join(__dirname, ".logs/combined.log"),
1649
- level: "info"
1650
- }),
1651
- new winston2.transports.File({
1652
- filename: path3.join(__dirname, ".logs/errors.log"),
1653
- level: "error"
1654
- })
1655
- ]);
1656
- } catch (e) {
1848
+ const fileTransports = createFileLogTransports();
1849
+ logger = fileTransports.length > 0 ? new ConduitLogger(fileTransports) : new ConduitLogger();
1850
+ } catch {
1657
1851
  logger = new ConduitLogger();
1658
1852
  }
1659
- const grpcSdk = new ConduitGrpcSdk7(
1853
+ const grpcSdk = new ConduitGrpcSdk9(
1660
1854
  coreUrl,
1661
1855
  moduleName,
1662
1856
  watchModules,
@@ -1665,7 +1859,7 @@ var initializeSdk = (coreUrl, moduleName, watchModules = true, serviceHealthStat
1665
1859
  );
1666
1860
  setupLoki(grpcSdk.name, grpcSdk.instance).then();
1667
1861
  if (process.env.METRICS_PORT) {
1668
- ConduitGrpcSdk7.Metrics = new ConduitMetrics(grpcSdk.name, grpcSdk.instance);
1862
+ ConduitGrpcSdk9.Metrics = new ConduitMetrics(grpcSdk.name, grpcSdk.instance);
1669
1863
  grpcSdk.addMiddleware(clientMiddleware());
1670
1864
  }
1671
1865
  return grpcSdk;
@@ -1863,8 +2057,346 @@ async function reconcileStoredModuleConfig(args) {
1863
2057
  return { config: persisted, persisted: true };
1864
2058
  }
1865
2059
 
2060
+ // src/utilities/accessTokenVerifier.ts
2061
+ import { ConduitGrpcSdk as ConduitGrpcSdk10, GrpcError as GrpcError5 } from "@conduitplatform/grpc-sdk";
2062
+ import { status as status7 } from "@grpc/grpc-js";
2063
+ import { createPublicKey } from "crypto";
2064
+
2065
+ // src/utilities/accessTokenVerifier.logic.ts
2066
+ import { createDecoder, createVerifier as createVerifier2 } from "fast-jwt";
2067
+ import { status as status6 } from "@grpc/grpc-js";
2068
+ import { GrpcError as GrpcError4 } from "@conduitplatform/grpc-sdk";
2069
+ var DEFAULT_LEEWAY_SECONDS = 5;
2070
+ var verifiers = /* @__PURE__ */ new Map();
2071
+ var decode = createDecoder({ complete: true });
2072
+ function fail(reason) {
2073
+ throw new GrpcError4(status6.UNAUTHENTICATED, reason);
2074
+ }
2075
+ function getVerifier(publicKey) {
2076
+ let verifier = verifiers.get(publicKey);
2077
+ if (!verifier) {
2078
+ verifier = createVerifier2({
2079
+ key: publicKey,
2080
+ algorithms: ["EdDSA"],
2081
+ ignoreExpiration: true,
2082
+ ignoreNotBefore: true,
2083
+ cache: false
2084
+ });
2085
+ verifiers.set(publicKey, verifier);
2086
+ }
2087
+ return verifier;
2088
+ }
2089
+ function selectVerificationKey(kid, signing, now) {
2090
+ if (!kid) return void 0;
2091
+ if (signing.publicKey && kid === signing.kid) return signing.publicKey;
2092
+ if (signing.previousKid && signing.previousPublicKey && kid === signing.previousKid && (signing.previousRetiredAt ?? 0) > now) {
2093
+ return signing.previousPublicKey;
2094
+ }
2095
+ return void 0;
2096
+ }
2097
+ function verifyAccessToken(token, state, options = {}) {
2098
+ const now = options.now ?? Date.now();
2099
+ const leeway = options.leewaySeconds ?? DEFAULT_LEEWAY_SECONDS;
2100
+ if (typeof token !== "string" || token.length === 0) fail("malformed token");
2101
+ let kid;
2102
+ try {
2103
+ const decoded = decode(token);
2104
+ if (decoded.header.alg !== "EdDSA") fail("unsupported algorithm");
2105
+ kid = decoded.header.kid;
2106
+ } catch (e) {
2107
+ if (e instanceof GrpcError4) throw e;
2108
+ fail("malformed token");
2109
+ }
2110
+ const key = selectVerificationKey(kid, state.signing, now);
2111
+ if (!key) fail("unknown kid");
2112
+ let claims;
2113
+ try {
2114
+ claims = getVerifier(key)(token);
2115
+ } catch {
2116
+ fail("bad signature");
2117
+ }
2118
+ if (typeof claims.sub !== "string" || typeof claims.sid !== "string" || typeof claims.exp !== "number") {
2119
+ fail("malformed token");
2120
+ }
2121
+ if (now / 1e3 >= claims.exp + leeway) fail("expired");
2122
+ if (claims.tv !== state.tokenVersion) fail("version mismatch");
2123
+ if (options.clientId !== void 0 && claims.cid !== options.clientId) {
2124
+ fail("client mismatch");
2125
+ }
2126
+ return claims;
2127
+ }
2128
+
2129
+ // src/utilities/accessTokenVerifier.ts
2130
+ var AUTHENTICATION_CONFIG_UPDATE_CHANNEL = "authentication:config:update";
2131
+ var INITIAL_RETRY_MS = 1e3;
2132
+ var MAX_RETRY_MS = 3e4;
2133
+ var REFRESH_INTERVAL_MS = 5 * 60 * 1e3;
2134
+ var UNKNOWN_KID_REFETCH_MIN_MS = 10 * 1e3;
2135
+ var SUBSCRIBER_ID = "access-token-verifier";
2136
+ function isConfigWithAccessTokens(config) {
2137
+ return typeof config === "object" && config !== null && typeof config.accessTokens === "object" && config.accessTokens !== null;
2138
+ }
2139
+ var AccessTokenVerifier = class _AccessTokenVerifier {
2140
+ constructor(grpcSdk) {
2141
+ this.grpcSdk = grpcSdk;
2142
+ }
2143
+ grpcSdk;
2144
+ static instance;
2145
+ _mode = "session";
2146
+ _strictRevocation = false;
2147
+ _tokenVersion = 0;
2148
+ _signing;
2149
+ _loaded = false;
2150
+ _subscribed = false;
2151
+ _generation = 0;
2152
+ _running = false;
2153
+ _retryTimer;
2154
+ _refreshTimer;
2155
+ _lastRefetch = 0;
2156
+ _refetching = false;
2157
+ _warned = /* @__PURE__ */ new Set();
2158
+ _listeners = /* @__PURE__ */ new Set();
2159
+ static getInstance(grpcSdk) {
2160
+ if (!_AccessTokenVerifier.instance) {
2161
+ _AccessTokenVerifier.instance = new _AccessTokenVerifier(grpcSdk);
2162
+ }
2163
+ return _AccessTokenVerifier.instance;
2164
+ }
2165
+ /**
2166
+ * Internal, for tests only: stops the verifier, clears all state and drops the singleton.
2167
+ */
2168
+ static resetForTests() {
2169
+ _AccessTokenVerifier.instance?.stop();
2170
+ _AccessTokenVerifier.instance?.resetState();
2171
+ _AccessTokenVerifier.instance = void 0;
2172
+ }
2173
+ resetState() {
2174
+ this._mode = "session";
2175
+ this._strictRevocation = false;
2176
+ this._tokenVersion = 0;
2177
+ this._signing = void 0;
2178
+ this._loaded = false;
2179
+ this._lastRefetch = 0;
2180
+ this._warned.clear();
2181
+ this._listeners.clear();
2182
+ }
2183
+ /** Snapshot of the verifier's observable state. */
2184
+ get state() {
2185
+ return {
2186
+ mode: this._mode,
2187
+ strictRevocation: this._strictRevocation,
2188
+ ready: this.ready,
2189
+ tokenVersion: this._tokenVersion,
2190
+ kid: this._signing?.kid
2191
+ };
2192
+ }
2193
+ /**
2194
+ * Registers a listener fired synchronously at the end of every applyConfig that changed
2195
+ * anything (including the first successful load). Returns an unsubscribe function.
2196
+ */
2197
+ onChange(listener) {
2198
+ this._listeners.add(listener);
2199
+ return () => {
2200
+ this._listeners.delete(listener);
2201
+ };
2202
+ }
2203
+ fingerprint() {
2204
+ return JSON.stringify([this._loaded, this._signing, this.state]);
2205
+ }
2206
+ get mode() {
2207
+ return this._mode;
2208
+ }
2209
+ get strictRevocation() {
2210
+ return this._strictRevocation;
2211
+ }
2212
+ /** True once signing keys have been loaded. */
2213
+ get ready() {
2214
+ return !!this._signing?.publicKey;
2215
+ }
2216
+ get tokenVersion() {
2217
+ return this._tokenVersion;
2218
+ }
2219
+ /**
2220
+ * Loads the authentication config, subscribes to its updates and starts a slow periodic
2221
+ * refresh. The first attempt is awaited; if it fails, retries continue in the background
2222
+ * with capped backoff until the config is loaded and the subscription is acknowledged.
2223
+ * Idempotent while running; never throws.
2224
+ */
2225
+ async start() {
2226
+ if (this._running) return;
2227
+ this._running = true;
2228
+ const generation = ++this._generation;
2229
+ await this.attempt(generation, INITIAL_RETRY_MS);
2230
+ if (generation !== this._generation) return;
2231
+ this._refreshTimer = setInterval(() => void this.refetch(true), REFRESH_INTERVAL_MS);
2232
+ this._refreshTimer.unref?.();
2233
+ }
2234
+ stop() {
2235
+ this._running = false;
2236
+ this._generation++;
2237
+ if (this._retryTimer) clearTimeout(this._retryTimer);
2238
+ if (this._refreshTimer) clearInterval(this._refreshTimer);
2239
+ this._retryTimer = void 0;
2240
+ this._refreshTimer = void 0;
2241
+ if (this._subscribed) {
2242
+ try {
2243
+ this.grpcSdk.bus?.unsubscribe(SUBSCRIBER_ID);
2244
+ } catch {
2245
+ }
2246
+ this._subscribed = false;
2247
+ }
2248
+ }
2249
+ async attempt(generation, delay) {
2250
+ if (generation !== this._generation) return;
2251
+ try {
2252
+ await this.subscribe(generation);
2253
+ if (!this._loaded) {
2254
+ this.applyConfig(await this.grpcSdk.config.get("authentication"));
2255
+ }
2256
+ } catch {
2257
+ }
2258
+ if (generation !== this._generation) return;
2259
+ if (this._subscribed && this._loaded) return;
2260
+ this._retryTimer = setTimeout(
2261
+ () => void this.attempt(generation, Math.min(delay * 2, MAX_RETRY_MS)),
2262
+ delay
2263
+ );
2264
+ this._retryTimer.unref?.();
2265
+ }
2266
+ async subscribe(generation) {
2267
+ if (this._subscribed) return;
2268
+ const bus = this.grpcSdk.bus;
2269
+ if (!bus) return;
2270
+ await bus.subscribeAck(
2271
+ AUTHENTICATION_CONFIG_UPDATE_CHANNEL,
2272
+ (message) => {
2273
+ try {
2274
+ this.applyConfig(JSON.parse(message));
2275
+ } catch {
2276
+ }
2277
+ },
2278
+ SUBSCRIBER_ID
2279
+ );
2280
+ if (generation !== this._generation) {
2281
+ bus.unsubscribe(SUBSCRIBER_ID);
2282
+ return;
2283
+ }
2284
+ this._subscribed = true;
2285
+ }
2286
+ /** Refetches the config from the authentication module; failures keep the previous state. */
2287
+ async refetch(force = false) {
2288
+ const now = Date.now();
2289
+ if (this._refetching) return;
2290
+ if (!force && now - this._lastRefetch < UNKNOWN_KID_REFETCH_MIN_MS) return;
2291
+ this._lastRefetch = now;
2292
+ this._refetching = true;
2293
+ try {
2294
+ this.applyConfig(await this.grpcSdk.config.get("authentication"));
2295
+ } catch {
2296
+ } finally {
2297
+ this._refetching = false;
2298
+ }
2299
+ }
2300
+ warnOnce(key, message) {
2301
+ if (this._warned.has(key)) return;
2302
+ this._warned.add(key);
2303
+ ConduitGrpcSdk10.Logger.warn(`AccessTokenVerifier: ${message}`);
2304
+ }
2305
+ static validPem(pem) {
2306
+ if (typeof pem !== "string" || !pem) return false;
2307
+ try {
2308
+ createPublicKey(pem);
2309
+ return true;
2310
+ } catch {
2311
+ return false;
2312
+ }
2313
+ }
2314
+ /**
2315
+ * Validates and normalizes the signing keys. Returns undefined when no signing block is
2316
+ * configured, null when the public key is invalid (the caller keeps the previous state).
2317
+ */
2318
+ normalizeSigning(s) {
2319
+ if (!(s && typeof s.kid === "string" && s.kid && s.publicKey)) return void 0;
2320
+ if (!_AccessTokenVerifier.validPem(s.publicKey)) {
2321
+ this.warnOnce("publicKey", "invalid signing public key, keeping previous state");
2322
+ return null;
2323
+ }
2324
+ const previousPublicKey = this.validPreviousKey(s.previousPublicKey);
2325
+ return {
2326
+ kid: s.kid,
2327
+ publicKey: s.publicKey,
2328
+ previousKid: previousPublicKey ? s.previousKid || void 0 : void 0,
2329
+ previousPublicKey,
2330
+ previousRetiredAt: Number(s.previousRetiredAt ?? 0)
2331
+ };
2332
+ }
2333
+ validPreviousKey(pem) {
2334
+ if (!pem) return void 0;
2335
+ if (_AccessTokenVerifier.validPem(pem)) return pem;
2336
+ this.warnOnce("previousPublicKey", "invalid previous public key, ignoring it");
2337
+ return void 0;
2338
+ }
2339
+ parseTokenVersion(raw) {
2340
+ const version = Number(raw ?? 0);
2341
+ if (Number.isNaN(version)) {
2342
+ this.warnOnce("tokenVersion", "invalid tokenVersion, all tokens will be rejected");
2343
+ }
2344
+ return version;
2345
+ }
2346
+ notifyListeners() {
2347
+ const state = this.state;
2348
+ for (const listener of [...this._listeners]) {
2349
+ try {
2350
+ listener(state);
2351
+ } catch (e) {
2352
+ ConduitGrpcSdk10.Logger.warn(
2353
+ `AccessTokenVerifier: change listener failed: ${e?.message}`
2354
+ );
2355
+ }
2356
+ }
2357
+ }
2358
+ /**
2359
+ * Applies an authentication module config object (full config). Invalid input is ignored
2360
+ * and the previous state is kept; invalid keys are logged once.
2361
+ */
2362
+ applyConfig(config) {
2363
+ if (!isConfigWithAccessTokens(config)) return;
2364
+ const tokens = config.accessTokens;
2365
+ const before = this.fingerprint();
2366
+ const signing = this.normalizeSigning(tokens.signing);
2367
+ if (signing === null) return;
2368
+ const version = this.parseTokenVersion(tokens.tokenVersion);
2369
+ this._mode = tokens.mode === "jwt" ? "jwt" : "session";
2370
+ this._tokenVersion = version;
2371
+ this._strictRevocation = tokens.strictRevocation === true;
2372
+ this._signing = signing;
2373
+ this._loaded = true;
2374
+ if (this.fingerprint() !== before) this.notifyListeners();
2375
+ }
2376
+ /**
2377
+ * Verifies an access token, throwing GrpcError(UNAUTHENTICATED) with a short reason on failure.
2378
+ * `options.now` is epoch milliseconds. An `unknown kid` triggers a throttled (at most once
2379
+ * per 10 s) background refetch of the config, to pick up a rotation sooner.
2380
+ */
2381
+ verify(token, options) {
2382
+ if (!this._signing) {
2383
+ throw new GrpcError5(status7.UNAUTHENTICATED, "verifier not ready");
2384
+ }
2385
+ try {
2386
+ return verifyAccessToken(
2387
+ token,
2388
+ { tokenVersion: this._tokenVersion, signing: this._signing },
2389
+ options
2390
+ );
2391
+ } catch (e) {
2392
+ if (e.message === "unknown kid") void this.refetch();
2393
+ throw e;
2394
+ }
2395
+ }
2396
+ };
2397
+
1866
2398
  // src/routing/RoutingController.ts
1867
- import { status as status4 } from "@grpc/grpc-js";
2399
+ import { status as status8 } from "@grpc/grpc-js";
1868
2400
  var RoutingController = class {
1869
2401
  _routeHandlers = {};
1870
2402
  handleRequest(call, callback) {
@@ -1872,7 +2404,7 @@ var RoutingController = class {
1872
2404
  this._routeHandlers[call.request.functionName](call, callback);
1873
2405
  } else {
1874
2406
  callback({
1875
- code: status4.NOT_FOUND,
2407
+ code: status8.NOT_FOUND,
1876
2408
  message: "Not found"
1877
2409
  });
1878
2410
  }
@@ -1931,13 +2463,13 @@ var ManagedModule = class extends ConduitServiceModule {
1931
2463
  await this.preRegisterLifecycle();
1932
2464
  await this.grpcSdk.config.registerModule(this.name, this.address, this.healthState);
1933
2465
  } catch (err) {
1934
- ConduitGrpcSdk8.Logger.error("Failed to initialize server");
1935
- ConduitGrpcSdk8.Logger.error(err);
2466
+ ConduitGrpcSdk11.Logger.error("Failed to initialize server");
2467
+ ConduitGrpcSdk11.Logger.error(err);
1936
2468
  process.exit(-1);
1937
2469
  }
1938
2470
  await this.postRegisterLifecycle().catch((err) => {
1939
- ConduitGrpcSdk8.Logger.error("Failed to activate module");
1940
- ConduitGrpcSdk8.Logger.error(err);
2471
+ ConduitGrpcSdk11.Logger.error("Failed to activate module");
2472
+ ConduitGrpcSdk11.Logger.error(err);
1941
2473
  process.exit(-1);
1942
2474
  });
1943
2475
  }
@@ -2004,11 +2536,11 @@ var ManagedModule = class extends ConduitServiceModule {
2004
2536
  * Registers common and module-specific metric types.
2005
2537
  */
2006
2538
  async registerMetrics() {
2007
- if (ConduitGrpcSdk8.Metrics) {
2008
- ConduitGrpcSdk8.Metrics.initializeDefaultMetrics();
2539
+ if (ConduitGrpcSdk11.Metrics) {
2540
+ ConduitGrpcSdk11.Metrics.initializeDefaultMetrics();
2009
2541
  if (this.metricsSchema) {
2010
2542
  Object.values(this.metricsSchema).forEach((metric) => {
2011
- ConduitGrpcSdk8.Metrics.registerMetric(metric.type, metric.config);
2543
+ ConduitGrpcSdk11.Metrics.registerMetric(metric.type, metric.config);
2012
2544
  });
2013
2545
  }
2014
2546
  }
@@ -2032,7 +2564,7 @@ var ManagedModule = class extends ConduitServiceModule {
2032
2564
  const known = new Set(this.grpcSdk.getKnownModuleNames());
2033
2565
  for (const n of names) {
2034
2566
  if (!known.has(n)) {
2035
- ConduitGrpcSdk8.Logger.warn(
2567
+ ConduitGrpcSdk11.Logger.warn(
2036
2568
  `Declared Conduit peer "${n}" is not a known built-in module (see ConduitGrpcSdk.getKnownModuleNames).`
2037
2569
  );
2038
2570
  }
@@ -2093,18 +2625,19 @@ var ManagedModule = class extends ConduitServiceModule {
2093
2625
  this.service.functions
2094
2626
  );
2095
2627
  }
2628
+ RoutingManager.grpcSdk = this.grpcSdk;
2096
2629
  RoutingManager.ClientController = new RoutingController();
2097
2630
  RoutingManager.AdminController = new RoutingController();
2098
2631
  await this.addHealthCheckService();
2099
2632
  await this.addModuleService();
2100
2633
  await this.grpcServer.start();
2101
- ConduitGrpcSdk8.Logger.log("gRPC server listening on " + this._port);
2634
+ ConduitGrpcSdk11.Logger.log("gRPC server listening on " + this._port);
2102
2635
  }
2103
2636
  async setConfig(call, callback) {
2104
2637
  try {
2105
2638
  if (!this.config) {
2106
2639
  return callback({
2107
- code: status5.INVALID_ARGUMENT,
2640
+ code: status9.INVALID_ARGUMENT,
2108
2641
  message: "Module is not configurable"
2109
2642
  });
2110
2643
  }
@@ -2123,7 +2656,7 @@ var ManagedModule = class extends ConduitServiceModule {
2123
2656
  this.config = convict(this.configSchema);
2124
2657
  this.config.load(previousConfig);
2125
2658
  return callback({
2126
- code: status5.INVALID_ARGUMENT,
2659
+ code: status9.INVALID_ARGUMENT,
2127
2660
  message: "Invalid configuration values: " + e.message
2128
2661
  });
2129
2662
  }
@@ -2132,7 +2665,7 @@ var ManagedModule = class extends ConduitServiceModule {
2132
2665
  await this._drainConfigQueue();
2133
2666
  this.grpcSdk.bus?.publish(kebabCase(this.name) + ":config:update", configJson);
2134
2667
  } catch (e) {
2135
- return callback({ code: status5.INTERNAL, message: e.message });
2668
+ return callback({ code: status9.INTERNAL, message: e.message });
2136
2669
  }
2137
2670
  }
2138
2671
  /** Used to update the module's configuration on initial Redis/DB reconciliation. */
@@ -2212,8 +2745,8 @@ var ManagedModule = class extends ConduitServiceModule {
2212
2745
  };
2213
2746
 
2214
2747
  // src/classes/ModuleError.ts
2215
- import { GrpcError as GrpcError2 } from "@conduitplatform/grpc-sdk";
2216
- var ModuleError = class extends GrpcError2 {
2748
+ import { GrpcError as GrpcError6 } from "@conduitplatform/grpc-sdk";
2749
+ var ModuleError = class extends GrpcError6 {
2217
2750
  debugLogInfo;
2218
2751
  constructor(errorDefinition, debugLogInfo) {
2219
2752
  const { grpcCode, conduitCode, message } = errorDefinition;
@@ -2228,6 +2761,8 @@ var ModuleError = class extends GrpcError2 {
2228
2761
  }
2229
2762
  };
2230
2763
  export {
2764
+ AUTHENTICATION_CONFIG_UPDATE_CHANNEL,
2765
+ AccessTokenVerifier,
2231
2766
  ConduitActiveSchema,
2232
2767
  ConduitBoolean,
2233
2768
  ConduitDate,
@@ -2238,6 +2773,7 @@ export {
2238
2773
  ConduitServiceModule,
2239
2774
  ConduitString,
2240
2775
  ConfigController,
2776
+ DEFAULT_LEEWAY_SECONDS,
2241
2777
  DEFAULT_STRIP_FIELDS,
2242
2778
  GrpcServer,
2243
2779
  ManagedModule,
@@ -2250,20 +2786,27 @@ export {
2250
2786
  convictConfigParser,
2251
2787
  createParsedRouterRequest,
2252
2788
  createServer,
2789
+ createUserHydrator,
2253
2790
  exportModel,
2791
+ getAuthMiddlewareKind,
2792
+ hydrateContextUser,
2254
2793
  importModel,
2255
2794
  initializeSdk,
2256
2795
  linearBackoffTimeout,
2257
2796
  linearBackoffTimeoutAsync,
2797
+ mapHydrationErrorCode,
2258
2798
  merge,
2259
2799
  readConduitPeersManifest,
2260
2800
  reconcileStoredModuleConfig,
2261
2801
  redactSensitiveConfig,
2262
2802
  restoreRedactedSecrets,
2263
2803
  sanitizeDocumentsForExport,
2804
+ selectVerificationKey,
2805
+ shouldHydrateUser,
2264
2806
  stableConfigJson,
2265
2807
  storedConfigsEquivalent,
2266
2808
  stripInternalFields,
2809
+ verifyAccessToken,
2267
2810
  wrapFunctionsAsync,
2268
2811
  wrapGrpcFunctions,
2269
2812
  wrapRouterGrpcFunction