@discover-cloud/shared 1.2.9 → 1.3.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.
Files changed (165) hide show
  1. package/dist/authorization/index.d.ts +1 -1
  2. package/dist/authorization/index.js +1 -1
  3. package/dist/authorization/permission-cache.service.d.ts +104 -16
  4. package/dist/authorization/permission-cache.service.js +156 -143
  5. package/dist/authorization/permission-checker.d.ts +30 -0
  6. package/dist/authorization/permission-checker.js +40 -0
  7. package/dist/contracts/auth-service/account.dto.d.ts +30 -0
  8. package/dist/contracts/auth-service/account.dto.js +7 -0
  9. package/dist/contracts/auth-service/auth.dto.d.ts +21 -0
  10. package/dist/contracts/auth-service/auth.dto.js +10 -0
  11. package/dist/dtos/auth-service.dto.d.ts +72 -26
  12. package/dist/dtos/auth-service.dto.js +4 -0
  13. package/dist/dtos/cloud-service.dto.d.ts +51 -27
  14. package/dist/dtos/cloud-service.dto.js +5 -0
  15. package/dist/dtos/insights-service.dto.d.ts +18 -27
  16. package/dist/dtos/insights-service.dto.js +8 -0
  17. package/dist/dtos/response.dto.d.ts +7 -84
  18. package/dist/dtos/response.dto.js +2 -21
  19. package/dist/dtos/user-service.dto.d.ts +118 -13
  20. package/dist/enums/domain.enums.d.ts +246 -75
  21. package/dist/enums/domain.enums.js +305 -102
  22. package/dist/enums/permissions.enums.d.ts +142 -80
  23. package/dist/enums/permissions.enums.js +174 -133
  24. package/dist/errors/app-error.d.ts +13 -18
  25. package/dist/errors/app-error.js +14 -20
  26. package/dist/errors/http-errors.d.ts +105 -17
  27. package/dist/errors/http-errors.js +118 -33
  28. package/dist/http/index.d.ts +1 -0
  29. package/dist/http/index.js +1 -0
  30. package/dist/http/request-context.d.ts +8 -0
  31. package/dist/http/request-context.js +37 -0
  32. package/dist/http/service-client.d.ts +91 -38
  33. package/dist/http/service-client.js +102 -53
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +1 -0
  36. package/dist/jwt/index.d.ts +2 -1
  37. package/dist/jwt/index.js +2 -1
  38. package/dist/jwt/machine-jwt-verifier.d.ts +21 -0
  39. package/dist/jwt/machine-jwt-verifier.js +84 -0
  40. package/dist/jwt/machine-token-client.d.ts +35 -4
  41. package/dist/jwt/machine-token-client.js +57 -23
  42. package/dist/jwt/user-jwt-verifier.d.ts +31 -0
  43. package/dist/jwt/user-jwt-verifier.js +101 -0
  44. package/dist/messaging/index.d.ts +1 -0
  45. package/dist/{security → messaging}/index.js +1 -1
  46. package/dist/messaging/rabbitmq.client.d.ts +13 -0
  47. package/dist/messaging/rabbitmq.client.js +127 -0
  48. package/dist/middleware/error-handler.middleware.d.ts +8 -28
  49. package/dist/middleware/error-handler.middleware.js +61 -52
  50. package/dist/middleware/index.d.ts +7 -5
  51. package/dist/middleware/index.js +7 -5
  52. package/dist/middleware/request-context.middleware.d.ts +17 -0
  53. package/dist/middleware/request-context.middleware.js +73 -0
  54. package/dist/middleware/require-auth.middleware.d.ts +17 -70
  55. package/dist/middleware/require-auth.middleware.js +24 -103
  56. package/dist/middleware/require-machine.middleware.d.ts +38 -0
  57. package/dist/middleware/require-machine.middleware.js +123 -0
  58. package/dist/middleware/require-org-permission-from-body.middleware.d.ts +10 -0
  59. package/dist/middleware/require-org-permission-from-body.middleware.js +24 -0
  60. package/dist/middleware/require-org-permission.middleware.d.ts +19 -0
  61. package/dist/middleware/require-org-permission.middleware.js +115 -0
  62. package/dist/middleware/require-platform-permission.middleware.d.ts +19 -0
  63. package/dist/middleware/require-platform-permission.middleware.js +91 -0
  64. package/dist/middleware/require-user.middleware.d.ts +14 -0
  65. package/dist/middleware/require-user.middleware.js +30 -0
  66. package/dist/middleware/require-workspace-permission.middleware.d.ts +20 -0
  67. package/dist/middleware/require-workspace-permission.middleware.js +114 -0
  68. package/dist/middleware/validate.middleware.d.ts +29 -29
  69. package/dist/middleware/validate.middleware.js +30 -32
  70. package/dist/types/express.types.d.ts +83 -122
  71. package/dist/types/express.types.js +28 -47
  72. package/dist/utils/date.util.d.ts +6 -0
  73. package/dist/utils/date.util.js +11 -0
  74. package/dist/utils/env.util.d.ts +6 -0
  75. package/dist/utils/env.util.js +19 -0
  76. package/dist/utils/index.d.ts +5 -4
  77. package/dist/utils/index.js +5 -4
  78. package/dist/utils/logger.util.d.ts +26 -0
  79. package/dist/utils/logger.util.js +53 -0
  80. package/dist/utils/pagination.util.d.ts +6 -0
  81. package/dist/utils/pagination.util.js +20 -0
  82. package/dist/utils/response.util.d.ts +27 -0
  83. package/dist/utils/response.util.js +56 -0
  84. package/dist/utils/slug.util.d.ts +9 -0
  85. package/dist/utils/slug.util.js +32 -0
  86. package/dist/utils/url-safety.util.d.ts +6 -0
  87. package/dist/utils/url-safety.util.js +72 -0
  88. package/package.json +3 -1
  89. package/dist/authorization/permissions.d.ts +0 -78
  90. package/dist/authorization/permissions.js +0 -174
  91. package/dist/context/access-context.d.ts +0 -10
  92. package/dist/context/access-context.js +0 -2
  93. package/dist/context/index.d.ts +0 -1
  94. package/dist/context/index.js +0 -17
  95. package/dist/dto/auth-service.dtos.d.ts +0 -44
  96. package/dist/dto/auth-service.dtos.js +0 -2
  97. package/dist/dto/index.d.ts +0 -3
  98. package/dist/dto/index.js +0 -19
  99. package/dist/dto/response.dtos.d.ts +0 -55
  100. package/dist/dto/response.dtos.js +0 -6
  101. package/dist/dto/user-service.dtos.d.ts +0 -50
  102. package/dist/dto/user-service.dtos.js +0 -2
  103. package/dist/enums/auth-service.enums.d.ts +0 -12
  104. package/dist/enums/auth-service.enums.js +0 -17
  105. package/dist/enums/permissions.types.d.ts +0 -12
  106. package/dist/enums/permissions.types.js +0 -17
  107. package/dist/enums/user-service.enums.d.ts +0 -32
  108. package/dist/enums/user-service.enums.js +0 -41
  109. package/dist/internal/index.d.ts +0 -4
  110. package/dist/internal/index.js +0 -20
  111. package/dist/internal/internal-jwt.service.d.ts +0 -13
  112. package/dist/internal/internal-jwt.service.js +0 -88
  113. package/dist/internal/internal-jwt.types.d.ts +0 -7
  114. package/dist/internal/internal-jwt.types.js +0 -2
  115. package/dist/internal/internal-key-manager.d.ts +0 -16
  116. package/dist/internal/internal-key-manager.js +0 -67
  117. package/dist/internal/registry.d.ts +0 -8
  118. package/dist/internal/registry.js +0 -34
  119. package/dist/internal/service-client.d.ts +0 -9
  120. package/dist/internal/service-client.js +0 -94
  121. package/dist/jwt/internal-jwt-verifier.d.ts +0 -41
  122. package/dist/jwt/internal-jwt-verifier.js +0 -185
  123. package/dist/jwt/jwt-verifier.d.ts +0 -9
  124. package/dist/jwt/jwt-verifier.js +0 -36
  125. package/dist/jwt/service-client.d.ts +0 -7
  126. package/dist/jwt/service-client.js +0 -87
  127. package/dist/middleware/authorize.d.ts +0 -3
  128. package/dist/middleware/authorize.js +0 -24
  129. package/dist/middleware/authorize.middleware.d.ts +0 -54
  130. package/dist/middleware/authorize.middleware.js +0 -104
  131. package/dist/middleware/error-handler.d.ts +0 -4
  132. package/dist/middleware/error-handler.js +0 -23
  133. package/dist/middleware/request-id.d.ts +0 -2
  134. package/dist/middleware/request-id.js +0 -9
  135. package/dist/middleware/request-id.middleware.d.ts +0 -22
  136. package/dist/middleware/request-id.middleware.js +0 -34
  137. package/dist/middleware/require-auth.d.ts +0 -10
  138. package/dist/middleware/require-auth.js +0 -34
  139. package/dist/middleware/require-human.middleware.d.ts +0 -2
  140. package/dist/middleware/require-human.middleware.js +0 -18
  141. package/dist/middleware/require-internal.middleware.d.ts +0 -18
  142. package/dist/middleware/require-internal.middleware.js +0 -183
  143. package/dist/middleware/validate.d.ts +0 -5
  144. package/dist/middleware/validate.js +0 -18
  145. package/dist/middleware/validated-merge.middleware.d.ts +0 -20
  146. package/dist/middleware/validated-merge.middleware.js +0 -33
  147. package/dist/middleware/verify-internal-jwt.d.ts +0 -7
  148. package/dist/middleware/verify-internal-jwt.js +0 -25
  149. package/dist/security/guard.d.ts +0 -10
  150. package/dist/security/guard.js +0 -40
  151. package/dist/security/index.d.ts +0 -1
  152. package/dist/types/express.d.ts +0 -22
  153. package/dist/types/express.js +0 -3
  154. package/dist/utils/date.utils.d.ts +0 -25
  155. package/dist/utils/date.utils.js +0 -30
  156. package/dist/utils/env.d.ts +0 -46
  157. package/dist/utils/env.js +0 -61
  158. package/dist/utils/env.utils.d.ts +0 -46
  159. package/dist/utils/env.utils.js +0 -61
  160. package/dist/utils/logger.utils.d.ts +0 -66
  161. package/dist/utils/logger.utils.js +0 -97
  162. package/dist/utils/response.d.ts +0 -4
  163. package/dist/utils/response.js +0 -35
  164. package/dist/utils/response.utils.d.ts +0 -54
  165. package/dist/utils/response.utils.js +0 -85
@@ -1,4 +1,10 @@
1
1
  "use strict";
2
+ /**
3
+ * @file service-client.ts
4
+ * @description HTTP client wrapper for service-to-service communication.
5
+ * Handles automatic JWT forwarding, request correlation tracking via header propagation,
6
+ * and automatic retry behaviors on transient failures.
7
+ */
2
8
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
9
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
10
  };
@@ -7,35 +13,15 @@ exports.ServiceClient = void 0;
7
13
  const axios_1 = __importDefault(require("axios"));
8
14
  const axios_retry_1 = __importDefault(require("axios-retry"));
9
15
  /**
10
- * SERVICE CLIENT (@discover-cloud/shared)
11
- * ─────────────────────────────────────────
12
- * HTTP client for service-to-service communication.
13
- *
14
- * Two call patterns:
15
- *
16
- * Pattern 1 — JWT-forwarding (user-initiated requests)
17
- * Pass the current Express Request — Authorization + x-request-id are
18
- * forwarded automatically. Used when the downstream service needs to
19
- * act on behalf of the authenticated user.
20
- * Methods: getWithAuth, postWithAuth, patchWithAuth, deleteWithAuth
21
- *
22
- * Pattern 2 — Internal calls (service-initiated, no incoming request)
23
- * Pass explicit headers — used when calls originate from service logic
24
- * rather than from an HTTP handler (e.g. auth service → user service
25
- * during account creation). Caller is responsible for providing the
26
- * X-Internal-Secret header.
27
- * Methods: get, post, patch, delete
28
- *
29
- * Retry strategy:
30
- * - Retries on network errors and 5xx responses only (up to 3 attempts,
31
- * exponential backoff). 4xx responses are never retried — they are
32
- * deterministic caller errors that won't resolve on retry.
33
- *
34
- * Timeout:
35
- * - 8 seconds per request (covers retry delays separately via axiosRetry).
36
- * Adjust per-call via config.timeout if a specific route needs more.
16
+ * ServiceClient encapsulates an AxiosInstance configured for service-to-service HTTP requests.
17
+ * Supports token forwarding (Pattern 1) and secure internal calls (Pattern 2).
37
18
  */
38
19
  class ServiceClient {
20
+ /**
21
+ * Initializes the Axios instance with a base URL, timeout, and retry rules.
22
+ *
23
+ * @param {string} baseURL - Downstream service base URL.
24
+ */
39
25
  constructor(baseURL) {
40
26
  this.http = axios_1.default.create({
41
27
  baseURL,
@@ -45,62 +31,123 @@ class ServiceClient {
45
31
  retries: 3,
46
32
  retryDelay: axios_retry_1.default.exponentialDelay,
47
33
  retryCondition: (err) => {
48
- // Retry network-level errors (no response received)
49
34
  if (axios_retry_1.default.isNetworkError(err))
50
35
  return true;
51
- // Retry transient server errors; never retry client errors
52
36
  const status = err.response?.status ?? 0;
53
37
  return status >= 500;
54
38
  },
55
39
  });
56
40
  }
57
- /* ----------------------------------------------------------------
58
- Pattern 1 — JWT-forwarding (pass Express req)
59
- Forwards Authorization header + x-request-id automatically.
60
- Use for endpoints that require a user identity downstream.
61
- ---------------------------------------------------------------- */
41
+ /* ---------------------------------------------------------------------------
42
+ Pattern 1 — JWT-forwarding (pass Express Request)
43
+ Forwards authorization tokens and request correlation IDs automatically.
44
+ --------------------------------------------------------------------------- */
45
+ /**
46
+ * Performs an HTTP GET request while forwarding authorization and request headers.
47
+ *
48
+ * @param {string} url - Request target endpoint relative path.
49
+ * @param {Request} req - The current Express request object.
50
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
51
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
52
+ */
62
53
  async getWithAuth(url, req, config) {
63
54
  return this.http.get(url, this.mergeAuth(req, config));
64
55
  }
56
+ /**
57
+ * Performs an HTTP POST request while forwarding authorization and request headers.
58
+ *
59
+ * @param {string} url - Request target endpoint relative path.
60
+ * @param {unknown} data - JSON request body data payload.
61
+ * @param {Request} req - The current Express request object.
62
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
63
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
64
+ */
65
65
  async postWithAuth(url, data, req, config) {
66
66
  return this.http.post(url, data, this.mergeAuth(req, config));
67
67
  }
68
+ /**
69
+ * Performs an HTTP PATCH request while forwarding authorization and request headers.
70
+ *
71
+ * @param {string} url - Request target endpoint relative path.
72
+ * @param {unknown} data - JSON request body data payload.
73
+ * @param {Request} req - The current Express request object.
74
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
75
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
76
+ */
68
77
  async patchWithAuth(url, data, req, config) {
69
78
  return this.http.patch(url, data, this.mergeAuth(req, config));
70
79
  }
80
+ /**
81
+ * Performs an HTTP DELETE request while forwarding authorization and request headers.
82
+ *
83
+ * @param {string} url - Request target endpoint relative path.
84
+ * @param {Request} req - The current Express request object.
85
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
86
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
87
+ */
71
88
  async deleteWithAuth(url, req, config) {
72
89
  return this.http.delete(url, this.mergeAuth(req, config));
73
90
  }
74
- /* ----------------------------------------------------------------
75
- Pattern 2 — Internal calls (explicit headers, no Express req)
76
- Used for service-initiated calls where there is no incoming HTTP
77
- request to forward from. Caller must supply X-Internal-Secret.
78
- ---------------------------------------------------------------- */
91
+ /* ---------------------------------------------------------------------------
92
+ Pattern 2 — Internal calls (explicit headers, no Express Request)
93
+ Used for background tasks or service-initiated operations without a request context.
94
+ --------------------------------------------------------------------------- */
95
+ /**
96
+ * Performs an HTTP GET request with explicit header configurations.
97
+ *
98
+ * @param {string} url - Request target endpoint relative path.
99
+ * @param {Record<string, string>} headers - Header keys and values to attach.
100
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
101
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
102
+ */
79
103
  async get(url, headers, config) {
80
104
  return this.http.get(url, this.mergeHeaders(headers, config));
81
105
  }
106
+ /**
107
+ * Performs an HTTP POST request with explicit header configurations.
108
+ *
109
+ * @param {string} url - Request target endpoint relative path.
110
+ * @param {unknown} data - JSON request body data payload.
111
+ * @param {Record<string, string>} headers - Header keys and values to attach.
112
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
113
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
114
+ */
82
115
  async post(url, data, headers, config) {
83
116
  return this.http.post(url, data, this.mergeHeaders(headers, config));
84
117
  }
118
+ /**
119
+ * Performs an HTTP PATCH request with explicit header configurations.
120
+ *
121
+ * @param {string} url - Request target endpoint relative path.
122
+ * @param {unknown} data - JSON request body data payload.
123
+ * @param {Record<string, string>} headers - Header keys and values to attach.
124
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
125
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
126
+ */
85
127
  async patch(url, data, headers, config) {
86
128
  return this.http.patch(url, data, this.mergeHeaders(headers, config));
87
129
  }
130
+ /**
131
+ * Performs an HTTP DELETE request with explicit header configurations.
132
+ *
133
+ * @param {string} url - Request target endpoint relative path.
134
+ * @param {Record<string, string>} headers - Header keys and values to attach.
135
+ * @param {AxiosRequestConfig} [config] - Optional request configuration parameters.
136
+ * @returns {Promise<AxiosResponse<T>>} Axios response promise.
137
+ */
88
138
  async delete(url, headers, config) {
89
139
  return this.http.delete(url, this.mergeHeaders(headers, config));
90
140
  }
91
- /* ----------------------------------------------------------------
92
- Private helpers
93
- ---------------------------------------------------------------- */
141
+ /* ---------------------------------------------------------------------------
142
+ Private Helpers
143
+ --------------------------------------------------------------------------- */
94
144
  /**
95
- * mergeAuth
96
- * Extracts Authorization and x-request-id from the Express request
97
- * and merges them into the Axios config headers.
145
+ * Extracts authorization credentials and tracing identifiers from Express requests
146
+ * and merges them into Axios config header values.
98
147
  *
99
- * x-request-id precedence:
100
- * 1. req.id set by express-request-id or equivalent middleware
101
- * 2. x-request-id header forwarded from the upstream caller
102
- * 3. Synthetic fallback (timestamp) — should not appear in production
103
- * if request-id middleware is wired correctly in the gateway
148
+ * @param {Request} req - The current Express request.
149
+ * @param {AxiosRequestConfig} [config] - The existing Axios request configuration.
150
+ * @returns {AxiosRequestConfig} The merged Axios request configuration.
104
151
  */
105
152
  mergeAuth(req, config) {
106
153
  const authHeader = req.headers.authorization;
@@ -116,9 +163,11 @@ class ServiceClient {
116
163
  };
117
164
  }
118
165
  /**
119
- * mergeHeaders
120
- * Merges caller-supplied headers into the Axios config.
121
- * Caller-supplied headers take precedence over config.headers.
166
+ * Integrates user-supplied headers into the request configuration object.
167
+ *
168
+ * @param {Record<string, string>} headers - The headers to merge.
169
+ * @param {AxiosRequestConfig} [config] - The existing Axios request configuration.
170
+ * @returns {AxiosRequestConfig} The merged Axios request configuration.
122
171
  */
123
172
  mergeHeaders(headers, config) {
124
173
  return {
package/dist/index.d.ts CHANGED
@@ -7,3 +7,4 @@ export * from "./middleware";
7
7
  export * from "./types";
8
8
  export * from "./jwt";
9
9
  export * from "./http";
10
+ export * from "./messaging";
package/dist/index.js CHANGED
@@ -23,3 +23,4 @@ __exportStar(require("./middleware"), exports);
23
23
  __exportStar(require("./types"), exports);
24
24
  __exportStar(require("./jwt"), exports);
25
25
  __exportStar(require("./http"), exports);
26
+ __exportStar(require("./messaging"), exports);
@@ -1,2 +1,3 @@
1
- export * from "./internal-jwt-verifier";
1
+ export * from "./user-jwt-verifier";
2
+ export * from "./machine-jwt-verifier";
2
3
  export * from "./machine-token-client";
package/dist/jwt/index.js CHANGED
@@ -14,5 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./internal-jwt-verifier"), exports);
17
+ __exportStar(require("./user-jwt-verifier"), exports);
18
+ __exportStar(require("./machine-jwt-verifier"), exports);
18
19
  __exportStar(require("./machine-token-client"), exports);
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @file machine-jwt-verifier.ts
3
+ * @description Verifies service-to-service RS256 machine JWTs issued by auth-service.
4
+ */
5
+ import { MachineTokenPayload } from "../types";
6
+ /**
7
+ * Verifies auth-service issued machine tokens used for service-to-service calls.
8
+ */
9
+ export declare class MachineJwtVerifier {
10
+ private readonly jwks;
11
+ private readonly issuer;
12
+ private readonly audience;
13
+ constructor(authServiceJwksUri?: string);
14
+ /**
15
+ * Verify machine JWT signature and claims.
16
+ *
17
+ * @param {string} token - Raw bearer machine token.
18
+ * @returns {Promise<MachineTokenPayload>} Verified machine payload.
19
+ */
20
+ verify(token: string): Promise<MachineTokenPayload>;
21
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ /**
3
+ * @file machine-jwt-verifier.ts
4
+ * @description Verifies service-to-service RS256 machine JWTs issued by auth-service.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.MachineJwtVerifier = void 0;
41
+ const jose = __importStar(require("jose"));
42
+ const CLOCK_TOLERANCE_SECONDS = 30;
43
+ const JWKS_CACHE_MAX_AGE_MS = 10 * 60 * 1000;
44
+ const JWKS_FETCH_TIMEOUT_MS = 5000;
45
+ /**
46
+ * Verifies auth-service issued machine tokens used for service-to-service calls.
47
+ */
48
+ class MachineJwtVerifier {
49
+ constructor(authServiceJwksUri) {
50
+ const jwksUri = authServiceJwksUri ??
51
+ process.env.AUTH_JWKS_URI ??
52
+ "http://auth-service:3001/.well-known/jwks.json";
53
+ this.issuer = process.env.MACHINE_JWT_ISSUER ?? "discover-cloud:auth-service";
54
+ this.audience = process.env.MACHINE_JWT_AUDIENCE ?? "discover-cloud:services";
55
+ this.jwks = jose.createRemoteJWKSet(new URL(jwksUri), {
56
+ cacheMaxAge: JWKS_CACHE_MAX_AGE_MS,
57
+ timeoutDuration: JWKS_FETCH_TIMEOUT_MS,
58
+ });
59
+ }
60
+ /**
61
+ * Verify machine JWT signature and claims.
62
+ *
63
+ * @param {string} token - Raw bearer machine token.
64
+ * @returns {Promise<MachineTokenPayload>} Verified machine payload.
65
+ */
66
+ async verify(token) {
67
+ const { payload } = await jose.jwtVerify(token, this.jwks, {
68
+ issuer: this.issuer,
69
+ audience: this.audience,
70
+ algorithms: ["RS256"],
71
+ clockTolerance: CLOCK_TOLERANCE_SECONDS,
72
+ });
73
+ if (payload.typ !== "machine") {
74
+ throw new jose.errors.JWTClaimValidationFailed(`Token type mismatch: expected "machine", got "${String(payload.typ)}"`, payload, "typ", "check_failed");
75
+ }
76
+ if (typeof payload.serviceId !== "string" ||
77
+ typeof payload.jti !== "string" ||
78
+ !Array.isArray(payload.scopes)) {
79
+ throw new jose.errors.JWTClaimValidationFailed("Missing required machine token claims", payload, "payload", "missing");
80
+ }
81
+ return payload;
82
+ }
83
+ }
84
+ exports.MachineJwtVerifier = MachineJwtVerifier;
@@ -1,13 +1,44 @@
1
+ /**
2
+ * @file machine-token-client.ts
3
+ * @description HTTP client for fetching and caching short-lived machine JWTs
4
+ * from the Auth Service for service-to-service communication.
5
+ */
1
6
  import { ILogger } from "../utils";
7
+ /**
8
+ * Handles retrieving and caching auth-service issued machine JWTs.
9
+ */
2
10
  export declare class MachineTokenClient {
3
- private readonly gatewayUrl;
11
+ private readonly authServiceUrl;
4
12
  private readonly serviceId;
5
- private readonly internalSecret?;
13
+ private readonly serviceSecret;
6
14
  private readonly logger;
7
15
  private cache;
8
16
  private fetchPromise;
9
- constructor(gatewayUrl: string, serviceId: string, internalSecret?: string | undefined, logger?: ILogger);
17
+ /**
18
+ * @param {string} authServiceUrl - Base URL of the Auth Service.
19
+ * @param {string} serviceId - The service ID identifying the calling microservice.
20
+ * @param {string} serviceSecret - Service-specific secret for authentication.
21
+ * @param {ILogger} [logger] - Optional logger instance.
22
+ */
23
+ constructor(authServiceUrl: string, serviceId: string, serviceSecret: string, logger?: ILogger);
24
+ /**
25
+ * Returns a valid machine JWT.
26
+ *
27
+ * @param {string} [requestId] - Request ID for distributed tracing.
28
+ * @returns {Promise<string>} The machine JWT token string.
29
+ */
10
30
  getToken(requestId?: string): Promise<string>;
11
- private getValidCachedToken;
31
+ /**
32
+ * Gets the cached token if it exists and is not within the refresh buffer window.
33
+ *
34
+ * @returns {CachedToken | null} The cached token, or null if invalid/expired.
35
+ */
36
+ private getCachedToken;
37
+ /**
38
+ * Performs the HTTP request to the Auth Service to retrieve a machine token.
39
+ *
40
+ * @param {string} [requestId] - Request ID for tracing.
41
+ * @returns {Promise<string>} The freshly issued machine token.
42
+ */
12
43
  private fetchToken;
13
44
  }
@@ -1,21 +1,41 @@
1
1
  "use strict";
2
+ /**
3
+ * @file machine-token-client.ts
4
+ * @description HTTP client for fetching and caching short-lived machine JWTs
5
+ * from the Auth Service for service-to-service communication.
6
+ */
2
7
  Object.defineProperty(exports, "__esModule", { value: true });
3
8
  exports.MachineTokenClient = void 0;
4
9
  const utils_1 = require("../utils");
5
- const REFRESH_BUFFER_S = 10;
10
+ const REFRESH_BUFFER_SECONDS = 60;
11
+ /**
12
+ * Handles retrieving and caching auth-service issued machine JWTs.
13
+ */
6
14
  class MachineTokenClient {
7
- constructor(gatewayUrl, serviceId, internalSecret, logger = utils_1.noopLogger) {
8
- this.gatewayUrl = gatewayUrl;
15
+ /**
16
+ * @param {string} authServiceUrl - Base URL of the Auth Service.
17
+ * @param {string} serviceId - The service ID identifying the calling microservice.
18
+ * @param {string} serviceSecret - Service-specific secret for authentication.
19
+ * @param {ILogger} [logger] - Optional logger instance.
20
+ */
21
+ constructor(authServiceUrl, serviceId, serviceSecret, logger = utils_1.noopLogger) {
22
+ this.authServiceUrl = authServiceUrl;
9
23
  this.serviceId = serviceId;
10
- this.internalSecret = internalSecret;
24
+ this.serviceSecret = serviceSecret;
11
25
  this.logger = logger;
12
26
  this.cache = null;
13
27
  this.fetchPromise = null;
14
28
  }
29
+ /**
30
+ * Returns a valid machine JWT.
31
+ *
32
+ * @param {string} [requestId] - Request ID for distributed tracing.
33
+ * @returns {Promise<string>} The machine JWT token string.
34
+ */
15
35
  async getToken(requestId) {
16
- const cachedToken = this.getValidCachedToken();
17
- if (cachedToken) {
18
- return cachedToken.token;
36
+ const cached = this.getCachedToken();
37
+ if (cached) {
38
+ return cached.token;
19
39
  }
20
40
  if (!this.fetchPromise) {
21
41
  this.fetchPromise = this.fetchToken(requestId).finally(() => {
@@ -24,44 +44,58 @@ class MachineTokenClient {
24
44
  }
25
45
  return this.fetchPromise;
26
46
  }
27
- getValidCachedToken() {
47
+ /**
48
+ * Gets the cached token if it exists and is not within the refresh buffer window.
49
+ *
50
+ * @returns {CachedToken | null} The cached token, or null if invalid/expired.
51
+ */
52
+ getCachedToken() {
28
53
  if (!this.cache) {
29
54
  return null;
30
55
  }
31
- const nowS = Math.floor(Date.now() / 1000);
32
- if (this.cache.expiresAt - REFRESH_BUFFER_S <= nowS) {
56
+ const now = Math.floor(Date.now() / 1000);
57
+ if (this.cache.expiresAt - REFRESH_BUFFER_SECONDS <= now) {
33
58
  return null;
34
59
  }
35
60
  return this.cache;
36
61
  }
62
+ /**
63
+ * Performs the HTTP request to the Auth Service to retrieve a machine token.
64
+ *
65
+ * @param {string} [requestId] - Request ID for tracing.
66
+ * @returns {Promise<string>} The freshly issued machine token.
67
+ */
37
68
  async fetchToken(requestId) {
38
- const url = `${this.gatewayUrl}/internal/machine-token`;
69
+ const url = `${this.authServiceUrl.replace(/\/$/, "")}/internal/machine-token`;
39
70
  this.logger.debug({ serviceId: this.serviceId, requestId }, "Fetching machine token");
40
- const headers = {
41
- "content-type": "application/json",
42
- };
43
- if (this.internalSecret) {
44
- headers["x-internal-secret"] = this.internalSecret;
45
- }
46
71
  const response = await fetch(url, {
47
72
  method: "POST",
48
- headers,
73
+ headers: {
74
+ "content-type": "application/json",
75
+ },
49
76
  body: JSON.stringify({
50
77
  serviceId: this.serviceId,
78
+ secret: this.serviceSecret,
51
79
  requestId,
52
80
  }),
53
81
  });
54
82
  if (!response.ok) {
55
83
  const text = await response.text().catch(() => "(unreadable)");
56
- throw new Error(`MachineTokenClient: gateway returned ${response.status} fetching machine token: ${text}`);
84
+ throw new Error(`Machine token request failed (${response.status}): ${text}`);
57
85
  }
58
86
  const body = (await response.json());
59
- const nowS = Math.floor(Date.now() / 1000);
87
+ if (!body.success ||
88
+ !body.data?.accessToken ||
89
+ typeof body.data.expiresIn !== "number" ||
90
+ body.data.expiresIn <= 0) {
91
+ throw new Error("Invalid machine token response");
92
+ }
93
+ const now = Math.floor(Date.now() / 1000);
60
94
  this.cache = {
61
- token: body.data.token,
62
- expiresAt: nowS + body.data.expiresIn,
95
+ token: body.data.accessToken,
96
+ expiresAt: now + body.data.expiresIn,
63
97
  };
64
- this.logger.info({
98
+ this.logger.debug({
65
99
  serviceId: this.serviceId,
66
100
  expiresAt: this.cache.expiresAt,
67
101
  }, "Machine token cached");
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @file user-jwt-verifier.ts
3
+ * @description Verifies user RS256 access tokens issued by auth-service.
4
+ */
5
+ import { AccessTokenPayload, UserContext } from "../types";
6
+ /**
7
+ * Verifies auth-service issued user access tokens.
8
+ */
9
+ export declare class UserJwtVerifier {
10
+ private readonly jwks;
11
+ private readonly issuer;
12
+ private readonly audience;
13
+ constructor();
14
+ /**
15
+ * Verify JWT signature and required user claims.
16
+ *
17
+ * @param {string} token - Raw bearer access token.
18
+ * @returns {Promise<AccessTokenPayload>} Verified access payload.
19
+ */
20
+ verify(token: string): Promise<AccessTokenPayload>;
21
+ /**
22
+ * Builds request authorization context.
23
+ *
24
+ * @param {string} token - Raw bearer access token.
25
+ * @returns {Promise<{ payload: AccessTokenPayload; context: UserContext }>} The auth context block.
26
+ */
27
+ buildAccessContext(token: string): Promise<{
28
+ payload: AccessTokenPayload;
29
+ context: UserContext;
30
+ }>;
31
+ }
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ /**
3
+ * @file user-jwt-verifier.ts
4
+ * @description Verifies user RS256 access tokens issued by auth-service.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.UserJwtVerifier = void 0;
41
+ const jose = __importStar(require("jose"));
42
+ const CLOCK_TOLERANCE_SECONDS = 30;
43
+ const JWKS_CACHE_MAX_AGE_MS = 10 * 60 * 1000;
44
+ const JWKS_FETCH_TIMEOUT_MS = 5000;
45
+ /**
46
+ * Verifies auth-service issued user access tokens.
47
+ */
48
+ class UserJwtVerifier {
49
+ constructor() {
50
+ const authJwksUri = process.env.AUTH_JWKS_URI ?? "http://auth-service:3001/.well-known/jwks.json";
51
+ this.issuer = process.env.EXTERNAL_JWT_ISSUER ?? "discover-cloud:auth-service";
52
+ this.audience = process.env.EXTERNAL_JWT_AUDIENCE ?? "discover-cloud:api";
53
+ this.jwks = jose.createRemoteJWKSet(new URL(authJwksUri), {
54
+ cacheMaxAge: JWKS_CACHE_MAX_AGE_MS,
55
+ timeoutDuration: JWKS_FETCH_TIMEOUT_MS,
56
+ });
57
+ }
58
+ /**
59
+ * Verify JWT signature and required user claims.
60
+ *
61
+ * @param {string} token - Raw bearer access token.
62
+ * @returns {Promise<AccessTokenPayload>} Verified access payload.
63
+ */
64
+ async verify(token) {
65
+ const { payload } = await jose.jwtVerify(token, this.jwks, {
66
+ issuer: this.issuer,
67
+ audience: this.audience,
68
+ algorithms: ["RS256"],
69
+ clockTolerance: CLOCK_TOLERANCE_SECONDS,
70
+ });
71
+ if (payload.typ !== "access") {
72
+ throw new jose.errors.JWTClaimValidationFailed(`Token type mismatch: expected "access", got "${String(payload.typ)}"`, payload, "typ", "check_failed");
73
+ }
74
+ if (typeof payload.accountId !== "string" ||
75
+ typeof payload.sessionId !== "string" ||
76
+ typeof payload.jti !== "string" ||
77
+ typeof payload.iat !== "number" ||
78
+ typeof payload.exp !== "number") {
79
+ throw new jose.errors.JWTClaimValidationFailed("Missing required access token claims", payload, "payload", "missing");
80
+ }
81
+ return payload;
82
+ }
83
+ /**
84
+ * Builds request authorization context.
85
+ *
86
+ * @param {string} token - Raw bearer access token.
87
+ * @returns {Promise<{ payload: AccessTokenPayload; context: UserContext }>} The auth context block.
88
+ */
89
+ async buildAccessContext(token) {
90
+ const payload = await this.verify(token);
91
+ return {
92
+ payload,
93
+ context: {
94
+ type: "user",
95
+ accountId: payload.accountId,
96
+ sessionId: payload.sessionId,
97
+ },
98
+ };
99
+ }
100
+ }
101
+ exports.UserJwtVerifier = UserJwtVerifier;
@@ -0,0 +1 @@
1
+ export * from './rabbitmq.client';
@@ -14,4 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./guard"), exports);
17
+ __exportStar(require("./rabbitmq.client"), exports);