@digilogiclabs/platform-core 1.9.0 → 1.10.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.
package/dist/auth.mjs CHANGED
@@ -562,6 +562,12 @@ var CommonRateLimits = {
562
562
  limit: 10,
563
563
  windowSeconds: 3600,
564
564
  blockDurationSeconds: 3600
565
+ },
566
+ /** Beta code validation: 5/min with 5min block (prevents brute force guessing) */
567
+ betaValidation: {
568
+ limit: 5,
569
+ windowSeconds: 60,
570
+ blockDurationSeconds: 300
565
571
  }
566
572
  };
567
573
  function createMemoryRateLimitStore() {
@@ -1105,6 +1111,71 @@ function isValidBearerToken(request, secret) {
1105
1111
  if (!token) return false;
1106
1112
  return constantTimeEqual(token, secret);
1107
1113
  }
1114
+ function verifyCronAuth(request, secret) {
1115
+ const authHeader = request.headers.get("authorization");
1116
+ if (!authHeader?.startsWith("Bearer ")) {
1117
+ return new Response(
1118
+ JSON.stringify({ error: "Missing authorization" }),
1119
+ { status: 401, headers: { "Content-Type": "application/json" } }
1120
+ );
1121
+ }
1122
+ const token = authHeader.slice(7);
1123
+ const expectedSecret = secret ?? process.env.CRON_SECRET;
1124
+ if (!expectedSecret) {
1125
+ console.error("[verifyCronAuth] CRON_SECRET not configured");
1126
+ return new Response(
1127
+ JSON.stringify({ error: "Server configuration error" }),
1128
+ { status: 500, headers: { "Content-Type": "application/json" } }
1129
+ );
1130
+ }
1131
+ if (!constantTimeEqual(token, expectedSecret)) {
1132
+ return new Response(
1133
+ JSON.stringify({ error: "Invalid authorization" }),
1134
+ { status: 401, headers: { "Content-Type": "application/json" } }
1135
+ );
1136
+ }
1137
+ return null;
1138
+ }
1139
+ function getClientIp(request) {
1140
+ return request.headers.get("cf-connecting-ip") || request.headers.get("x-real-ip") || request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || "unknown";
1141
+ }
1142
+ function rateLimitResponse(result) {
1143
+ const retryAfter = Math.ceil(result.resetMs / 1e3);
1144
+ const resetTimestamp = Math.ceil(Date.now() / 1e3 + result.resetMs / 1e3);
1145
+ return new Response(
1146
+ JSON.stringify({ error: "Too many requests", retryAfter }),
1147
+ {
1148
+ status: 429,
1149
+ headers: {
1150
+ "Content-Type": "application/json",
1151
+ "X-RateLimit-Limit": String(result.limit),
1152
+ "X-RateLimit-Remaining": "0",
1153
+ "X-RateLimit-Reset": String(resetTimestamp),
1154
+ "Retry-After": String(retryAfter)
1155
+ }
1156
+ }
1157
+ );
1158
+ }
1159
+ function addRateLimitHeaders(response, result) {
1160
+ const resetTimestamp = Math.ceil(Date.now() / 1e3 + result.resetMs / 1e3);
1161
+ response.headers.set("X-RateLimit-Limit", String(result.limit));
1162
+ response.headers.set("X-RateLimit-Remaining", String(result.remaining));
1163
+ response.headers.set("X-RateLimit-Reset", String(resetTimestamp));
1164
+ return response;
1165
+ }
1166
+ function safeValidate(schema, data) {
1167
+ const result = schema.safeParse(data);
1168
+ if (result.success) {
1169
+ return { success: true, data: result.data };
1170
+ }
1171
+ return {
1172
+ success: false,
1173
+ errors: (result.error?.issues || []).map((issue) => ({
1174
+ field: issue.path.join("."),
1175
+ message: issue.message
1176
+ }))
1177
+ };
1178
+ }
1108
1179
 
1109
1180
  // src/auth/beta-client.ts
1110
1181
  var DEFAULT_CONFIG = {
@@ -1322,6 +1393,7 @@ export {
1322
1393
  StandardAuditActions,
1323
1394
  StandardRateLimitPresets,
1324
1395
  WrapperPresets,
1396
+ addRateLimitHeaders,
1325
1397
  buildAllowlist,
1326
1398
  buildAuthCookies,
1327
1399
  buildErrorBody,
@@ -1356,6 +1428,7 @@ export {
1356
1428
  extractClientIp,
1357
1429
  fetchBetaSettings,
1358
1430
  getBoolEnv,
1431
+ getClientIp,
1359
1432
  getCorrelationId,
1360
1433
  getEndSessionEndpoint,
1361
1434
  getEnvSummary,
@@ -1373,15 +1446,18 @@ export {
1373
1446
  isTokenExpired,
1374
1447
  isValidBearerToken,
1375
1448
  parseKeycloakRoles,
1449
+ rateLimitResponse,
1376
1450
  refreshKeycloakToken,
1377
1451
  resetRateLimitForKey,
1378
1452
  resolveIdentifier,
1379
1453
  resolveRateLimitIdentifier,
1454
+ safeValidate,
1380
1455
  sanitizeApiError,
1381
1456
  storeBetaCode,
1382
1457
  stripHtml,
1383
1458
  validateBetaCode,
1384
1459
  validateEnvVars,
1460
+ verifyCronAuth,
1385
1461
  zodErrorResponse
1386
1462
  };
1387
1463
  //# sourceMappingURL=auth.mjs.map