@discover-cloud/shared 1.2.8 → 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,53 +1,32 @@
1
1
  "use strict";
2
+ /**
3
+ * @file require-auth.middleware.ts
4
+ * @description Authentication boundary middleware. Verifies the internal gateway JWT,
5
+ * builds the auth context, and gates endpoints.
6
+ */
2
7
  Object.defineProperty(exports, "__esModule", { value: true });
3
8
  exports.RequireAuthMiddleware = void 0;
4
9
  const jose_1 = require("jose");
5
10
  const utils_1 = require("../utils");
6
- const internal_jwt_verifier_1 = require("../jwt/internal-jwt-verifier");
7
11
  /**
8
- * REQUIRE AUTH MIDDLEWARE (@discover-cloud/shared)
9
- * ─────────────────────────────────────────────────────────────────────────
10
- * Verifies the internal JWT, resolves permissions from the Redis cache,
11
- * and attaches the typed AccessContext to req.accessContext.
12
- *
13
- * Moved to shared so every downstream service (auth, user, cloud, insights)
14
- * uses the same verified implementation rather than maintaining their own copy.
15
- *
16
- * Token extraction:
17
- * Reads a Bearer token from the Authorization header.
18
- * Does not support cookie-based auth — that is the API gateway's responsibility.
19
- *
20
- * On success:
21
- * req.internalAuth → raw verified JWT payload (use for jti, caller, requestId)
22
- * req.accessContext → clean typed context (use in controllers and services)
23
- *
24
- * On failure:
25
- * Returns a structured error response and does NOT call next().
26
- * next(err) is only called for genuinely unexpected errors (not auth failures).
27
- *
28
- * Inline guards (requirePermission, requireRole):
29
- * Convenience methods for single-route guards. For router-level permission
30
- * enforcement, prefer the standalone factories in permission.middleware.ts —
31
- * they don't require a reference to this class instance.
32
- *
33
- * Logging:
34
- * Unexpected errors are logged at "error" level with requestId for correlation.
35
- * Auth failures (expired, invalid token) are intentionally not logged at error
36
- * level — they are client errors, not server faults.
37
- *
38
- * Usage in each service's app.ts:
39
- * import { RequireAuthMiddleware } from "@discover-cloud/shared";
40
- *
41
- * const requireAuth = new RequireAuthMiddleware(jwtVerifier, logger);
42
- * router.use(requireAuth.handle);
12
+ * Middleware handling authentication validation.
13
+ * Extracts the JWT, verifies it via UserJwtVerifier, and attaches the AuthContext.
43
14
  */
44
15
  class RequireAuthMiddleware {
16
+ /**
17
+ * @param {UserJwtVerifier} verifier - The token verification engine.
18
+ * @param {ILogger} [logger] - Optional logger instance.
19
+ */
45
20
  constructor(verifier, logger = utils_1.noopLogger) {
46
21
  this.verifier = verifier;
47
22
  this.logger = logger;
48
23
  /**
49
- * Core authentication middleware.
50
- * Apply via: router.use(requireAuth.handle) or router.get("/", requireAuth.handle, controller.x)
24
+ * Core Express middleware handler for authenticating requests.
25
+ *
26
+ * @param {Request} req - Express request object.
27
+ * @param {Response} res - Express response object.
28
+ * @param {NextFunction} next - Express next function.
29
+ * @returns {Promise<void>}
51
30
  */
52
31
  this.handle = async (req, res, next) => {
53
32
  const token = this.extractBearer(req);
@@ -57,14 +36,12 @@ class RequireAuthMiddleware {
57
36
  }
58
37
  try {
59
38
  const { payload, context } = await this.verifier.buildAccessContext(token);
60
- req.internalAuth = payload;
61
- req.accessContext = context;
39
+ req.authPayload = payload;
40
+ req.authContext = context;
62
41
  this.logger.debug({
63
42
  requestId: req.id,
64
- // log accountId for humans, serviceId for machines — never log both
65
- identity: context.kind === "human" ? context.accountId : context.serviceId,
66
- kind: context.kind,
67
- caller: payload.caller,
43
+ identity: context.accountId,
44
+ type: context.type,
68
45
  }, "Request authenticated");
69
46
  next();
70
47
  }
@@ -72,52 +49,10 @@ class RequireAuthMiddleware {
72
49
  this.handleJwtError(err, req, res);
73
50
  }
74
51
  };
75
- /**
76
- * Inline permission guard — use when this class instance is available at the call site.
77
- * For router-level guards, prefer requireGlobalPermission() from permission.middleware.ts.
78
- *
79
- * Usage: router.get("/", requireAuth.handle, requireAuth.requirePermission(P.READ_ACCOUNTS), controller.list)
80
- */
81
- this.requirePermission = (permission) => (req, res, next) => {
82
- const ctx = req.accessContext;
83
- if (!ctx) {
84
- // Should not happen after handle() — indicates middleware ordering bug
85
- (0, utils_1.failure)(res, req, "No access context — ensure requireAuth runs first", "UNAUTHORIZED", 401);
86
- return;
87
- }
88
- if (!internal_jwt_verifier_1.InternalJwtVerifier.hasPermission(ctx, permission)) {
89
- (0, utils_1.failure)(res, req, `Missing required permission: ${permission}`, "FORBIDDEN", 403);
90
- return;
91
- }
92
- next();
93
- };
94
- /**
95
- * Inline role guard — use when this class instance is available at the call site.
96
- *
97
- * Prefer permission-based guards over role-based guards where possible.
98
- * Role checks are appropriate for coarse access gates (e.g. "only admins enter this router").
99
- */
100
- this.requireRole = (role) => (req, res, next) => {
101
- const ctx = req.accessContext;
102
- if (!ctx) {
103
- (0, utils_1.failure)(res, req, "No access context — ensure requireAuth runs first", "UNAUTHORIZED", 401);
104
- return;
105
- }
106
- if (!internal_jwt_verifier_1.InternalJwtVerifier.hasRole(ctx, role)) {
107
- (0, utils_1.failure)(res, req, `Missing required role: ${role}`, "FORBIDDEN", 403);
108
- return;
109
- }
110
- next();
111
- };
112
52
  }
113
- /* ────────────────────────────────────────────────────────────────────
114
- PRIVATE HELPERS
115
- ──────────────────────────────────────────────────────────────────── */
116
- /**
117
- * Extracts the Bearer token from the Authorization header.
118
- * Returns null (not an error) if the header is absent or malformed —
119
- * callers decide how to handle the missing token.
120
- */
53
+ /* ---------------------------------------------------------------------------
54
+ Private Helpers
55
+ --------------------------------------------------------------------------- */
121
56
  extractBearer(req) {
122
57
  const header = req.headers.authorization;
123
58
  if (!header) {
@@ -129,19 +64,6 @@ class RequireAuthMiddleware {
129
64
  }
130
65
  return token;
131
66
  }
132
- /**
133
- * Maps jose verification errors to appropriate HTTP responses.
134
- *
135
- * Error categories:
136
- * JWTExpired → 401 TOKEN_EXPIRED (client should refresh)
137
- * JWTClaimValidationFailed,
138
- * JWSSignatureVerificationFailed,
139
- * JWSInvalid, JWTInvalid → 401 INVALID_TOKEN (client should re-login)
140
- * Anything else → 503 SERVICE_UNAVAILABLE (unexpected — log at error)
141
- *
142
- * Security note: generic "invalid token" messages are intentional.
143
- * Never expose which specific claim failed — that aids token forgery attempts.
144
- */
145
67
  handleJwtError(err, req, res) {
146
68
  if (err instanceof jose_1.errors.JWTExpired) {
147
69
  (0, utils_1.failure)(res, req, "Your session has expired. Please log in again.", "TOKEN_EXPIRED", 401);
@@ -154,7 +76,6 @@ class RequireAuthMiddleware {
154
76
  (0, utils_1.failure)(res, req, "Token is invalid or has been tampered with.", "INVALID_TOKEN", 401);
155
77
  return;
156
78
  }
157
- // Unexpected error — log for investigation, return a safe 503
158
79
  this.logger.error({ err, requestId: req.id }, "RequireAuthMiddleware: unexpected error during JWT verification");
159
80
  (0, utils_1.failure)(res, req, "Authentication service is temporarily unavailable.", "SERVICE_UNAVAILABLE", 503);
160
81
  }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @file require-machine.middleware.ts
3
+ * @description Express middleware enforcing auth-service issued machine JWT verification
4
+ * for service-to-service communication endpoints.
5
+ */
6
+ import { RequestHandler } from "express";
7
+ import { ILogger } from "../utils/logger.util";
8
+ /**
9
+ * Configuration options for machine authentication middleware.
10
+ */
11
+ export interface RequireMachineOptions {
12
+ /**
13
+ * Auth-service JWKS endpoint used to verify machine JWT signatures.
14
+ */
15
+ authServiceJwksUri?: string;
16
+ /**
17
+ * Service identifiers allowed to access this endpoint.
18
+ */
19
+ allowedServices?: string[];
20
+ /**
21
+ * Optional structured logger.
22
+ */
23
+ logger?: ILogger;
24
+ }
25
+ /**
26
+ * Creates middleware requiring a valid machine JWT.
27
+ *
28
+ * Flow:
29
+ * - Extract Bearer token
30
+ * - Verify RS256 signature using auth-service JWKS
31
+ * - Validate machine token claims
32
+ * - Apply service allowlist
33
+ * - Attach MachineContext
34
+ *
35
+ * @param {RequireMachineOptions} [options] - Middleware configuration options.
36
+ * @returns {RequestHandler} Express middleware handler.
37
+ */
38
+ export declare function requireMachine(options?: RequireMachineOptions): RequestHandler;
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ /**
3
+ * @file require-machine.middleware.ts
4
+ * @description Express middleware enforcing auth-service issued machine JWT verification
5
+ * for service-to-service communication endpoints.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.requireMachine = requireMachine;
42
+ const jose = __importStar(require("jose"));
43
+ const logger_util_1 = require("../utils/logger.util");
44
+ const machine_jwt_verifier_1 = require("../jwt/machine-jwt-verifier");
45
+ /**
46
+ * Creates middleware requiring a valid machine JWT.
47
+ *
48
+ * Flow:
49
+ * - Extract Bearer token
50
+ * - Verify RS256 signature using auth-service JWKS
51
+ * - Validate machine token claims
52
+ * - Apply service allowlist
53
+ * - Attach MachineContext
54
+ *
55
+ * @param {RequireMachineOptions} [options] - Middleware configuration options.
56
+ * @returns {RequestHandler} Express middleware handler.
57
+ */
58
+ function requireMachine(options = {}) {
59
+ const logger = options.logger ?? logger_util_1.noopLogger;
60
+ const verifier = new machine_jwt_verifier_1.MachineJwtVerifier(options.authServiceJwksUri);
61
+ const { allowedServices } = options;
62
+ return async (req, res, next) => {
63
+ const header = req.headers.authorization;
64
+ if (!header?.startsWith("Bearer ")) {
65
+ res.status(401).json({
66
+ success: false,
67
+ error: { code: "UNAUTHORIZED", message: "Missing Authorization header" },
68
+ });
69
+ return;
70
+ }
71
+ const token = header.slice(7);
72
+ try {
73
+ const payload = await verifier.verify(token);
74
+ if (allowedServices && !allowedServices.includes(payload.serviceId)) {
75
+ logger.warn({ requestId: req.id, serviceId: payload.serviceId }, "[requireMachine] Service rejected");
76
+ res.status(403).json({
77
+ success: false,
78
+ error: {
79
+ code: "FORBIDDEN",
80
+ message: "Service is not permitted to access this endpoint",
81
+ },
82
+ });
83
+ return;
84
+ }
85
+ const context = {
86
+ type: "machine",
87
+ serviceId: payload.serviceId,
88
+ scopes: payload.scopes,
89
+ };
90
+ req.authPayload = payload;
91
+ req.authContext = context;
92
+ logger.debug({ requestId: req.id, serviceId: payload.serviceId, jti: payload.jti }, "[requireMachine] Machine authenticated");
93
+ next();
94
+ }
95
+ catch (err) {
96
+ if (err instanceof jose.errors.JWTExpired) {
97
+ res.status(401).json({
98
+ success: false,
99
+ error: { code: "TOKEN_EXPIRED", message: "Machine token expired" },
100
+ });
101
+ return;
102
+ }
103
+ if (err instanceof jose.errors.JWTClaimValidationFailed ||
104
+ err instanceof jose.errors.JWSSignatureVerificationFailed ||
105
+ err instanceof jose.errors.JWSInvalid ||
106
+ err instanceof jose.errors.JWTInvalid) {
107
+ res.status(401).json({
108
+ success: false,
109
+ error: { code: "INVALID_TOKEN", message: "Invalid machine token" },
110
+ });
111
+ return;
112
+ }
113
+ logger.error({ err, requestId: req.id }, "[requireMachine] Machine authentication failure");
114
+ res.status(503).json({
115
+ success: false,
116
+ error: {
117
+ code: "SERVICE_UNAVAILABLE",
118
+ message: "Machine authentication temporarily unavailable",
119
+ },
120
+ });
121
+ }
122
+ };
123
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @file require-org-permission-from-body.middleware.ts
3
+ * @description Checks org permission only when organizationId exists in request body.
4
+ * Used for endpoints that support both personal and organization scopes.
5
+ */
6
+ import { RequestHandler } from 'express';
7
+ import { Permission } from '../enums';
8
+ export declare const createRequireOrgPermissionFromBody: (requireOrgPermission: (permission: Permission) => RequestHandler) => {
9
+ requireOrgPermissionFromBody: (permission: Permission) => RequestHandler;
10
+ };
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * @file require-org-permission-from-body.middleware.ts
4
+ * @description Checks org permission only when organizationId exists in request body.
5
+ * Used for endpoints that support both personal and organization scopes.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.createRequireOrgPermissionFromBody = void 0;
9
+ const createRequireOrgPermissionFromBody = (requireOrgPermission) => {
10
+ const requireOrgPermissionFromBody = (permission) => {
11
+ return async (req, res, next) => {
12
+ const organizationId = req.body?.organizationId ??
13
+ req.validated?.body?.organizationId;
14
+ if (!organizationId) {
15
+ return next();
16
+ }
17
+ return requireOrgPermission(permission)(req, res, next);
18
+ };
19
+ };
20
+ return {
21
+ requireOrgPermissionFromBody,
22
+ };
23
+ };
24
+ exports.createRequireOrgPermissionFromBody = createRequireOrgPermissionFromBody;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @file require-org-permission.middleware.ts
3
+ * @description Express middleware generator to enforce organization-scoped permission checks.
4
+ */
5
+ import { RequestHandler } from "express";
6
+ import { Permission } from "../enums";
7
+ import { PermissionCacheService } from "../authorization/permission-cache.service";
8
+ /**
9
+ * Creates requireOrgPermission middleware factory.
10
+ *
11
+ * @param {PermissionCacheService} permissionCache - Shared Redis cache service.
12
+ * @param {(accountId: string, organizationId: string) => Promise<string[]>} resolveFn - Cache miss database/API lookup function.
13
+ * @returns {object} Organization permission middlewares.
14
+ */
15
+ export declare const createRequireOrgPermission: (permissionCache: PermissionCacheService, resolveFn: (accountId: string, organizationId: string) => Promise<string[]>) => {
16
+ requireOrgPermission: (permission: Permission) => RequestHandler;
17
+ requireAnyOrgPermission: (...permissions: Permission[]) => RequestHandler;
18
+ requireAllOrgPermissions: (...permissions: Permission[]) => RequestHandler;
19
+ };
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ /**
3
+ * @file require-org-permission.middleware.ts
4
+ * @description Express middleware generator to enforce organization-scoped permission checks.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createRequireOrgPermission = void 0;
8
+ const permission_checker_1 = require("../authorization/permission-checker");
9
+ const utils_1 = require("../utils");
10
+ /**
11
+ * Creates requireOrgPermission middleware factory.
12
+ *
13
+ * @param {PermissionCacheService} permissionCache - Shared Redis cache service.
14
+ * @param {(accountId: string, organizationId: string) => Promise<string[]>} resolveFn - Cache miss database/API lookup function.
15
+ * @returns {object} Organization permission middlewares.
16
+ */
17
+ const createRequireOrgPermission = (permissionCache, resolveFn) => {
18
+ const requireOrgPermission = (permission) => {
19
+ return async (req, res, next) => {
20
+ const ctx = req.authContext;
21
+ if (!ctx || ctx.type !== "user") {
22
+ (0, utils_1.failure)(res, req, "Unauthorized: No auth context", "UNAUTHORIZED", 401);
23
+ return;
24
+ }
25
+ const organizationId = req.params["organizationId"] ??
26
+ req.params["orgId"] ??
27
+ req.validated?.params?.["organizationId"] ??
28
+ req.validated?.body?.["organizationId"];
29
+ if (!organizationId || typeof organizationId !== "string") {
30
+ (0, utils_1.failure)(res, req, "Bad Request: Missing organization context", "BAD_REQUEST", 400);
31
+ return;
32
+ }
33
+ try {
34
+ const perms = await permissionCache.resolveOrganizationPermissions(ctx.accountId, organizationId, async () => {
35
+ return resolveFn(ctx.accountId, organizationId);
36
+ });
37
+ if (!permission_checker_1.PermissionChecker.has(perms, permission)) {
38
+ (0, utils_1.failure)(res, req, `Forbidden: Missing required organization permission: ${permission}`, "FORBIDDEN", 403);
39
+ return;
40
+ }
41
+ next();
42
+ }
43
+ catch (err) {
44
+ next(err);
45
+ }
46
+ };
47
+ };
48
+ const requireAnyOrgPermission = (...permissions) => {
49
+ return async (req, res, next) => {
50
+ const ctx = req.authContext;
51
+ if (!ctx || ctx.type !== "user") {
52
+ (0, utils_1.failure)(res, req, "Unauthorized: No auth context", "UNAUTHORIZED", 401);
53
+ return;
54
+ }
55
+ const organizationId = req.params["organizationId"] ??
56
+ req.params["orgId"] ??
57
+ req.validated?.params?.["organizationId"] ??
58
+ req.validated?.body?.["organizationId"];
59
+ if (!organizationId || typeof organizationId !== "string") {
60
+ (0, utils_1.failure)(res, req, "Bad Request: Missing organization context", "BAD_REQUEST", 400);
61
+ return;
62
+ }
63
+ try {
64
+ const perms = await permissionCache.resolveOrganizationPermissions(ctx.accountId, organizationId, async () => {
65
+ return resolveFn(ctx.accountId, organizationId);
66
+ });
67
+ if (!permission_checker_1.PermissionChecker.hasAny(perms, permissions)) {
68
+ (0, utils_1.failure)(res, req, `Forbidden: Missing one of required organization permissions: [${permissions.join(", ")}]`, "FORBIDDEN", 403);
69
+ return;
70
+ }
71
+ next();
72
+ }
73
+ catch (err) {
74
+ next(err);
75
+ }
76
+ };
77
+ };
78
+ const requireAllOrgPermissions = (...permissions) => {
79
+ return async (req, res, next) => {
80
+ const ctx = req.authContext;
81
+ if (!ctx || ctx.type !== "user") {
82
+ (0, utils_1.failure)(res, req, "Unauthorized: No auth context", "UNAUTHORIZED", 401);
83
+ return;
84
+ }
85
+ const organizationId = req.params["organizationId"] ??
86
+ req.params["orgId"] ??
87
+ req.validated?.params?.["organizationId"] ??
88
+ req.validated?.body?.["organizationId"];
89
+ if (!organizationId || typeof organizationId !== "string") {
90
+ (0, utils_1.failure)(res, req, "Bad Request: Missing organization context", "BAD_REQUEST", 400);
91
+ return;
92
+ }
93
+ try {
94
+ const perms = await permissionCache.resolveOrganizationPermissions(ctx.accountId, organizationId, async () => {
95
+ return resolveFn(ctx.accountId, organizationId);
96
+ });
97
+ if (!permission_checker_1.PermissionChecker.hasAll(perms, permissions)) {
98
+ const missing = permissions.filter(p => !permission_checker_1.PermissionChecker.has(perms, p));
99
+ (0, utils_1.failure)(res, req, `Forbidden: Missing required organization permissions: [${missing.join(", ")}]`, "FORBIDDEN", 403);
100
+ return;
101
+ }
102
+ next();
103
+ }
104
+ catch (err) {
105
+ next(err);
106
+ }
107
+ };
108
+ };
109
+ return {
110
+ requireOrgPermission,
111
+ requireAnyOrgPermission,
112
+ requireAllOrgPermissions,
113
+ };
114
+ };
115
+ exports.createRequireOrgPermission = createRequireOrgPermission;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @file require-platform-permission.middleware.ts
3
+ * @description Express middleware generator to enforce platform-scoped permission checks.
4
+ */
5
+ import { RequestHandler } from "express";
6
+ import { PlatformPermission } from "../enums";
7
+ import { PermissionCacheService } from "../authorization/permission-cache.service";
8
+ /**
9
+ * Creates requirePlatformPermission middleware.
10
+ *
11
+ * @param {PermissionCacheService} permissionCache - Shared Redis cache service.
12
+ * @param {(accountId: string) => Promise<string[]>} resolveFn - Cache miss database/API lookup function.
13
+ * @returns {object} Platform permission middlewares.
14
+ */
15
+ export declare const createRequirePlatformPermission: (permissionCache: PermissionCacheService, resolveFn: (accountId: string) => Promise<string[]>) => {
16
+ requirePlatformPermission: (permission: PlatformPermission) => RequestHandler;
17
+ requireAnyPlatformPermission: (...permissions: PlatformPermission[]) => RequestHandler;
18
+ requireAllPlatformPermissions: (...permissions: PlatformPermission[]) => RequestHandler;
19
+ };
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ /**
3
+ * @file require-platform-permission.middleware.ts
4
+ * @description Express middleware generator to enforce platform-scoped permission checks.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createRequirePlatformPermission = void 0;
8
+ const permission_checker_1 = require("../authorization/permission-checker");
9
+ const utils_1 = require("../utils");
10
+ /**
11
+ * Creates requirePlatformPermission middleware.
12
+ *
13
+ * @param {PermissionCacheService} permissionCache - Shared Redis cache service.
14
+ * @param {(accountId: string) => Promise<string[]>} resolveFn - Cache miss database/API lookup function.
15
+ * @returns {object} Platform permission middlewares.
16
+ */
17
+ const createRequirePlatformPermission = (permissionCache, resolveFn) => {
18
+ const requirePlatformPermission = (permission) => {
19
+ return async (req, res, next) => {
20
+ const ctx = req.authContext;
21
+ if (!ctx || ctx.type !== "user") {
22
+ (0, utils_1.failure)(res, req, "Unauthorized: No access context", "UNAUTHORIZED", 401);
23
+ return;
24
+ }
25
+ try {
26
+ const perms = await permissionCache.resolvePlatformPermissions(ctx.accountId, async () => {
27
+ return resolveFn(ctx.accountId);
28
+ });
29
+ if (!permission_checker_1.PermissionChecker.has(perms, permission)) {
30
+ (0, utils_1.failure)(res, req, `Forbidden: Missing required platform permission: ${permission}`, "FORBIDDEN", 403);
31
+ return;
32
+ }
33
+ next();
34
+ }
35
+ catch (err) {
36
+ next(err);
37
+ }
38
+ };
39
+ };
40
+ const requireAnyPlatformPermission = (...permissions) => {
41
+ return async (req, res, next) => {
42
+ const ctx = req.authContext;
43
+ if (!ctx || ctx.type !== "user") {
44
+ (0, utils_1.failure)(res, req, "Unauthorized: No access context", "UNAUTHORIZED", 401);
45
+ return;
46
+ }
47
+ try {
48
+ const perms = await permissionCache.resolvePlatformPermissions(ctx.accountId, async () => {
49
+ return resolveFn(ctx.accountId);
50
+ });
51
+ if (!permission_checker_1.PermissionChecker.hasAny(perms, permissions)) {
52
+ (0, utils_1.failure)(res, req, `Forbidden: Missing one of required platform permissions: [${permissions.join(", ")}]`, "FORBIDDEN", 403);
53
+ return;
54
+ }
55
+ next();
56
+ }
57
+ catch (err) {
58
+ next(err);
59
+ }
60
+ };
61
+ };
62
+ const requireAllPlatformPermissions = (...permissions) => {
63
+ return async (req, res, next) => {
64
+ const ctx = req.authContext;
65
+ if (!ctx || ctx.type !== "user") {
66
+ (0, utils_1.failure)(res, req, "Unauthorized: No access context", "UNAUTHORIZED", 401);
67
+ return;
68
+ }
69
+ try {
70
+ const perms = await permissionCache.resolvePlatformPermissions(ctx.accountId, async () => {
71
+ return resolveFn(ctx.accountId);
72
+ });
73
+ if (!permission_checker_1.PermissionChecker.hasAll(perms, permissions)) {
74
+ const missing = permissions.filter(p => !permission_checker_1.PermissionChecker.has(perms, p));
75
+ (0, utils_1.failure)(res, req, `Forbidden: Missing required platform permissions: [${missing.join(", ")}]`, "FORBIDDEN", 403);
76
+ return;
77
+ }
78
+ next();
79
+ }
80
+ catch (err) {
81
+ next(err);
82
+ }
83
+ };
84
+ };
85
+ return {
86
+ requirePlatformPermission,
87
+ requireAnyPlatformPermission,
88
+ requireAllPlatformPermissions,
89
+ };
90
+ };
91
+ exports.createRequirePlatformPermission = createRequirePlatformPermission;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @file require-user.middleware.ts
3
+ * @description Express middleware to assert that the request auth context belongs to a user (not a machine).
4
+ */
5
+ import { Request, Response, NextFunction } from "express";
6
+ /**
7
+ * Asserts that the current request has a valid user context, returning 401/403 otherwise.
8
+ *
9
+ * @param {Request} req - Express request object.
10
+ * @param {Response} res - Express response object.
11
+ * @param {NextFunction} next - Express next middleware function.
12
+ * @returns {void}
13
+ */
14
+ export declare const requireUser: (req: Request, res: Response, next: NextFunction) => void;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * @file require-user.middleware.ts
4
+ * @description Express middleware to assert that the request auth context belongs to a user (not a machine).
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.requireUser = void 0;
8
+ const utils_1 = require("../utils");
9
+ const types_1 = require("../types");
10
+ /**
11
+ * Asserts that the current request has a valid user context, returning 401/403 otherwise.
12
+ *
13
+ * @param {Request} req - Express request object.
14
+ * @param {Response} res - Express response object.
15
+ * @param {NextFunction} next - Express next middleware function.
16
+ * @returns {void}
17
+ */
18
+ const requireUser = (req, res, next) => {
19
+ const ctx = req.authContext;
20
+ if (!ctx) {
21
+ (0, utils_1.failure)(res, req, "Unauthorized: No auth context", "UNAUTHORIZED", 401);
22
+ return;
23
+ }
24
+ if (!(0, types_1.isUserContext)(ctx)) {
25
+ (0, utils_1.failure)(res, req, "User token required", "FORBIDDEN", 401);
26
+ return;
27
+ }
28
+ next();
29
+ };
30
+ exports.requireUser = requireUser;