@fonderie/auth 7.17.0 → 7.18.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/brain/outcomes.md +1 -0
- package/brain/signatures.md +23 -1
- package/dist/index.cjs +120 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +114 -19
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.cjs +12 -7
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +1 -1
- package/dist/middlewares/index.d.ts +1 -1
- package/dist/middlewares/index.js +12 -7
- package/dist/middlewares/index.js.map +1 -1
- package/dist/migrations/sql/021_session_client_kind.sql +6 -0
- package/dist/{session-C-ptRylj.d.cts → session-B-IgXFu8.d.cts} +32 -2
- package/dist/{session-C-ptRylj.d.ts → session-B-IgXFu8.d.ts} +32 -2
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -3,8 +3,8 @@ export { IMfaChallenge, ISession } from './types.cjs';
|
|
|
3
3
|
import { IFonderieModule, IAdminDescription, IReadinessProblem, IFonderieApp, IDefaultTemplate, IAdminRoute } from '@fonderie/core';
|
|
4
4
|
import { IStoreAdapter } from '@fonderie/store';
|
|
5
5
|
import { EventBus } from '@fonderie/events';
|
|
6
|
-
import { I as IAuthConfig, a as IRequestLocation } from './session-
|
|
7
|
-
export { A as AUTH_CONFIG_KEYS, b as AuthLimitedRoute, c as AuthMessageKey, d as
|
|
6
|
+
import { I as IAuthConfig, a as IRequestLocation } from './session-B-IgXFu8.cjs';
|
|
7
|
+
export { A as AUTH_CONFIG_KEYS, b as AuthLimitedRoute, c as AuthMessageKey, C as CLIENT_KINDS, d as ClientKind, e as IAuthRateLimitConfig, f as IAuthRuntimeConfig, g as IAuthSecrets, h as IDataExportContributor, i as ILocationRequest, j as ISessionPolicy, L as LocationResolver, M as MESSAGE_KEYS, S as SESSION_POLICY_PRESETS, k as buildAuthAccountLimiter, l as buildAuthIpLimiter, m as clientKindOf, n as configForClient, r as readAuthRuntimeConfig, o as resolveLocation, s as sanitizeLocation, p as sessionPolicyConfigKeys, w as withSession } from './session-B-IgXFu8.cjs';
|
|
8
8
|
import { IUserDTO } from './dtos/user.cjs';
|
|
9
9
|
export { toUserDTO } from './dtos/user.cjs';
|
|
10
10
|
export { requireAuth, validate } from '@fonderie/core/middlewares';
|
|
@@ -50,6 +50,8 @@ interface ISessionDTO {
|
|
|
50
50
|
location: IRequestLocation | null;
|
|
51
51
|
createdAt: string;
|
|
52
52
|
expiresAt: string;
|
|
53
|
+
/** The platform declared at sign-in (mobile | desktop | web), or null. */
|
|
54
|
+
clientKind: string | null;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
declare const registerSchema: z.ZodUnion<readonly [z.ZodObject<{
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export { IMfaChallenge, ISession } from './types.js';
|
|
|
3
3
|
import { IFonderieModule, IAdminDescription, IReadinessProblem, IFonderieApp, IDefaultTemplate, IAdminRoute } from '@fonderie/core';
|
|
4
4
|
import { IStoreAdapter } from '@fonderie/store';
|
|
5
5
|
import { EventBus } from '@fonderie/events';
|
|
6
|
-
import { I as IAuthConfig, a as IRequestLocation } from './session-
|
|
7
|
-
export { A as AUTH_CONFIG_KEYS, b as AuthLimitedRoute, c as AuthMessageKey, d as
|
|
6
|
+
import { I as IAuthConfig, a as IRequestLocation } from './session-B-IgXFu8.js';
|
|
7
|
+
export { A as AUTH_CONFIG_KEYS, b as AuthLimitedRoute, c as AuthMessageKey, C as CLIENT_KINDS, d as ClientKind, e as IAuthRateLimitConfig, f as IAuthRuntimeConfig, g as IAuthSecrets, h as IDataExportContributor, i as ILocationRequest, j as ISessionPolicy, L as LocationResolver, M as MESSAGE_KEYS, S as SESSION_POLICY_PRESETS, k as buildAuthAccountLimiter, l as buildAuthIpLimiter, m as clientKindOf, n as configForClient, r as readAuthRuntimeConfig, o as resolveLocation, s as sanitizeLocation, p as sessionPolicyConfigKeys, w as withSession } from './session-B-IgXFu8.js';
|
|
8
8
|
import { IUserDTO } from './dtos/user.js';
|
|
9
9
|
export { toUserDTO } from './dtos/user.js';
|
|
10
10
|
export { requireAuth, validate } from '@fonderie/core/middlewares';
|
|
@@ -50,6 +50,8 @@ interface ISessionDTO {
|
|
|
50
50
|
location: IRequestLocation | null;
|
|
51
51
|
createdAt: string;
|
|
52
52
|
expiresAt: string;
|
|
53
|
+
/** The platform declared at sign-in (mobile | desktop | web), or null. */
|
|
54
|
+
clientKind: string | null;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
declare const registerSchema: z.ZodUnion<readonly [z.ZodObject<{
|
package/dist/index.js
CHANGED
|
@@ -312,8 +312,8 @@ function issueMfaPendingToken(userId, config, loginMethod) {
|
|
|
312
312
|
);
|
|
313
313
|
}
|
|
314
314
|
function issueTokenPair(userId, config, options) {
|
|
315
|
-
const duration = config.sessionDuration
|
|
316
|
-
const accessDuration = config.accessTokenDuration
|
|
315
|
+
const duration = validDuration(config.sessionDuration, DEFAULT_SESSION_DURATION, "sessionDuration");
|
|
316
|
+
const accessDuration = validDuration(config.accessTokenDuration, DEFAULT_ACCESS_TOKEN_DURATION, "accessTokenDuration");
|
|
317
317
|
const authTime = options.authTime ?? Math.floor(Date.now() / 1e3);
|
|
318
318
|
const loginMethod = options.loginMethod;
|
|
319
319
|
const phoneVerified = options.phoneVerified ?? false;
|
|
@@ -356,6 +356,90 @@ function durationMs(value) {
|
|
|
356
356
|
const scale = { ms: 1, s: 1e3, m: 6e4, h: 36e5, d: 864e5, w: 6048e5, y: 315576e5 };
|
|
357
357
|
return Number(m[1]) * (scale[unit] ?? 1e3);
|
|
358
358
|
}
|
|
359
|
+
var warnedDurations = /* @__PURE__ */ new Set();
|
|
360
|
+
function validDuration(value, fallback, name) {
|
|
361
|
+
if (value === void 0 || value === null || value === "") return fallback;
|
|
362
|
+
if (durationMs(String(value)) !== null) return String(value);
|
|
363
|
+
const key = `${name}=${String(value)}`;
|
|
364
|
+
if (!warnedDurations.has(key)) {
|
|
365
|
+
warnedDurations.add(key);
|
|
366
|
+
console.warn(`[auth] ${name} ${JSON.stringify(value)} is not a duration (e.g. '90d', '1h') \u2014 using ${fallback}`);
|
|
367
|
+
}
|
|
368
|
+
return fallback;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/services/session-policy.ts
|
|
372
|
+
var CLIENT_KINDS = ["mobile", "desktop", "web"];
|
|
373
|
+
var SESSION_POLICY_PRESETS = {
|
|
374
|
+
// Personal device; the token lives in the Keychain / Keystore.
|
|
375
|
+
mobile: { sessionDuration: "90d", sessionMaxAge: "365d" },
|
|
376
|
+
// Personal, but often a shared workstation.
|
|
377
|
+
desktop: { sessionDuration: "30d", sessionMaxAge: "180d" },
|
|
378
|
+
// Shared and public computers; cookies.
|
|
379
|
+
web: { sessionDuration: "14d", sessionMaxAge: "90d" }
|
|
380
|
+
};
|
|
381
|
+
function clientKindOf(headers) {
|
|
382
|
+
const v = headers.get("x-client-kind")?.trim().toLowerCase();
|
|
383
|
+
return CLIENT_KINDS.includes(v ?? "") ? v : null;
|
|
384
|
+
}
|
|
385
|
+
var FIELDS = ["sessionDuration", "sessionMaxAge", "accessTokenDuration"];
|
|
386
|
+
function configForClient(config, runtime, kind) {
|
|
387
|
+
const rt = runtime ?? {};
|
|
388
|
+
const code = config;
|
|
389
|
+
const out = { ...config, ...rt };
|
|
390
|
+
for (const field of FIELDS) {
|
|
391
|
+
const value = (kind ? rt.sessionPolicies?.[kind]?.[field] : void 0) ?? rt[field] ?? (kind ? code.sessionPolicies?.[kind]?.[field] : void 0) ?? code[field] ?? (kind ? SESSION_POLICY_PRESETS[kind][field] : void 0);
|
|
392
|
+
if (value === void 0) delete out[field];
|
|
393
|
+
else out[field] = value;
|
|
394
|
+
}
|
|
395
|
+
return out;
|
|
396
|
+
}
|
|
397
|
+
function sessionPolicyConfigKeys(kind) {
|
|
398
|
+
return {
|
|
399
|
+
sessionDuration: `auth.session.duration.${kind}`,
|
|
400
|
+
sessionMaxAge: `auth.session.max_age.${kind}`,
|
|
401
|
+
accessTokenDuration: `auth.access.duration.${kind}`
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function readAuthRuntimeConfig(read) {
|
|
405
|
+
const text = (key) => {
|
|
406
|
+
const v = read(key);
|
|
407
|
+
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
408
|
+
};
|
|
409
|
+
const bool2 = (key) => {
|
|
410
|
+
const v = read(key);
|
|
411
|
+
if (typeof v === "boolean") return v;
|
|
412
|
+
if (typeof v === "string" && ["true", "false"].includes(v.trim().toLowerCase())) return v.trim().toLowerCase() === "true";
|
|
413
|
+
return void 0;
|
|
414
|
+
};
|
|
415
|
+
const num = (key) => {
|
|
416
|
+
const v = read(key);
|
|
417
|
+
const n = typeof v === "number" ? v : typeof v === "string" && v.trim() ? Number(v) : NaN;
|
|
418
|
+
return Number.isFinite(n) ? n : void 0;
|
|
419
|
+
};
|
|
420
|
+
const out = {};
|
|
421
|
+
const set = (k, v) => {
|
|
422
|
+
if (v !== void 0) out[k] = v;
|
|
423
|
+
};
|
|
424
|
+
set("sessionDuration", text("auth.session.duration"));
|
|
425
|
+
set("sessionMaxAge", text("auth.session.max_age"));
|
|
426
|
+
set("accessTokenDuration", text("auth.access.duration"));
|
|
427
|
+
set("verificationCooldown", num("auth.verification.cooldown"));
|
|
428
|
+
set("mfa", bool2("auth.mfa.enabled"));
|
|
429
|
+
set("requireVerification", bool2("auth.verification.required"));
|
|
430
|
+
const policies = {};
|
|
431
|
+
for (const kind of CLIENT_KINDS) {
|
|
432
|
+
const keys = sessionPolicyConfigKeys(kind);
|
|
433
|
+
const policy = {};
|
|
434
|
+
for (const field of FIELDS) {
|
|
435
|
+
const v = text(keys[field]);
|
|
436
|
+
if (v !== void 0) policy[field] = v;
|
|
437
|
+
}
|
|
438
|
+
if (Object.keys(policy).length) policies[kind] = policy;
|
|
439
|
+
}
|
|
440
|
+
if (Object.keys(policies).length) out.sessionPolicies = policies;
|
|
441
|
+
return out;
|
|
442
|
+
}
|
|
359
443
|
|
|
360
444
|
// src/services/mfa.ts
|
|
361
445
|
import { createHmac, randomBytes } from "crypto";
|
|
@@ -980,8 +1064,8 @@ var SessionModel = class {
|
|
|
980
1064
|
async create(userId, token, expiresAt, sid, meta) {
|
|
981
1065
|
const location = this.locate && meta?.headers ? await resolveLocation(this.locate, { ip: meta.ipAddress, headers: meta.headers }) : null;
|
|
982
1066
|
await this.store.query(
|
|
983
|
-
`INSERT INTO fonderie_sessions (user_id, token, expires_at, sid, user_agent, ip_address, location, last_used_at)
|
|
984
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, now())
|
|
1067
|
+
`INSERT INTO fonderie_sessions (user_id, token, expires_at, sid, user_agent, ip_address, location, last_used_at, client_kind)
|
|
1068
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, now(), $8)
|
|
985
1069
|
ON CONFLICT (token) DO NOTHING`,
|
|
986
1070
|
[
|
|
987
1071
|
userId,
|
|
@@ -990,7 +1074,8 @@ var SessionModel = class {
|
|
|
990
1074
|
sid ?? null,
|
|
991
1075
|
meta?.userAgent ?? null,
|
|
992
1076
|
meta?.ipAddress ?? null,
|
|
993
|
-
location ? JSON.stringify(location) : null
|
|
1077
|
+
location ? JSON.stringify(location) : null,
|
|
1078
|
+
meta?.clientKind ?? null
|
|
994
1079
|
]
|
|
995
1080
|
);
|
|
996
1081
|
}
|
|
@@ -1005,12 +1090,12 @@ var SessionModel = class {
|
|
|
1005
1090
|
async match(token) {
|
|
1006
1091
|
const hash = hashRefreshToken(token);
|
|
1007
1092
|
const [current] = await this.store.query(
|
|
1008
|
-
`SELECT id, user_id, sid, token, created_at FROM fonderie_sessions WHERE token IN ($1, $2) AND expires_at > now() LIMIT 1`,
|
|
1093
|
+
`SELECT id, user_id, sid, token, created_at, client_kind FROM fonderie_sessions WHERE token IN ($1, $2) AND expires_at > now() LIMIT 1`,
|
|
1009
1094
|
[hash, token]
|
|
1010
1095
|
);
|
|
1011
1096
|
if (current) return { kind: "current", row: toRow(current) };
|
|
1012
1097
|
const [previous] = await this.store.query(
|
|
1013
|
-
`SELECT id, user_id, sid, token, created_at, (previous_valid_until > now()) AS in_grace
|
|
1098
|
+
`SELECT id, user_id, sid, token, created_at, client_kind, (previous_valid_until > now()) AS in_grace
|
|
1014
1099
|
FROM fonderie_sessions WHERE previous_token_hash = $1 AND expires_at > now() LIMIT 1`,
|
|
1015
1100
|
[hash]
|
|
1016
1101
|
);
|
|
@@ -1076,7 +1161,7 @@ var SessionModel = class {
|
|
|
1076
1161
|
// No token — that never leaves the server.
|
|
1077
1162
|
async listLiveByUser(userId) {
|
|
1078
1163
|
return this.store.query(
|
|
1079
|
-
`SELECT id, sid,
|
|
1164
|
+
`SELECT id, sid, client_kind AS "clientKind",
|
|
1080
1165
|
user_agent AS "userAgent",
|
|
1081
1166
|
ip_address AS "ipAddress",
|
|
1082
1167
|
location,
|
|
@@ -1125,7 +1210,8 @@ var SessionModel = class {
|
|
|
1125
1210
|
}
|
|
1126
1211
|
};
|
|
1127
1212
|
function toRow(r) {
|
|
1128
|
-
|
|
1213
|
+
const kind = CLIENT_KINDS.includes(r.client_kind ?? "") ? r.client_kind : null;
|
|
1214
|
+
return { id: r.id, userId: r.user_id, sid: r.sid, stored: r.token, createdAt: r.created_at ? new Date(r.created_at) : /* @__PURE__ */ new Date(), clientKind: kind };
|
|
1129
1215
|
}
|
|
1130
1216
|
|
|
1131
1217
|
// src/models/backup-code.model.ts
|
|
@@ -1256,7 +1342,8 @@ function requestMeta(ctx) {
|
|
|
1256
1342
|
const meta = {
|
|
1257
1343
|
ipAddress: typeof ip === "string" && ip.length > 0 ? ip : null,
|
|
1258
1344
|
userAgent: ua && ua.length > 0 ? ua.slice(0, UA_MAX) : null,
|
|
1259
|
-
headers: ctx.request.headers
|
|
1345
|
+
headers: ctx.request.headers,
|
|
1346
|
+
clientKind: clientKindOf(ctx.request.headers)
|
|
1260
1347
|
};
|
|
1261
1348
|
if (meta.ipAddress === null && meta.userAgent === null) warnIfIdentityless(ctx);
|
|
1262
1349
|
return meta;
|
|
@@ -1371,7 +1458,7 @@ function mfaController(store, config, issuer, bus) {
|
|
|
1371
1458
|
await users.enableMfa(ctx.user.id);
|
|
1372
1459
|
}
|
|
1373
1460
|
}
|
|
1374
|
-
const { accessToken, refreshToken, sid } = issueTokenPair(ctx.user.id, config, {
|
|
1461
|
+
const { accessToken, refreshToken, sid } = issueTokenPair(ctx.user.id, configForClient(config, config.resolve?.(ctx), clientKindOf(ctx.request.headers)), {
|
|
1375
1462
|
loginMethod: ctx.user.loginMethod,
|
|
1376
1463
|
phoneVerified: ctx.user.phoneVerified
|
|
1377
1464
|
});
|
|
@@ -1733,7 +1820,7 @@ function authController(store, config, bus, locales = defineLocales()) {
|
|
|
1733
1820
|
},
|
|
1734
1821
|
reqOpts
|
|
1735
1822
|
));
|
|
1736
|
-
const { accessToken, refreshToken, sid } = issueTokenPair(user.id, config, {
|
|
1823
|
+
const { accessToken, refreshToken, sid } = issueTokenPair(user.id, configForClient(config, config.resolve?.(ctx), clientKindOf(ctx.request.headers)), {
|
|
1737
1824
|
loginMethod: "email"
|
|
1738
1825
|
});
|
|
1739
1826
|
const registerMeta = requestMeta(ctx);
|
|
@@ -1876,7 +1963,7 @@ function authController(store, config, bus, locales = defineLocales()) {
|
|
|
1876
1963
|
mfaToken
|
|
1877
1964
|
});
|
|
1878
1965
|
}
|
|
1879
|
-
const { accessToken, refreshToken, sid } = issueTokenPair(user.id, config, {
|
|
1966
|
+
const { accessToken, refreshToken, sid } = issueTokenPair(user.id, configForClient(config, config.resolve?.(ctx), clientKindOf(ctx.request.headers)), {
|
|
1880
1967
|
loginMethod: "email"
|
|
1881
1968
|
});
|
|
1882
1969
|
await sessions.create(user.id, refreshToken, refreshTokenExpiry(refreshToken), sid, meta);
|
|
@@ -1969,8 +2056,7 @@ function authController(store, config, bus, locales = defineLocales()) {
|
|
|
1969
2056
|
if (!payload || payload.type !== "refresh") {
|
|
1970
2057
|
return setApiResponse3(HTTP3.UNAUTHORIZED, "TOKEN_REFRESH_FAILED", "Invalid refresh token");
|
|
1971
2058
|
}
|
|
1972
|
-
const
|
|
1973
|
-
const maxAgeMs = durationMs(resolvedRefresh.sessionMaxAge);
|
|
2059
|
+
const runtime = config.resolve?.(ctx);
|
|
1974
2060
|
let issued = null;
|
|
1975
2061
|
for (let attempt = 0; attempt < 3 && !issued; attempt++) {
|
|
1976
2062
|
const found = await sessions.match(token);
|
|
@@ -1984,6 +2070,8 @@ function authController(store, config, bus, locales = defineLocales()) {
|
|
|
1984
2070
|
);
|
|
1985
2071
|
return setApiResponse3(HTTP3.UNAUTHORIZED, "TOKEN_REFRESH_FAILED", "Session expired or already revoked");
|
|
1986
2072
|
}
|
|
2073
|
+
const resolvedRefresh = configForClient(config, runtime, found.row.clientKind);
|
|
2074
|
+
const maxAgeMs = resolvedRefresh.sessionMaxAge ? durationMs(String(resolvedRefresh.sessionMaxAge)) : null;
|
|
1987
2075
|
if (maxAgeMs !== null && Date.now() - found.row.createdAt.getTime() > maxAgeMs) {
|
|
1988
2076
|
await sessions.revokeById(found.row.id);
|
|
1989
2077
|
return setApiResponse3(HTTP3.UNAUTHORIZED, "TOKEN_REFRESH_FAILED", "Session reached its maximum age \u2014 sign in again");
|
|
@@ -2165,7 +2253,7 @@ function authController(store, config, bus, locales = defineLocales()) {
|
|
|
2165
2253
|
);
|
|
2166
2254
|
}
|
|
2167
2255
|
await phoneVerif.deleteByUser(ctx.user.id);
|
|
2168
|
-
const { accessToken, refreshToken, sid } = issueTokenPair(ctx.user.id, config, {
|
|
2256
|
+
const { accessToken, refreshToken, sid } = issueTokenPair(ctx.user.id, configForClient(config, config.resolve?.(ctx), clientKindOf(ctx.request.headers)), {
|
|
2169
2257
|
loginMethod: "phone",
|
|
2170
2258
|
phoneVerified: true
|
|
2171
2259
|
});
|
|
@@ -2342,6 +2430,7 @@ function toSessionDTO(row, currentSid) {
|
|
|
2342
2430
|
ipAddress: row.ipAddress,
|
|
2343
2431
|
userAgent: row.userAgent,
|
|
2344
2432
|
location: sanitizeLocation(row.location),
|
|
2433
|
+
clientKind: row.clientKind ?? null,
|
|
2345
2434
|
createdAt: row.createdAt instanceof Date ? row.createdAt.toISOString() : String(row.createdAt),
|
|
2346
2435
|
expiresAt: row.expiresAt instanceof Date ? row.expiresAt.toISOString() : String(row.expiresAt)
|
|
2347
2436
|
};
|
|
@@ -2890,7 +2979,7 @@ function oauthController(store, config, bus) {
|
|
|
2890
2979
|
return setApiResponse5(HTTP5.SERVER_ERROR, "SERVER_ERROR", "Apple login failed");
|
|
2891
2980
|
}
|
|
2892
2981
|
await announceOAuthUpsert(ctx, upserted, "apple", fullUser);
|
|
2893
|
-
const { accessToken, refreshToken, sid } = issueTokenPair(upserted.id, config, { loginMethod: "apple" });
|
|
2982
|
+
const { accessToken, refreshToken, sid } = issueTokenPair(upserted.id, configForClient(config, config.resolve?.(ctx), clientKindOf(ctx.request.headers)), { loginMethod: "apple" });
|
|
2894
2983
|
await sessions.create(upserted.id, refreshToken, refreshTokenExpiry(refreshToken), sid, meta);
|
|
2895
2984
|
await loginEvents.recordSafe({
|
|
2896
2985
|
userId: upserted.id,
|
|
@@ -3041,7 +3130,7 @@ function oauthController(store, config, bus) {
|
|
|
3041
3130
|
return setApiResponse5(HTTP5.SERVER_ERROR, "SERVER_ERROR", "OAuth login failed");
|
|
3042
3131
|
}
|
|
3043
3132
|
await announceOAuthUpsert(ctx, upserted, "google", fullUser);
|
|
3044
|
-
const { accessToken, refreshToken, sid } = issueTokenPair(upserted.id, config, {
|
|
3133
|
+
const { accessToken, refreshToken, sid } = issueTokenPair(upserted.id, configForClient(config, config.resolve?.(ctx), clientKindOf(ctx.request.headers)), {
|
|
3045
3134
|
loginMethod: "google"
|
|
3046
3135
|
});
|
|
3047
3136
|
await sessions.create(upserted.id, refreshToken, refreshTokenExpiry(refreshToken), sid, meta);
|
|
@@ -3629,7 +3718,7 @@ var AuthModule = class {
|
|
|
3629
3718
|
name = "@fonderie/auth";
|
|
3630
3719
|
// Baked in at build time by tsup.base, so the operator's Modules page can
|
|
3631
3720
|
// say what is actually deployed rather than 'not reported'.
|
|
3632
|
-
version = "7.
|
|
3721
|
+
version = "7.18.0";
|
|
3633
3722
|
// Users, sessions, login history, suspend — only through @fonderie/admin.
|
|
3634
3723
|
describeAdmin() {
|
|
3635
3724
|
return { routes: describeAuthAdminRoutes(this.store) };
|
|
@@ -4224,19 +4313,25 @@ function startUserRetention(store, options) {
|
|
|
4224
4313
|
export {
|
|
4225
4314
|
AUTH_CONFIG_KEYS,
|
|
4226
4315
|
AuthModule,
|
|
4316
|
+
CLIENT_KINDS,
|
|
4227
4317
|
DEFAULT_TEMPLATES,
|
|
4228
4318
|
MESSAGE_KEYS,
|
|
4319
|
+
SESSION_POLICY_PRESETS,
|
|
4229
4320
|
buildAuthAccountLimiter,
|
|
4230
4321
|
buildAuthIpLimiter,
|
|
4322
|
+
clientKindOf,
|
|
4323
|
+
configForClient,
|
|
4231
4324
|
describeAuthAdminRoutes,
|
|
4232
4325
|
importUser,
|
|
4233
4326
|
normalizeEmail,
|
|
4234
4327
|
normalizeEmailSafe,
|
|
4235
4328
|
purgeSoftDeletedUsers,
|
|
4329
|
+
readAuthRuntimeConfig,
|
|
4236
4330
|
requireAuth2 as requireAuth,
|
|
4237
4331
|
resolveLocation,
|
|
4238
4332
|
sanitizeLocation,
|
|
4239
4333
|
schemas_exports as schemas,
|
|
4334
|
+
sessionPolicyConfigKeys,
|
|
4240
4335
|
startUserRetention,
|
|
4241
4336
|
toAdminUserDTO,
|
|
4242
4337
|
toAdminUserPageDTO,
|