najm-auth 3.4.0 → 4.0.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/index.js CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/AuthPlugin.ts
9
- import { Err as Err15, plugin } from "najm-core";
9
+ import { Err as Err16, plugin } from "najm-core";
10
10
  import { cache } from "najm-cache";
11
11
 
12
12
  // src/auth.tokens.ts
@@ -354,6 +354,7 @@ function parseSessionCookiePayload(payload, maxAgeSeconds = DEFAULT_SESSION_MAX_
354
354
  if (!isRecord(data) || !isValidUser(data.user)) return null;
355
355
  if (!isStringArray(data.roles) || !isStringArray(data.permissions)) return null;
356
356
  if (!Number.isInteger(data.sessionVersion) || data.sessionVersion < 0) return null;
357
+ if (typeof data.tokenFamily !== "string" || !data.tokenFamily) return null;
357
358
  if (!Number.isFinite(data.iat) || !Number.isInteger(data.iat) || data.iat <= 0) return null;
358
359
  const issuedAt = data.iat;
359
360
  if (issuedAt > now + MAX_CLOCK_SKEW_MS) return null;
@@ -363,6 +364,7 @@ function parseSessionCookiePayload(payload, maxAgeSeconds = DEFAULT_SESSION_MAX_
363
364
  roles: [...data.roles],
364
365
  permissions: [...data.permissions],
365
366
  sessionVersion: data.sessionVersion,
367
+ tokenFamily: data.tokenFamily,
366
368
  iat: issuedAt
367
369
  };
368
370
  } catch {
@@ -439,8 +441,10 @@ var CookieManager = class CookieManager2 {
439
441
  // =========================================================================
440
442
  /**
441
443
  * Write a signed session cookie containing user data, roles, and permissions.
442
- * The cookie is HMAC-signed with the configured session secret so it is tamper-proof
443
- * but readable without a database query. Short TTL (5 min) ensures freshness.
444
+ * The cookie is HMAC-signed with the configured session secret, so its claims
445
+ * can be parsed without a database query. Authorization still verifies the
446
+ * session version and positive family liveness; a valid signature alone is
447
+ * never a revocation check. Short TTL (5 min) bounds claim staleness.
444
448
  */
445
449
  setSessionCookie(data) {
446
450
  const payload = { ...data, iat: Date.now() };
@@ -486,7 +490,7 @@ import { Get, Post, ResMsg } from "najm-core";
486
490
  import { Body, User as User2, Headers, Ctx } from "najm-core";
487
491
 
488
492
  // src/auth/AuthService.ts
489
- import { Injectable as Injectable11, Inject as Inject11 } from "najm-core";
493
+ import { Injectable as Injectable12, Inject as Inject12 } from "najm-core";
490
494
  import { Err as Err12, Log } from "najm-core";
491
495
  import { Transaction as Transaction4 } from "najm-database";
492
496
  import { I18n as I18n8, I18nService as I18nService2 } from "najm-i18n";
@@ -494,7 +498,7 @@ import { EmailService, passwordResetTemplate, accountInviteTemplate } from "najm
494
498
  import { nanoid as nanoid5 } from "nanoid";
495
499
 
496
500
  // src/users/UserService.ts
497
- import { Injectable as Injectable5, Inject as Inject5 } from "najm-core";
501
+ import { Injectable as Injectable6, Inject as Inject7 } from "najm-core";
498
502
  import { Transaction } from "najm-database";
499
503
  import { I18nService } from "najm-i18n";
500
504
  import { I18n as I18n4 } from "najm-i18n";
@@ -674,6 +678,15 @@ var UserRepository = class UserRepository2 {
674
678
  const [newUser] = await this.db.insert(this.users).values(data).returning();
675
679
  return newUser;
676
680
  }
681
+ /**
682
+ * Ids of everyone holding a role. Used to end sessions when the role's
683
+ * permission set changes: tokens carry permissions as claims, so the holders
684
+ * keep exercising the old set until their sessions do.
685
+ */
686
+ async getIdsByRole(roleId) {
687
+ const rows = await this.db.select({ id: this.users.id }).from(this.users).where(eq2(this.users.roleId, roleId));
688
+ return rows.map((row) => row.id);
689
+ }
677
690
  async update(id, data) {
678
691
  const [updatedUser] = await this.db.update(this.users).set(data).where(eq2(this.users.id, id)).returning();
679
692
  return updatedUser;
@@ -1334,6 +1347,16 @@ __name(isEmailIdentifier, "isEmailIdentifier");
1334
1347
 
1335
1348
  // src/users/UserService.ts
1336
1349
  import { Err as Err5 } from "najm-core";
1350
+
1351
+ // src/tokens/SessionInvalidationService.ts
1352
+ import { Inject as Inject6, Injectable as Injectable5 } from "najm-core";
1353
+ import { CacheService } from "najm-cache";
1354
+ import timestring2 from "timestring";
1355
+
1356
+ // src/tokens/TokenRepository.ts
1357
+ import { and, eq as eq4, isNull, lt } from "drizzle-orm";
1358
+ import { Repository as Repository3, Inject as Inject5 } from "najm-core";
1359
+ import { DB as DB3 } from "najm-database";
1337
1360
  var __decorate8 = function(decorators, target, key, desc) {
1338
1361
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1339
1362
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1343,19 +1366,383 @@ var __decorate8 = function(decorators, target, key, desc) {
1343
1366
  var __metadata8 = function(k, v) {
1344
1367
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1345
1368
  };
1369
+ var TokenRepository = class TokenRepository2 {
1370
+ static {
1371
+ __name(this, "TokenRepository");
1372
+ }
1373
+ db;
1374
+ schema;
1375
+ get tokens() {
1376
+ return this.schema.tokens;
1377
+ }
1378
+ get users() {
1379
+ return this.schema.users;
1380
+ }
1381
+ /** Shared query helper, scoped to the current database/transaction identity. */
1382
+ queryHelper;
1383
+ get q() {
1384
+ const db = this.db;
1385
+ if (this.queryHelper?.db !== db) {
1386
+ this.queryHelper = { db, queries: new AuthQueries(db, this.schema) };
1387
+ }
1388
+ return this.queryHelper.queries;
1389
+ }
1390
+ /**
1391
+ * Upsert the refresh-token row for a session, keyed on `tokenFamily` (the
1392
+ * per-login session identifier, unique). A brand-new login inserts a fresh
1393
+ * family row; a refresh rotation updates only that family's row, leaving the
1394
+ * user's other sessions untouched.
1395
+ */
1396
+ async storeRefreshToken(tokenData) {
1397
+ return await this.db.insert(this.tokens).values(tokenData).onConflictDoUpdate({
1398
+ target: this.tokens.tokenFamily,
1399
+ set: {
1400
+ token: tokenData.token,
1401
+ expiresAt: tokenData.expiresAt,
1402
+ previousHash: tokenData.previousHash ?? null,
1403
+ previousValidUntil: tokenData.previousValidUntil ?? null,
1404
+ previousUsedAt: tokenData.previousUsedAt ?? null
1405
+ },
1406
+ // A revoked family is a durable tombstone. It must never be revived by
1407
+ // an issuance racing with logout, or after the cache markers are lost.
1408
+ setWhere: and(eq4(this.tokens.status, "active"), eq4(this.tokens.userId, tokenData.userId))
1409
+ }).returning();
1410
+ }
1411
+ /**
1412
+ * Rotate an existing refresh-token family with compare-and-swap semantics.
1413
+ * This can never update a family durably revoked by a concurrent logout.
1414
+ */
1415
+ async rotateRefreshToken(tokenData, expectedCurrentHash) {
1416
+ return await this.db.update(this.tokens).set({
1417
+ token: tokenData.token,
1418
+ expiresAt: tokenData.expiresAt,
1419
+ previousHash: tokenData.previousHash,
1420
+ previousValidUntil: tokenData.previousValidUntil,
1421
+ previousUsedAt: tokenData.previousUsedAt ?? null
1422
+ }).where(and(eq4(this.tokens.tokenFamily, tokenData.tokenFamily), eq4(this.tokens.userId, tokenData.userId), eq4(this.tokens.token, expectedCurrentHash), eq4(this.tokens.status, "active"))).returning();
1423
+ }
1424
+ /**
1425
+ * Claim the previous-token grace slot for a single family. Conditional on
1426
+ * BOTH the stored previousHash still matching the presented token AND
1427
+ * previousUsedAt being NULL. Gating on the hash (not just the flag) closes
1428
+ * the rotation race: the winner's rotation rewrites previousHash via
1429
+ * storeRefreshToken (and resets previousUsedAt to NULL), so a loser whose
1430
+ * UPDATE lands after that rotation no longer matches and gets zero rows —
1431
+ * exactly one caller ever claims the slot.
1432
+ */
1433
+ async markPreviousUsed(tokenFamily, previousHash) {
1434
+ return await this.db.update(this.tokens).set({ previousUsedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.previousHash, previousHash), isNull(this.tokens.previousUsedAt), eq4(this.tokens.status, "active"))).returning();
1435
+ }
1436
+ /** Look up a single session's token row by its family identifier. */
1437
+ async getByFamily(tokenFamily) {
1438
+ const [token] = await this.db.select().from(this.tokens).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.status, "active")));
1439
+ return token ?? null;
1440
+ }
1441
+ /**
1442
+ * Durably revoke one family without depending on physical deletion.
1443
+ *
1444
+ * The row remains as a tombstone until its original refresh expiry. This is
1445
+ * what prevents a later cache loss from turning a failed/omitted cleanup
1446
+ * delete into a valid database-backed recovery session.
1447
+ */
1448
+ async revokeFamily(tokenFamily) {
1449
+ return this.db.update(this.tokens).set({
1450
+ status: "revoked",
1451
+ previousHash: null,
1452
+ previousValidUntil: null,
1453
+ previousUsedAt: null
1454
+ }).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.status, "active"))).returning();
1455
+ }
1456
+ /** Durably revoke every active family for a user. */
1457
+ async revokeAllForUser(userId) {
1458
+ return this.db.update(this.tokens).set({
1459
+ status: "revoked",
1460
+ previousHash: null,
1461
+ previousValidUntil: null,
1462
+ previousUsedAt: null
1463
+ }).where(and(eq4(this.tokens.userId, userId), eq4(this.tokens.status, "active"))).returning();
1464
+ }
1465
+ /**
1466
+ * Opportunistic cleanup: with one row per family (no unique userId), expired
1467
+ * and abandoned sessions accumulate. Delete every expired row.
1468
+ */
1469
+ async deleteExpired() {
1470
+ return this.db.delete(this.tokens).where(lt(this.tokens.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning();
1471
+ }
1472
+ async isUserExists(userId) {
1473
+ const [user] = await this.db.select({ id: this.users.id }).from(this.users).where(eq4(this.users.id, userId)).limit(1);
1474
+ return !!user;
1475
+ }
1476
+ async getRoleNameById(userId) {
1477
+ return this.q.getRoleName(userId);
1478
+ }
1479
+ async getUserPermissions(userId) {
1480
+ return this.q.getUserPermissions(userId);
1481
+ }
1482
+ async getRoleAndPermissions(userId) {
1483
+ return this.q.getRoleAndPermissions(userId);
1484
+ }
1485
+ async getUser(userId) {
1486
+ return await this.q.getUserWithPermissions(eq4(this.users.id, userId)) ?? null;
1487
+ }
1488
+ };
1489
+ __decorate8([
1490
+ DB3(),
1491
+ __metadata8("design:type", Object)
1492
+ ], TokenRepository.prototype, "db", void 0);
1493
+ __decorate8([
1494
+ Inject5(AUTH_SCHEMA),
1495
+ __metadata8("design:type", Object)
1496
+ ], TokenRepository.prototype, "schema", void 0);
1497
+ TokenRepository = __decorate8([
1498
+ Repository3()
1499
+ ], TokenRepository);
1500
+
1501
+ // src/tokens/SessionInvalidationService.ts
1502
+ var __decorate9 = function(decorators, target, key, desc) {
1503
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1504
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1505
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1506
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1507
+ };
1508
+ var __metadata9 = function(k, v) {
1509
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1510
+ };
1511
+ var SessionInvalidationService_1;
1512
+ var _a5;
1513
+ var _b3;
1514
+ var SessionInvalidationService = class SessionInvalidationService2 {
1515
+ static {
1516
+ __name(this, "SessionInvalidationService");
1517
+ }
1518
+ static {
1519
+ SessionInvalidationService_1 = this;
1520
+ }
1521
+ cache;
1522
+ tokens;
1523
+ config;
1524
+ constructor(cache2, tokens) {
1525
+ this.cache = cache2;
1526
+ this.tokens = tokens;
1527
+ }
1528
+ /**
1529
+ * Fields whose change ends existing sessions. Everything absent from this set
1530
+ * — display name, avatar, language — is a profile edit and must leave the
1531
+ * user signed in, on every device.
1532
+ */
1533
+ static SECURITY_FIELDS = Object.freeze([
1534
+ "password",
1535
+ "status",
1536
+ "role",
1537
+ "roleId",
1538
+ "email",
1539
+ "emailVerified",
1540
+ "phone"
1541
+ ]);
1542
+ /** Whether an update payload touches anything that must end sessions. */
1543
+ static affectsSecurityState(data) {
1544
+ if (!data)
1545
+ return false;
1546
+ return SessionInvalidationService_1.SECURITY_FIELDS.some((field) => data[field] !== void 0);
1547
+ }
1548
+ get accessTokenTtlMs() {
1549
+ return timestring2(this.config.jwt.accessExpiresIn, "ms");
1550
+ }
1551
+ get refreshTokenTtlMs() {
1552
+ return timestring2(this.config.jwt.refreshExpiresIn, "ms");
1553
+ }
1554
+ sessionVersionKey(userId) {
1555
+ return `auth:session-version:${userId}`;
1556
+ }
1557
+ revokedFamilyKey(tokenFamily) {
1558
+ return `auth:revoked-family:${tokenFamily}`;
1559
+ }
1560
+ /**
1561
+ * Positive liveness marker for one session family.
1562
+ *
1563
+ * The signed session snapshot is authorized against this rather than against
1564
+ * the absence of a revocation marker, so losing the cache cannot make a
1565
+ * logged-out family look valid again: with no marker the fast path simply
1566
+ * declines and the request falls through to the database-backed resolver.
1567
+ */
1568
+ familyKey(tokenFamily) {
1569
+ return `auth:family:${tokenFamily}`;
1570
+ }
1571
+ userCacheKey(userId) {
1572
+ return `auth:user:${userId}`;
1573
+ }
1574
+ parseSessionVersion(raw) {
1575
+ if (!raw)
1576
+ return 0;
1577
+ const parsed = Number(raw);
1578
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
1579
+ }
1580
+ async getSessionVersion(userId) {
1581
+ return this.parseSessionVersion(await this.cache.get(this.sessionVersionKey(userId)));
1582
+ }
1583
+ /**
1584
+ * Extend the version key's lifetime without rewriting its value.
1585
+ *
1586
+ * Token issuance used to `set()` the version it had just read, which meant an
1587
+ * invalidation landing between that read and that write was silently undone —
1588
+ * the revoked version came back and the old tokens verified again. Only the
1589
+ * expiry is touched here, so a concurrent bump always survives.
1590
+ */
1591
+ async touchSessionVersion(userId) {
1592
+ await this.cache.expire(this.sessionVersionKey(userId), this.accessTokenTtlMs);
1593
+ }
1594
+ /**
1595
+ * Invalidate every access token already issued for a user, and drop the
1596
+ * cached user record so the next read sees the new state rather than a stale
1597
+ * snapshot that is merely truthy.
1598
+ *
1599
+ * The bump is an atomic increment, so concurrent invalidations cannot read
1600
+ * the same version and write the same successor back.
1601
+ */
1602
+ async invalidateAccessTokens(userId) {
1603
+ const key = this.sessionVersionKey(userId);
1604
+ const { count } = await this.cache.incr(key, this.accessTokenTtlMs);
1605
+ await this.cache.expire(key, this.accessTokenTtlMs);
1606
+ await this.dropUserCache(userId);
1607
+ return count;
1608
+ }
1609
+ async dropUserCache(userId) {
1610
+ await this.cache.del(this.userCacheKey(userId));
1611
+ }
1612
+ /**
1613
+ * End every session a user holds: access tokens by version, refresh sessions
1614
+ * by row, and each family's liveness marker.
1615
+ *
1616
+ * Callers run this AFTER their database mutation has committed. Running it
1617
+ * before would leave a window in which a concurrent login re-established a
1618
+ * session against the state the mutation was about to remove; running it
1619
+ * after a rollback merely signs the user out again, which is safe.
1620
+ */
1621
+ async invalidateUser(userId) {
1622
+ await this.invalidateAccessTokens(userId);
1623
+ const revoked = await this.tokens.revokeAllForUser(userId);
1624
+ await Promise.all(familiesOf(revoked).map((family) => this.markFamilyRevoked(family)));
1625
+ }
1626
+ /**
1627
+ * Record that a family is live, and whose it is. Called wherever the family's
1628
+ * refresh row is written.
1629
+ *
1630
+ * The marker stores the owning user rather than a bare flag so a reader can
1631
+ * confirm, in the same single lookup, that the family it was handed actually
1632
+ * belongs to the identity claiming it.
1633
+ *
1634
+ * Revocation always wins. A refresh that rotated its row, was descheduled,
1635
+ * and resumed after a logout would otherwise re-mark its family live and
1636
+ * hand the browser back the session it had just ended — the database row is
1637
+ * gone by then, but nothing on the fast path reads the database. So this
1638
+ * writes, then re-reads the revocation marker and withdraws the write if one
1639
+ * appeared. Combined with `markFamilyRevoked` setting the revocation marker
1640
+ * *before* clearing liveness, every interleaving of the two converges on
1641
+ * revoked: whichever of the pair observes the other, the liveness key ends
1642
+ * up deleted.
1643
+ *
1644
+ * @returns whether the family is live after this call.
1645
+ */
1646
+ async markFamilyIssued(tokenFamily, userId) {
1647
+ await this.cache.set(this.familyKey(tokenFamily), userId, this.refreshTokenTtlMs);
1648
+ if (await this.isFamilyRevoked(tokenFamily)) {
1649
+ await this.cache.del(this.familyKey(tokenFamily));
1650
+ return false;
1651
+ }
1652
+ return true;
1653
+ }
1654
+ /**
1655
+ * What one lookup can say about a family, in a single batched cache read.
1656
+ *
1657
+ * The three answers are deliberately distinct. `revoked` is authoritative and
1658
+ * must deny. `unknown` means the cache cannot vouch for the family — it was
1659
+ * evicted, or the cache was lost — and must send the caller to an
1660
+ * authoritative, database-backed check rather than being read either way.
1661
+ * Only `live` is a positive assertion, and only for the named user.
1662
+ */
1663
+ async familyStatus(tokenFamily, userId) {
1664
+ if (!tokenFamily)
1665
+ return "unknown";
1666
+ const [owner, revoked] = await this.readMany([
1667
+ this.familyKey(tokenFamily),
1668
+ this.revokedFamilyKey(tokenFamily)
1669
+ ]);
1670
+ if (revoked != null)
1671
+ return "revoked";
1672
+ if (owner == null)
1673
+ return "unknown";
1674
+ if (userId !== void 0 && owner !== userId)
1675
+ return "revoked";
1676
+ return "live";
1677
+ }
1678
+ /**
1679
+ * Whether a family is positively known to be live, and — when a user is
1680
+ * given — to belong to that user.
1681
+ *
1682
+ * `false` means "not proven live" — revoked, mismatched, or simply not in
1683
+ * cache. Callers must treat it as a reason to fall back to an authoritative
1684
+ * check, never as proof of validity in the other direction.
1685
+ */
1686
+ async isFamilyLive(tokenFamily, userId) {
1687
+ return await this.familyStatus(tokenFamily, userId) === "live";
1688
+ }
1689
+ async readMany(keys) {
1690
+ const cache2 = this.cache;
1691
+ if (cache2.getMany)
1692
+ return cache2.getMany(keys);
1693
+ return Promise.all(keys.map((key) => cache2.get(key)));
1694
+ }
1695
+ /**
1696
+ * Keep revocation through both credential lifetimes. If deleting the refresh
1697
+ * row fails, its still-valid cookie must remain denied after access expires.
1698
+ */
1699
+ async markFamilyRevoked(tokenFamily) {
1700
+ await this.cache.set(this.revokedFamilyKey(tokenFamily), "1", Math.max(this.accessTokenTtlMs, this.refreshTokenTtlMs));
1701
+ await this.cache.del(this.familyKey(tokenFamily));
1702
+ }
1703
+ async isFamilyRevoked(tokenFamily) {
1704
+ return await this.cache.get(this.revokedFamilyKey(tokenFamily)) !== null;
1705
+ }
1706
+ };
1707
+ __decorate9([
1708
+ Inject6(AUTH_CONFIG),
1709
+ __metadata9("design:type", Object)
1710
+ ], SessionInvalidationService.prototype, "config", void 0);
1711
+ SessionInvalidationService = SessionInvalidationService_1 = __decorate9([
1712
+ Injectable5(),
1713
+ __metadata9("design:paramtypes", [typeof (_a5 = typeof CacheService !== "undefined" && CacheService) === "function" ? _a5 : Object, typeof (_b3 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _b3 : Object])
1714
+ ], SessionInvalidationService);
1715
+ function familiesOf(rows) {
1716
+ if (!Array.isArray(rows))
1717
+ return [];
1718
+ return rows.map((row) => row?.tokenFamily).filter((family) => typeof family === "string" && family.length > 0);
1719
+ }
1720
+ __name(familiesOf, "familiesOf");
1721
+
1722
+ // src/users/UserService.ts
1723
+ var __decorate10 = function(decorators, target, key, desc) {
1724
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1725
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1726
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1727
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1728
+ };
1729
+ var __metadata10 = function(k, v) {
1730
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1731
+ };
1346
1732
  var __param2 = function(paramIndex, decorator) {
1347
1733
  return function(target, key) {
1348
1734
  decorator(target, key, paramIndex);
1349
1735
  };
1350
1736
  };
1351
- var _a5;
1352
- var _b3;
1737
+ var _a6;
1738
+ var _b4;
1353
1739
  var _c;
1354
1740
  var _d;
1355
1741
  var _e;
1356
1742
  var _f;
1357
1743
  var _g;
1358
1744
  var _h;
1745
+ var _j;
1359
1746
  var E164_PHONE = /^\+[1-9]\d{7,14}$/;
1360
1747
  var UserService = class UserService2 {
1361
1748
  static {
@@ -1368,8 +1755,9 @@ var UserService = class UserService2 {
1368
1755
  encryptionService;
1369
1756
  i18nService;
1370
1757
  authConfig;
1758
+ sessionInvalidation;
1371
1759
  t;
1372
- constructor(roleValidator, roleService, userRepository, userValidator, encryptionService, i18nService, authConfig) {
1760
+ constructor(roleValidator, roleService, userRepository, userValidator, encryptionService, i18nService, authConfig, sessionInvalidation) {
1373
1761
  this.roleValidator = roleValidator;
1374
1762
  this.roleService = roleService;
1375
1763
  this.userRepository = userRepository;
@@ -1377,6 +1765,19 @@ var UserService = class UserService2 {
1377
1765
  this.encryptionService = encryptionService;
1378
1766
  this.i18nService = i18nService;
1379
1767
  this.authConfig = authConfig;
1768
+ this.sessionInvalidation = sessionInvalidation;
1769
+ }
1770
+ /**
1771
+ * End the user's sessions after a security-relevant mutation has committed.
1772
+ *
1773
+ * Deactivating, deleting, or re-roling an account through the generic
1774
+ * endpoints used to leave every already-issued token working until it
1775
+ * expired. Invalidation belongs here, next to the write, so no caller can
1776
+ * forget it — the application-level commands that already revoke keep doing
1777
+ * so, and a second call is harmless.
1778
+ */
1779
+ async invalidateSessions(userId) {
1780
+ await this.sessionInvalidation?.invalidateUser(userId);
1380
1781
  }
1381
1782
  sanitizeUser(user) {
1382
1783
  if (!user)
@@ -1494,15 +1895,23 @@ var UserService = class UserService2 {
1494
1895
  };
1495
1896
  const cleanedUpdateData = clean(updateData);
1496
1897
  const updatedUser = await this.userRepository.update(id, cleanedUpdateData);
1497
- return this.sanitizeUser(this.requireUser(updatedUser));
1898
+ const result = this.sanitizeUser(this.requireUser(updatedUser));
1899
+ if (SessionInvalidationService.affectsSecurityState(cleanedUpdateData)) {
1900
+ await this.invalidateSessions(id);
1901
+ }
1902
+ return result;
1498
1903
  }
1499
1904
  async delete(id) {
1500
1905
  const user = await this.userRepository.delete(id);
1501
- return this.sanitizeUser(this.requireUser(user));
1906
+ const result = this.sanitizeUser(this.requireUser(user));
1907
+ await this.invalidateSessions(id);
1908
+ return result;
1502
1909
  }
1503
1910
  async deleteAll() {
1504
1911
  const deletedUsers = await this.userRepository.deleteAll();
1505
- return this.sanitizeUsers(deletedUsers);
1912
+ const result = this.sanitizeUsers(deletedUsers);
1913
+ await Promise.all(result.map((user) => this.invalidateSessions(user.id)));
1914
+ return result;
1506
1915
  }
1507
1916
  async getRoleName(id) {
1508
1917
  await this.userValidator.checkUserExists(id);
@@ -1524,11 +1933,15 @@ var UserService = class UserService2 {
1524
1933
  async assignRole(id, roleId, roleName) {
1525
1934
  const resolvedRoleId = await this.resolveUserRole(roleId, roleName);
1526
1935
  const updatedUser = await this.userRepository.update(id, { roleId: resolvedRoleId });
1527
- return this.sanitizeUser(this.requireUser(updatedUser));
1936
+ const result = this.sanitizeUser(this.requireUser(updatedUser));
1937
+ await this.invalidateSessions(id);
1938
+ return result;
1528
1939
  }
1529
1940
  async removeRole(id) {
1530
1941
  const updatedUser = await this.userRepository.update(id, { roleId: null });
1531
- return this.sanitizeUser(this.requireUser(updatedUser));
1942
+ const result = this.sanitizeUser(this.requireUser(updatedUser));
1943
+ await this.invalidateSessions(id);
1944
+ return result;
1532
1945
  }
1533
1946
  async seedAdminUser(config) {
1534
1947
  if (!config?.email || !config?.password) {
@@ -1563,170 +1976,42 @@ var UserService = class UserService2 {
1563
1976
  return this.i18nService.getCurrentLanguage();
1564
1977
  }
1565
1978
  };
1566
- __decorate8([
1979
+ __decorate10([
1567
1980
  I18n4("users"),
1568
- __metadata8("design:type", Object)
1981
+ __metadata10("design:type", Object)
1569
1982
  ], UserService.prototype, "t", void 0);
1570
- __decorate8([
1983
+ __decorate10([
1571
1984
  Transaction(),
1572
- __metadata8("design:type", Function),
1573
- __metadata8("design:paramtypes", [typeof (_g = typeof Record !== "undefined" && Record) === "function" ? _g : Object, Object]),
1574
- __metadata8("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object)
1985
+ __metadata10("design:type", Function),
1986
+ __metadata10("design:paramtypes", [typeof (_h = typeof Record !== "undefined" && Record) === "function" ? _h : Object, Object]),
1987
+ __metadata10("design:returntype", typeof (_j = typeof Promise !== "undefined" && Promise) === "function" ? _j : Object)
1575
1988
  ], UserService.prototype, "create", null);
1576
- UserService = __decorate8([
1577
- Injectable5(),
1578
- __param2(6, Inject5(AUTH_CONFIG)),
1579
- __metadata8("design:paramtypes", [typeof (_a5 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _a5 : Object, typeof (_b3 = typeof RoleService !== "undefined" && RoleService) === "function" ? _b3 : Object, typeof (_c = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _c : Object, typeof (_d = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _d : Object, typeof (_e = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _e : Object, typeof (_f = typeof I18nService !== "undefined" && I18nService) === "function" ? _f : Object, Object])
1989
+ UserService = __decorate10([
1990
+ Injectable6(),
1991
+ __param2(6, Inject7(AUTH_CONFIG)),
1992
+ __metadata10("design:paramtypes", [typeof (_a6 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _a6 : Object, typeof (_b4 = typeof RoleService !== "undefined" && RoleService) === "function" ? _b4 : Object, typeof (_c = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _c : Object, typeof (_d = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _d : Object, typeof (_e = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _e : Object, typeof (_f = typeof I18nService !== "undefined" && I18nService) === "function" ? _f : Object, Object, typeof (_g = typeof SessionInvalidationService !== "undefined" && SessionInvalidationService) === "function" ? _g : Object])
1580
1993
  ], UserService);
1581
1994
 
1582
1995
  // src/tokens/TokenService.ts
1583
- import { Injectable as Injectable6, Inject as Inject8 } from "najm-core";
1996
+ import { Injectable as Injectable7, Inject as Inject9 } from "najm-core";
1584
1997
  import { I18n as I18n5 } from "najm-i18n";
1585
- import { CacheService } from "najm-cache";
1998
+ import { CacheService as CacheService2 } from "najm-cache";
1586
1999
  import { createHash } from "crypto";
1587
2000
  import jwt from "jsonwebtoken";
1588
2001
  import { nanoid as nanoid4 } from "nanoid";
1589
-
1590
- // src/tokens/TokenRepository.ts
1591
- import { and, eq as eq4, isNull, lt } from "drizzle-orm";
1592
- import { Repository as Repository3, Inject as Inject6 } from "najm-core";
1593
- import { DB as DB3 } from "najm-database";
1594
- var __decorate9 = function(decorators, target, key, desc) {
1595
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1596
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1597
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1598
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1599
- };
1600
- var __metadata9 = function(k, v) {
1601
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1602
- };
1603
- var TokenRepository = class TokenRepository2 {
1604
- static {
1605
- __name(this, "TokenRepository");
1606
- }
1607
- db;
1608
- schema;
1609
- get tokens() {
1610
- return this.schema.tokens;
1611
- }
1612
- get users() {
1613
- return this.schema.users;
1614
- }
1615
- /** Shared query helper, scoped to the current database/transaction identity. */
1616
- queryHelper;
1617
- get q() {
1618
- const db = this.db;
1619
- if (this.queryHelper?.db !== db) {
1620
- this.queryHelper = { db, queries: new AuthQueries(db, this.schema) };
1621
- }
1622
- return this.queryHelper.queries;
1623
- }
1624
- /**
1625
- * Upsert the refresh-token row for a session, keyed on `tokenFamily` (the
1626
- * per-login session identifier, unique). A brand-new login inserts a fresh
1627
- * family row; a refresh rotation updates only that family's row, leaving the
1628
- * user's other sessions untouched.
1629
- */
1630
- async storeRefreshToken(tokenData) {
1631
- return await this.db.insert(this.tokens).values(tokenData).onConflictDoUpdate({
1632
- target: this.tokens.tokenFamily,
1633
- set: {
1634
- token: tokenData.token,
1635
- expiresAt: tokenData.expiresAt,
1636
- previousHash: tokenData.previousHash ?? null,
1637
- previousValidUntil: tokenData.previousValidUntil ?? null,
1638
- previousUsedAt: tokenData.previousUsedAt ?? null
1639
- }
1640
- }).returning();
1641
- }
1642
- /**
1643
- * Rotate an existing refresh-token family with compare-and-swap semantics.
1644
- * This can never insert a family deleted by a concurrent logout.
1645
- */
1646
- async rotateRefreshToken(tokenData, expectedCurrentHash) {
1647
- return await this.db.update(this.tokens).set({
1648
- token: tokenData.token,
1649
- expiresAt: tokenData.expiresAt,
1650
- previousHash: tokenData.previousHash,
1651
- previousValidUntil: tokenData.previousValidUntil,
1652
- previousUsedAt: tokenData.previousUsedAt ?? null
1653
- }).where(and(eq4(this.tokens.tokenFamily, tokenData.tokenFamily), eq4(this.tokens.userId, tokenData.userId), eq4(this.tokens.token, expectedCurrentHash))).returning();
1654
- }
1655
- /**
1656
- * Claim the previous-token grace slot for a single family. Conditional on
1657
- * BOTH the stored previousHash still matching the presented token AND
1658
- * previousUsedAt being NULL. Gating on the hash (not just the flag) closes
1659
- * the rotation race: the winner's rotation rewrites previousHash via
1660
- * storeRefreshToken (and resets previousUsedAt to NULL), so a loser whose
1661
- * UPDATE lands after that rotation no longer matches and gets zero rows —
1662
- * exactly one caller ever claims the slot.
1663
- */
1664
- async markPreviousUsed(tokenFamily, previousHash) {
1665
- return await this.db.update(this.tokens).set({ previousUsedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.previousHash, previousHash), isNull(this.tokens.previousUsedAt))).returning();
1666
- }
1667
- /** Look up a single session's token row by its family identifier. */
1668
- async getByFamily(tokenFamily) {
1669
- const [token] = await this.db.select().from(this.tokens).where(eq4(this.tokens.tokenFamily, tokenFamily));
1670
- return token ?? null;
1671
- }
1672
- /** Revoke a single session (one family). */
1673
- async revokeFamily(tokenFamily) {
1674
- return this.db.delete(this.tokens).where(eq4(this.tokens.tokenFamily, tokenFamily)).returning();
1675
- }
1676
- /** Revoke every session for a user (password change/reset, logout-all). */
1677
- async revokeAllForUser(userId) {
1678
- return this.db.delete(this.tokens).where(eq4(this.tokens.userId, userId)).returning();
1679
- }
1680
- /**
1681
- * Opportunistic cleanup: with one row per family (no unique userId), expired
1682
- * and abandoned sessions accumulate. Delete every expired row.
1683
- */
1684
- async deleteExpired() {
1685
- return this.db.delete(this.tokens).where(lt(this.tokens.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning();
1686
- }
1687
- async isUserExists(userId) {
1688
- const [user] = await this.db.select({ id: this.users.id }).from(this.users).where(eq4(this.users.id, userId)).limit(1);
1689
- return !!user;
1690
- }
1691
- async getRoleNameById(userId) {
1692
- return this.q.getRoleName(userId);
1693
- }
1694
- async getUserPermissions(userId) {
1695
- return this.q.getUserPermissions(userId);
1696
- }
1697
- async getRoleAndPermissions(userId) {
1698
- return this.q.getRoleAndPermissions(userId);
1699
- }
1700
- async getUser(userId) {
1701
- return await this.q.getUserWithPermissions(eq4(this.users.id, userId)) ?? null;
1702
- }
1703
- };
1704
- __decorate9([
1705
- DB3(),
1706
- __metadata9("design:type", Object)
1707
- ], TokenRepository.prototype, "db", void 0);
1708
- __decorate9([
1709
- Inject6(AUTH_SCHEMA),
1710
- __metadata9("design:type", Object)
1711
- ], TokenRepository.prototype, "schema", void 0);
1712
- TokenRepository = __decorate9([
1713
- Repository3()
1714
- ], TokenRepository);
1715
-
1716
- // src/tokens/TokenService.ts
1717
- import timestring2 from "timestring";
2002
+ import timestring3 from "timestring";
1718
2003
 
1719
2004
  // src/credentialSetup/CredentialSetupRequirementRepository.ts
1720
2005
  import { and as and2, eq as eq5 } from "drizzle-orm";
1721
- import { Err as Err6, Inject as Inject7, Repository as Repository4 } from "najm-core";
2006
+ import { Err as Err6, Inject as Inject8, Repository as Repository4 } from "najm-core";
1722
2007
  import { DB as DB4 } from "najm-database";
1723
- var __decorate10 = function(decorators, target, key, desc) {
2008
+ var __decorate11 = function(decorators, target, key, desc) {
1724
2009
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1725
2010
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1726
2011
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1727
2012
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1728
2013
  };
1729
- var __metadata10 = function(k, v) {
2014
+ var __metadata11 = function(k, v) {
1730
2015
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1731
2016
  };
1732
2017
  var CredentialSetupRequirementRepository = class CredentialSetupRequirementRepository2 {
@@ -1774,15 +2059,15 @@ var CredentialSetupRequirementRepository = class CredentialSetupRequirementRepos
1774
2059
  return requirement;
1775
2060
  }
1776
2061
  };
1777
- __decorate10([
2062
+ __decorate11([
1778
2063
  DB4(),
1779
- __metadata10("design:type", Object)
2064
+ __metadata11("design:type", Object)
1780
2065
  ], CredentialSetupRequirementRepository.prototype, "db", void 0);
1781
- __decorate10([
1782
- Inject7(AUTH_SCHEMA),
1783
- __metadata10("design:type", Object)
2066
+ __decorate11([
2067
+ Inject8(AUTH_SCHEMA),
2068
+ __metadata11("design:type", Object)
1784
2069
  ], CredentialSetupRequirementRepository.prototype, "schema", void 0);
1785
- CredentialSetupRequirementRepository = __decorate10([
2070
+ CredentialSetupRequirementRepository = __decorate11([
1786
2071
  Repository4()
1787
2072
  ], CredentialSetupRequirementRepository);
1788
2073
 
@@ -1791,20 +2076,21 @@ var PASSWORD_SETUP_PURPOSE = "password";
1791
2076
 
1792
2077
  // src/tokens/TokenService.ts
1793
2078
  import { Err as Err7 } from "najm-core";
1794
- var __decorate11 = function(decorators, target, key, desc) {
2079
+ var __decorate12 = function(decorators, target, key, desc) {
1795
2080
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1796
2081
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1797
2082
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1798
2083
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1799
2084
  };
1800
- var __metadata11 = function(k, v) {
2085
+ var __metadata12 = function(k, v) {
1801
2086
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1802
2087
  };
1803
2088
  var TokenService_1;
1804
- var _a6;
1805
- var _b4;
2089
+ var _a7;
2090
+ var _b5;
1806
2091
  var _c2;
1807
2092
  var _d2;
2093
+ var _e2;
1808
2094
  var TokenService = class TokenService2 {
1809
2095
  static {
1810
2096
  __name(this, "TokenService");
@@ -1816,13 +2102,23 @@ var TokenService = class TokenService2 {
1816
2102
  cookieManager;
1817
2103
  cache;
1818
2104
  credentialSetupRequirements;
2105
+ sessions;
1819
2106
  config;
1820
2107
  t;
1821
- constructor(tokenRepository, cookieManager, cache2, credentialSetupRequirements) {
2108
+ constructor(tokenRepository, cookieManager, cache2, credentialSetupRequirements, sessions) {
1822
2109
  this.tokenRepository = tokenRepository;
1823
2110
  this.cookieManager = cookieManager;
1824
2111
  this.cache = cache2;
1825
2112
  this.credentialSetupRequirements = credentialSetupRequirements;
2113
+ this.sessions = sessions;
2114
+ }
2115
+ /** The shared invalidation contract — see SessionInvalidationService. */
2116
+ get invalidation() {
2117
+ if (!this.sessions) {
2118
+ this.sessions = new SessionInvalidationService(this.cache, this.tokenRepository);
2119
+ this.sessions.config = this.config;
2120
+ }
2121
+ return this.sessions;
1826
2122
  }
1827
2123
  /**
1828
2124
  * Get blacklist key prefix
@@ -1833,17 +2129,11 @@ var TokenService = class TokenService2 {
1833
2129
  get resetTokenPrefix() {
1834
2130
  return "auth:reset:";
1835
2131
  }
1836
- get sessionVersionPrefix() {
1837
- return "auth:session-version:";
1838
- }
1839
2132
  sessionVersionKey(userId) {
1840
- return `${this.sessionVersionPrefix}${userId}`;
1841
- }
1842
- accessTokenTtlMs() {
1843
- return timestring2(this.config.jwt.accessExpiresIn, "ms");
2133
+ return this.invalidation.sessionVersionKey(userId);
1844
2134
  }
1845
2135
  expiresAt(expiresIn) {
1846
- return Math.floor((Date.now() + timestring2(expiresIn, "ms")) / 1e3);
2136
+ return Math.floor((Date.now() + timestring3(expiresIn, "ms")) / 1e3);
1847
2137
  }
1848
2138
  async getCacheValues(keys) {
1849
2139
  const cache2 = this.cache;
@@ -1852,10 +2142,7 @@ var TokenService = class TokenService2 {
1852
2142
  return Promise.all(keys.map((key) => cache2.get(key)));
1853
2143
  }
1854
2144
  parseSessionVersion(raw) {
1855
- if (!raw)
1856
- return 0;
1857
- const parsed = Number(raw);
1858
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
2145
+ return this.invalidation.parseSessionVersion(raw);
1859
2146
  }
1860
2147
  // ============ TOKEN VALIDATION ============
1861
2148
  extractAccessToken(authorization) {
@@ -1877,18 +2164,23 @@ var TokenService = class TokenService2 {
1877
2164
  }
1878
2165
  const sessionKey = this.sessionVersionKey(payload.userId);
1879
2166
  const blacklistKey = payload.jti ? `${this.blacklistPrefix}${payload.jti}` : null;
1880
- const familyKey = payload.tokenFamily ? this.revokedFamilyKey(payload.tokenFamily) : null;
2167
+ const revokedKey = payload.tokenFamily ? this.revokedFamilyKey(payload.tokenFamily) : null;
2168
+ const liveKey = payload.tokenFamily ? this.invalidation.familyKey(payload.tokenFamily) : null;
1881
2169
  const keys = [
1882
2170
  ...blacklistKey ? [blacklistKey] : [],
1883
2171
  sessionKey,
1884
- ...familyKey ? [familyKey] : []
2172
+ ...revokedKey ? [revokedKey] : [],
2173
+ ...liveKey ? [liveKey] : []
1885
2174
  ];
1886
2175
  const values = await this.getCacheValues(keys);
1887
2176
  const valueByKey = new Map(keys.map((key, i) => [key, values[i]]));
1888
2177
  if (blacklistKey && valueByKey.get(blacklistKey) != null) {
1889
2178
  Err7(this.t("errors.tokenRevoked"), 401);
1890
2179
  }
1891
- if (familyKey && valueByKey.get(familyKey) != null) {
2180
+ if (revokedKey && valueByKey.get(revokedKey) != null) {
2181
+ Err7(this.t("errors.tokenRevoked"), 401);
2182
+ }
2183
+ if (!liveKey || valueByKey.get(liveKey) !== payload.userId) {
1892
2184
  Err7(this.t("errors.tokenRevoked"), 401);
1893
2185
  }
1894
2186
  const activeSessionVersion = this.parseSessionVersion(valueByKey.get(sessionKey) ?? null);
@@ -1922,6 +2214,11 @@ var TokenService = class TokenService2 {
1922
2214
  this.clearRefreshSessionCookies();
1923
2215
  Err7(this.t(messageKey), 401);
1924
2216
  }
2217
+ async assertRefreshFamilyAllowed(tokenFamily, userId) {
2218
+ if (await this.invalidation.familyStatus(tokenFamily, userId) === "revoked") {
2219
+ this.rejectRefreshSession();
2220
+ }
2221
+ }
1925
2222
  readRefreshSessionCookie() {
1926
2223
  const refreshToken = this.cookieManager.getRefreshToken();
1927
2224
  if (!refreshToken) {
@@ -1948,6 +2245,7 @@ var TokenService = class TokenService2 {
1948
2245
  async resolveRefreshSessionFromCookie() {
1949
2246
  const { refreshToken, userId, tokenFamily } = this.readRefreshSessionCookie();
1950
2247
  const stored = await this.tokenRepository.getByFamily(tokenFamily);
2248
+ await this.assertRefreshFamilyAllowed(tokenFamily, userId);
1951
2249
  if (!stored || stored.userId !== userId) {
1952
2250
  this.rejectRefreshSession();
1953
2251
  }
@@ -1979,7 +2277,8 @@ var TokenService = class TokenService2 {
1979
2277
  user,
1980
2278
  roles: user.role ? [user.role] : [],
1981
2279
  permissions: Array.isArray(user.permissions) ? user.permissions : [],
1982
- sessionVersion
2280
+ sessionVersion,
2281
+ tokenFamily
1983
2282
  };
1984
2283
  }
1985
2284
  // ============ USER RETRIEVAL (MAIN METHOD) ============
@@ -1988,7 +2287,26 @@ var TokenService = class TokenService2 {
1988
2287
  return null;
1989
2288
  const token = this.extractAccessToken(auth2);
1990
2289
  const { userId } = await this.verifyAccessToken(token);
1991
- return this.getUserById(userId);
2290
+ return this.requireActiveUser(await this.getUserById(userId));
2291
+ }
2292
+ /**
2293
+ * A user record is only an authorization if the account is still usable.
2294
+ *
2295
+ * A valid signature and an unrevoked version say the *token* is intact; they
2296
+ * say nothing about whether the account behind it was since deactivated or
2297
+ * deleted. Session invalidation is what normally ends such a token, but this
2298
+ * check is what makes a truthy cached record insufficient on its own — so a
2299
+ * missed invalidation, or a record filled into cache moments before the
2300
+ * change, still cannot authorize a request.
2301
+ */
2302
+ requireActiveUser(user) {
2303
+ if (!user) {
2304
+ Err7(this.t("errors.tokenVerificationFailed"), 401);
2305
+ }
2306
+ if (user.status !== void 0 && user.status !== "active") {
2307
+ Err7(this.t("errors.accountInactive"), 403);
2308
+ }
2309
+ return user;
1992
2310
  }
1993
2311
  async getUserById(userId) {
1994
2312
  const cacheKey = `auth:user:${userId}`;
@@ -2018,7 +2336,7 @@ var TokenService = class TokenService2 {
2018
2336
  const sessionVersion = await this.getUserSessionVersion(data.userId);
2019
2337
  const expiresAt = this.expiresAt(this.config.jwt.accessExpiresIn);
2020
2338
  if (sessionVersion > 0) {
2021
- await this.cache.set(this.sessionVersionKey(data.userId), String(sessionVersion), this.accessTokenTtlMs());
2339
+ await this.invalidation.touchSessionVersion(data.userId);
2022
2340
  }
2023
2341
  const token = jwt.sign({ ...data, jti, sessionVersion, exp: expiresAt }, this.config.jwt.accessSecret);
2024
2342
  return { token, expiresAt, sessionVersion };
@@ -2031,9 +2349,24 @@ var TokenService = class TokenService2 {
2031
2349
  async getSessionVersion(userId) {
2032
2350
  return this.getUserSessionVersion(userId);
2033
2351
  }
2352
+ /**
2353
+ * Whether one session family is positively known to be live.
2354
+ *
2355
+ * `false` means "not proven live" — logged out, or simply not in cache — and
2356
+ * is a reason to fall back to an authoritative check, never on its own a
2357
+ * reason to treat a session as valid.
2358
+ */
2359
+ async isSessionFamilyLive(tokenFamily, userId) {
2360
+ return await this.invalidation.familyStatus(tokenFamily, userId) === "live";
2361
+ }
2034
2362
  /**
2035
2363
  * Generate access token with unique jti for blacklist support.
2036
2364
  * Includes roles/permissions for client-side RBAC/PBAC.
2365
+ *
2366
+ * The token only verifies while its `tokenFamily` is a live session — see
2367
+ * verifyAccessToken. A token minted without one, or for a family that has
2368
+ * been revoked, is refused by design rather than trusted on its signature.
2369
+ * Use generateTokens() to establish a family.
2037
2370
  */
2038
2371
  async generateAccessToken(data) {
2039
2372
  return (await this.signAccessToken(data)).token;
@@ -2118,12 +2451,13 @@ var TokenService = class TokenService2 {
2118
2451
  * This prevents token theft in case of database breach
2119
2452
  */
2120
2453
  async storeRefreshToken(userId, refreshToken, tokenFamily) {
2121
- const expireInSecond = timestring2(this.config.jwt.refreshExpiresIn, "s");
2454
+ await this.assertRefreshFamilyAllowed(tokenFamily, userId);
2455
+ const expireInSecond = timestring3(this.config.jwt.refreshExpiresIn, "s");
2122
2456
  const hashedToken = this.hashToken(refreshToken);
2123
2457
  const existing = await this.tokenRepository.getByFamily(tokenFamily);
2124
2458
  const previousHash = existing?.token ?? null;
2125
2459
  const previousValidUntil = previousHash ? new Date(Date.now() + TokenService_1.PREVIOUS_GRACE_SECONDS * 1e3).toISOString() : null;
2126
- await this.tokenRepository.storeRefreshToken({
2460
+ const stored = await this.tokenRepository.storeRefreshToken({
2127
2461
  userId,
2128
2462
  token: hashedToken,
2129
2463
  tokenFamily,
@@ -2132,6 +2466,12 @@ var TokenService = class TokenService2 {
2132
2466
  previousValidUntil,
2133
2467
  previousUsedAt: null
2134
2468
  });
2469
+ if (!stored?.length) {
2470
+ this.rejectRefreshSession();
2471
+ }
2472
+ if (!await this.invalidation.markFamilyIssued(tokenFamily, userId)) {
2473
+ this.rejectRefreshSession();
2474
+ }
2135
2475
  }
2136
2476
  /**
2137
2477
  * Rotate only the family row observed by refreshTokens(). This conditional
@@ -2139,7 +2479,7 @@ var TokenService = class TokenService2 {
2139
2479
  */
2140
2480
  async rotateTokens(userId, tokenFamily, expectedCurrentHash) {
2141
2481
  const generated = await this.createTokenPair(userId, tokenFamily);
2142
- const expireInSecond = timestring2(this.config.jwt.refreshExpiresIn, "s");
2482
+ const expireInSecond = timestring3(this.config.jwt.refreshExpiresIn, "s");
2143
2483
  const rotated = await this.tokenRepository.rotateRefreshToken({
2144
2484
  userId,
2145
2485
  token: this.hashToken(generated.refreshToken),
@@ -2152,6 +2492,9 @@ var TokenService = class TokenService2 {
2152
2492
  if (!rotated?.length) {
2153
2493
  Err7(this.t("errors.refreshTokenInvalid"), 401);
2154
2494
  }
2495
+ if (!await this.invalidation.markFamilyIssued(tokenFamily, userId)) {
2496
+ this.rejectRefreshSession();
2497
+ }
2155
2498
  return generated;
2156
2499
  }
2157
2500
  /**
@@ -2161,6 +2504,7 @@ var TokenService = class TokenService2 {
2161
2504
  async refreshTokens() {
2162
2505
  const { refreshToken, userId, tokenFamily } = this.readRefreshSessionCookie();
2163
2506
  const stored = await this.tokenRepository.getByFamily(tokenFamily);
2507
+ await this.assertRefreshFamilyAllowed(tokenFamily, userId);
2164
2508
  if (!stored || stored.userId !== userId) {
2165
2509
  this.rejectRefreshSession();
2166
2510
  }
@@ -2196,16 +2540,21 @@ var TokenService = class TokenService2 {
2196
2540
  }
2197
2541
  /** Revoke every refresh session for a user (password change/reset, logout-all). */
2198
2542
  async revokeAllForUser(userId) {
2199
- return this.tokenRepository.revokeAllForUser(userId);
2543
+ const revoked = await this.tokenRepository.revokeAllForUser(userId);
2544
+ if (Array.isArray(revoked)) {
2545
+ await Promise.all(revoked.map((row) => row?.tokenFamily).filter((family) => typeof family === "string" && !!family).map((family) => this.invalidation.markFamilyRevoked(family)));
2546
+ }
2547
+ return revoked;
2200
2548
  }
2201
2549
  /** Revoke a single refresh session (one family). */
2202
2550
  async revokeFamily(tokenFamily) {
2203
- await this.markFamilyRevoked(tokenFamily);
2551
+ await this.invalidation.markFamilyRevoked(tokenFamily);
2204
2552
  return this.tokenRepository.revokeFamily(tokenFamily);
2205
2553
  }
2206
2554
  /**
2207
2555
  * Opportunistic cleanup of expired/abandoned sessions. With one row per
2208
- * family (no unique userId), abandoned logins would otherwise accumulate.
2556
+ * family (no unique userId), expired live rows and revocation tombstones
2557
+ * would otherwise accumulate.
2209
2558
  * Best-effort — never let cleanup failure break the calling flow.
2210
2559
  */
2211
2560
  async deleteExpiredSessions() {
@@ -2215,10 +2564,7 @@ var TokenService = class TokenService2 {
2215
2564
  }
2216
2565
  }
2217
2566
  async invalidateUserAccessTokens(userId) {
2218
- const nextVersion = await this.getUserSessionVersion(userId) + 1;
2219
- await this.cache.set(this.sessionVersionKey(userId), String(nextVersion), this.accessTokenTtlMs());
2220
- await this.cache.del(`auth:user:${userId}`);
2221
- return nextVersion;
2567
+ return this.invalidation.invalidateAccessTokens(userId);
2222
2568
  }
2223
2569
  async getUserFromCookie() {
2224
2570
  const userId = await this.resolveUserFromCookie();
@@ -2226,27 +2572,16 @@ var TokenService = class TokenService2 {
2226
2572
  if (!user) {
2227
2573
  Err7(this.t("errors.refreshTokenInvalid"), 401);
2228
2574
  }
2229
- return user;
2230
- }
2231
- get revokedFamilyPrefix() {
2232
- return "auth:revoked-family:";
2575
+ return this.requireActiveUser(user);
2233
2576
  }
2234
2577
  revokedFamilyKey(tokenFamily) {
2235
- return `${this.revokedFamilyPrefix}${tokenFamily}`;
2236
- }
2237
- /**
2238
- * Mark a family as revoked in cache for the access-token TTL, so every
2239
- * access token minted for that family (not just the presented one) is
2240
- * rejected by verifyAccessToken until it would have expired anyway.
2241
- */
2242
- async markFamilyRevoked(tokenFamily) {
2243
- await this.cache.set(this.revokedFamilyKey(tokenFamily), "1", this.accessTokenTtlMs());
2578
+ return this.invalidation.revokedFamilyKey(tokenFamily);
2244
2579
  }
2245
2580
  /**
2246
2581
  * Revoke only the suspect family — NOT the whole user. Bumping the global
2247
2582
  * per-user session version here would kill every device's access tokens on a
2248
- * single family's reuse detection. Instead drop the family's refresh row and
2249
- * mark the family revoked so its access tokens stop verifying.
2583
+ * single family's reuse detection. Instead durably mark the family revoked
2584
+ * so database recovery and its access tokens both stop verifying.
2250
2585
  */
2251
2586
  async revokeSuspectRefreshFamily(userId, tokenFamily) {
2252
2587
  if (tokenFamily) {
@@ -2258,7 +2593,7 @@ var TokenService = class TokenService2 {
2258
2593
  }
2259
2594
  /**
2260
2595
  * Logout the CURRENT session only — blacklist the presented access token,
2261
- * mark its family revoked, and delete that family's refresh row. Other
2596
+ * mark its family revoked in cache and durably in the token row. Other
2262
2597
  * devices/sessions for the same user keep working. Use a password change or
2263
2598
  * reset (revoke-all) to terminate every session.
2264
2599
  *
@@ -2339,7 +2674,7 @@ var TokenService = class TokenService2 {
2339
2674
  const token = jwt.sign(data, this.config.jwt.refreshSecret, {
2340
2675
  expiresIn
2341
2676
  });
2342
- await this.cache.set(`${this.resetTokenPrefix}${userId}`, jti, timestring2(expiresIn, "ms"));
2677
+ await this.cache.set(`${this.resetTokenPrefix}${userId}`, jti, timestring3(expiresIn, "ms"));
2343
2678
  return { token, userId };
2344
2679
  }
2345
2680
  /**
@@ -2358,8 +2693,20 @@ var TokenService = class TokenService2 {
2358
2693
  return this.generateSetPasswordToken(userId, "invite", "3d");
2359
2694
  }
2360
2695
  /**
2361
- * Verify password reset token
2362
- * Returns userId if valid, throws error if expired/invalid
2696
+ * Verify and CONSUME a password reset or invite token.
2697
+ *
2698
+ * Consumption is a single atomic compare-and-delete, so exactly one of any
2699
+ * number of concurrent callers holding the same link is told to proceed. The
2700
+ * earlier `get()` then `del()` pair left a window in which two callers both
2701
+ * read the same jti, both passed, and both went on to set a password.
2702
+ *
2703
+ * The comparison also means a stale token cannot delete the jti of a newer
2704
+ * one that superseded it — the newer link keeps working.
2705
+ *
2706
+ * Callers must finish validating the replacement password BEFORE calling
2707
+ * this: consumption is deliberately irreversible, so a token burned by a
2708
+ * request that then failed validation would cost the user their link for
2709
+ * nothing.
2363
2710
  */
2364
2711
  async verifyResetToken(token) {
2365
2712
  let decoded;
@@ -2371,40 +2718,42 @@ var TokenService = class TokenService2 {
2371
2718
  if (decoded.type !== "reset" && decoded.type !== "invite" || !decoded.jti) {
2372
2719
  Err7(this.t("errors.invalidResetToken"));
2373
2720
  }
2721
+ const consume = this.cache.compareAndDelete;
2722
+ if (typeof consume !== "function") {
2723
+ Err7.invalidOperation("Password reset requires a cache with atomic compare-and-delete");
2724
+ }
2374
2725
  const key = `${this.resetTokenPrefix}${decoded.userId}`;
2375
- const storedJti = await this.cache.get(key);
2376
- if (!storedJti || storedJti !== decoded.jti) {
2726
+ if (!await consume.call(this.cache, key, decoded.jti)) {
2377
2727
  Err7(this.t("errors.invalidResetToken"));
2378
2728
  }
2379
- await this.cache.del(key);
2380
2729
  return decoded.userId;
2381
2730
  }
2382
2731
  async getUserSessionVersion(userId) {
2383
- return this.parseSessionVersion(await this.cache.get(this.sessionVersionKey(userId)));
2732
+ return this.invalidation.getSessionVersion(userId);
2384
2733
  }
2385
2734
  };
2386
- __decorate11([
2387
- Inject8(AUTH_CONFIG),
2388
- __metadata11("design:type", Object)
2735
+ __decorate12([
2736
+ Inject9(AUTH_CONFIG),
2737
+ __metadata12("design:type", Object)
2389
2738
  ], TokenService.prototype, "config", void 0);
2390
- __decorate11([
2739
+ __decorate12([
2391
2740
  I18n5("auth"),
2392
- __metadata11("design:type", Object)
2741
+ __metadata12("design:type", Object)
2393
2742
  ], TokenService.prototype, "t", void 0);
2394
- TokenService = TokenService_1 = __decorate11([
2395
- Injectable6(),
2396
- __metadata11("design:paramtypes", [typeof (_a6 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _a6 : Object, typeof (_b4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _b4 : Object, typeof (_c2 = typeof CacheService !== "undefined" && CacheService) === "function" ? _c2 : Object, typeof (_d2 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _d2 : Object])
2743
+ TokenService = TokenService_1 = __decorate12([
2744
+ Injectable7(),
2745
+ __metadata12("design:paramtypes", [typeof (_a7 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _a7 : Object, typeof (_b5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _b5 : Object, typeof (_c2 = typeof CacheService2 !== "undefined" && CacheService2) === "function" ? _c2 : Object, typeof (_d2 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _d2 : Object, typeof (_e2 = typeof SessionInvalidationService !== "undefined" && SessionInvalidationService) === "function" ? _e2 : Object])
2397
2746
  ], TokenService);
2398
2747
 
2399
2748
  // src/auth/AuthService.ts
2400
- import timestring3 from "timestring";
2749
+ import timestring4 from "timestring";
2401
2750
 
2402
2751
  // src/auth/AuthSessionService.ts
2403
- import { Injectable as Injectable8 } from "najm-core";
2752
+ import { Injectable as Injectable9 } from "najm-core";
2404
2753
  import { Err as Err9 } from "najm-core";
2405
2754
 
2406
2755
  // src/credentialSetup/CredentialSetupRequirementService.ts
2407
- import { Injectable as Injectable7 } from "najm-core";
2756
+ import { Injectable as Injectable8 } from "najm-core";
2408
2757
  import { Transaction as Transaction2 } from "najm-database";
2409
2758
 
2410
2759
  // src/identity/temporaryCredential.ts
@@ -2476,17 +2825,17 @@ function normalizeSetupPurpose(purpose) {
2476
2825
  __name(normalizeSetupPurpose, "normalizeSetupPurpose");
2477
2826
 
2478
2827
  // src/credentialSetup/CredentialSetupRequirementService.ts
2479
- var __decorate12 = function(decorators, target, key, desc) {
2828
+ var __decorate13 = function(decorators, target, key, desc) {
2480
2829
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2481
2830
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2482
2831
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2483
2832
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2484
2833
  };
2485
- var __metadata12 = function(k, v) {
2834
+ var __metadata13 = function(k, v) {
2486
2835
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2487
2836
  };
2488
- var _a7;
2489
- var _b5;
2837
+ var _a8;
2838
+ var _b6;
2490
2839
  var _c3;
2491
2840
  var CredentialSetupRequirementService = class CredentialSetupRequirementService2 {
2492
2841
  static {
@@ -2526,15 +2875,15 @@ var CredentialSetupRequirementService = class CredentialSetupRequirementService2
2526
2875
  return this.repository.complete(userId, normalizeSetupPurpose(purpose));
2527
2876
  }
2528
2877
  };
2529
- __decorate12([
2878
+ __decorate13([
2530
2879
  Transaction2({ retries: 2 }),
2531
- __metadata12("design:type", Function),
2532
- __metadata12("design:paramtypes", [String, String, Object]),
2533
- __metadata12("design:returntype", typeof (_c3 = typeof Promise !== "undefined" && Promise) === "function" ? _c3 : Object)
2880
+ __metadata13("design:type", Function),
2881
+ __metadata13("design:paramtypes", [String, String, Object]),
2882
+ __metadata13("design:returntype", typeof (_c3 = typeof Promise !== "undefined" && Promise) === "function" ? _c3 : Object)
2534
2883
  ], CredentialSetupRequirementService.prototype, "markRequired", null);
2535
- CredentialSetupRequirementService = __decorate12([
2536
- Injectable7(),
2537
- __metadata12("design:paramtypes", [typeof (_a7 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _a7 : Object, typeof (_b5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b5 : Object])
2884
+ CredentialSetupRequirementService = __decorate13([
2885
+ Injectable8(),
2886
+ __metadata13("design:paramtypes", [typeof (_a8 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _a8 : Object, typeof (_b6 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b6 : Object])
2538
2887
  ], CredentialSetupRequirementService);
2539
2888
 
2540
2889
  // src/credentialSetup/errors.ts
@@ -2560,17 +2909,17 @@ var credentialSetupError = /* @__PURE__ */ __name((code, message, status = 400)
2560
2909
  }, "credentialSetupError");
2561
2910
 
2562
2911
  // src/auth/AuthSessionService.ts
2563
- var __decorate13 = function(decorators, target, key, desc) {
2912
+ var __decorate14 = function(decorators, target, key, desc) {
2564
2913
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2565
2914
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2566
2915
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2567
2916
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2568
2917
  };
2569
- var __metadata13 = function(k, v) {
2918
+ var __metadata14 = function(k, v) {
2570
2919
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2571
2920
  };
2572
- var _a8;
2573
- var _b6;
2921
+ var _a9;
2922
+ var _b7;
2574
2923
  var _c4;
2575
2924
  var _d3;
2576
2925
  var AuthSessionService = class AuthSessionService2 {
@@ -2598,7 +2947,7 @@ var AuthSessionService = class AuthSessionService2 {
2598
2947
  const generated = await this.tokenService.generateTokens(user.id);
2599
2948
  this.cookieManager.setRefreshToken(generated.refreshToken);
2600
2949
  await this.userService.updateLastLogin(user.id);
2601
- const { roles, permissions, sessionVersion } = generated;
2950
+ const { roles, permissions, sessionVersion, tokenFamily } = generated;
2602
2951
  this.cookieManager.setSessionCookie({
2603
2952
  user: {
2604
2953
  id: user.id,
@@ -2609,39 +2958,40 @@ var AuthSessionService = class AuthSessionService2 {
2609
2958
  },
2610
2959
  roles,
2611
2960
  permissions,
2612
- sessionVersion
2961
+ sessionVersion,
2962
+ tokenFamily
2613
2963
  });
2614
2964
  const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sessionVersion, ...tokens } = generated;
2615
2965
  return { ...tokens, user };
2616
2966
  }
2617
2967
  };
2618
- AuthSessionService = __decorate13([
2619
- Injectable8(),
2620
- __metadata13("design:paramtypes", [typeof (_a8 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a8 : Object, typeof (_b6 = typeof UserService !== "undefined" && UserService) === "function" ? _b6 : Object, typeof (_c4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c4 : Object, typeof (_d3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _d3 : Object])
2968
+ AuthSessionService = __decorate14([
2969
+ Injectable9(),
2970
+ __metadata14("design:paramtypes", [typeof (_a9 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a9 : Object, typeof (_b7 = typeof UserService !== "undefined" && UserService) === "function" ? _b7 : Object, typeof (_c4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c4 : Object, typeof (_d3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _d3 : Object])
2621
2971
  ], AuthSessionService);
2622
2972
 
2623
2973
  // src/credentialSetup/PasswordSetupService.ts
2624
- import { Inject as Inject10, Injectable as Injectable10 } from "najm-core";
2974
+ import { Inject as Inject11, Injectable as Injectable11 } from "najm-core";
2625
2975
  import { I18n as I18n7 } from "najm-i18n";
2626
2976
 
2627
2977
  // src/credentialSetup/CredentialSetupService.ts
2628
2978
  import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
2629
2979
  import { CookieService as CookieService2 } from "najm-cookies";
2630
- import { Err as Err11, Injectable as Injectable9 } from "najm-core";
2980
+ import { Err as Err11, Injectable as Injectable10 } from "najm-core";
2631
2981
  import { Transaction as Transaction3 } from "najm-database";
2632
2982
  import { I18n as I18n6 } from "najm-i18n";
2633
2983
 
2634
2984
  // src/credentialSetup/CredentialSetupRepository.ts
2635
2985
  import { and as and3, eq as eq6, gt, isNull as isNull2, lt as lt2 } from "drizzle-orm";
2636
- import { Err as Err10, Inject as Inject9, Repository as Repository5 } from "najm-core";
2986
+ import { Err as Err10, Inject as Inject10, Repository as Repository5 } from "najm-core";
2637
2987
  import { DB as DB5 } from "najm-database";
2638
- var __decorate14 = function(decorators, target, key, desc) {
2988
+ var __decorate15 = function(decorators, target, key, desc) {
2639
2989
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2640
2990
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2641
2991
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2642
2992
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2643
2993
  };
2644
- var __metadata14 = function(k, v) {
2994
+ var __metadata15 = function(k, v) {
2645
2995
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2646
2996
  };
2647
2997
  var CredentialSetupRepository = class CredentialSetupRepository2 {
@@ -2693,33 +3043,33 @@ var CredentialSetupRepository = class CredentialSetupRepository2 {
2693
3043
  return this.db.delete(this.sessions).where(lt2(this.sessions.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning({ userId: this.sessions.userId });
2694
3044
  }
2695
3045
  };
2696
- __decorate14([
3046
+ __decorate15([
2697
3047
  DB5(),
2698
- __metadata14("design:type", Object)
3048
+ __metadata15("design:type", Object)
2699
3049
  ], CredentialSetupRepository.prototype, "db", void 0);
2700
- __decorate14([
2701
- Inject9(AUTH_SCHEMA),
2702
- __metadata14("design:type", Object)
3050
+ __decorate15([
3051
+ Inject10(AUTH_SCHEMA),
3052
+ __metadata15("design:type", Object)
2703
3053
  ], CredentialSetupRepository.prototype, "schema", void 0);
2704
- CredentialSetupRepository = __decorate14([
3054
+ CredentialSetupRepository = __decorate15([
2705
3055
  Repository5()
2706
3056
  ], CredentialSetupRepository);
2707
3057
 
2708
3058
  // src/credentialSetup/CredentialSetupService.ts
2709
- var __decorate15 = function(decorators, target, key, desc) {
3059
+ var __decorate16 = function(decorators, target, key, desc) {
2710
3060
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2711
3061
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2712
3062
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2713
3063
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2714
3064
  };
2715
- var __metadata15 = function(k, v) {
3065
+ var __metadata16 = function(k, v) {
2716
3066
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2717
3067
  };
2718
- var _a9;
2719
- var _b7;
3068
+ var _a10;
3069
+ var _b8;
2720
3070
  var _c5;
2721
3071
  var _d4;
2722
- var _e2;
3072
+ var _e3;
2723
3073
  var _f2;
2724
3074
  var _g2;
2725
3075
  var DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME = "najm.credential-setup";
@@ -2855,48 +3205,48 @@ var CredentialSetupService = class CredentialSetupService2 {
2855
3205
  });
2856
3206
  }
2857
3207
  };
2858
- __decorate15([
3208
+ __decorate16([
2859
3209
  I18n6("auth"),
2860
- __metadata15("design:type", Object)
3210
+ __metadata16("design:type", Object)
2861
3211
  ], CredentialSetupService.prototype, "t", void 0);
2862
- __decorate15([
3212
+ __decorate16([
2863
3213
  Transaction3({ retries: 2 }),
2864
- __metadata15("design:type", Function),
2865
- __metadata15("design:paramtypes", [String, Object]),
2866
- __metadata15("design:returntype", typeof (_e2 = typeof Promise !== "undefined" && Promise) === "function" ? _e2 : Object)
3214
+ __metadata16("design:type", Function),
3215
+ __metadata16("design:paramtypes", [String, Object]),
3216
+ __metadata16("design:returntype", typeof (_e3 = typeof Promise !== "undefined" && Promise) === "function" ? _e3 : Object)
2867
3217
  ], CredentialSetupService.prototype, "begin", null);
2868
- __decorate15([
3218
+ __decorate16([
2869
3219
  Transaction3({ retries: 2 }),
2870
- __metadata15("design:type", Function),
2871
- __metadata15("design:paramtypes", [Object, Function]),
2872
- __metadata15("design:returntype", typeof (_f2 = typeof Promise !== "undefined" && Promise) === "function" ? _f2 : Object)
3220
+ __metadata16("design:type", Function),
3221
+ __metadata16("design:paramtypes", [Object, Function]),
3222
+ __metadata16("design:returntype", typeof (_f2 = typeof Promise !== "undefined" && Promise) === "function" ? _f2 : Object)
2873
3223
  ], CredentialSetupService.prototype, "consume", null);
2874
- __decorate15([
3224
+ __decorate16([
2875
3225
  Transaction3({ retries: 2 }),
2876
- __metadata15("design:type", Function),
2877
- __metadata15("design:paramtypes", [Object]),
2878
- __metadata15("design:returntype", typeof (_g2 = typeof Promise !== "undefined" && Promise) === "function" ? _g2 : Object)
3226
+ __metadata16("design:type", Function),
3227
+ __metadata16("design:paramtypes", [Object]),
3228
+ __metadata16("design:returntype", typeof (_g2 = typeof Promise !== "undefined" && Promise) === "function" ? _g2 : Object)
2879
3229
  ], CredentialSetupService.prototype, "cancel", null);
2880
- CredentialSetupService = __decorate15([
2881
- Injectable9(),
2882
- __metadata15("design:paramtypes", [typeof (_a9 = typeof CredentialSetupRepository !== "undefined" && CredentialSetupRepository) === "function" ? _a9 : Object, typeof (_b7 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b7 : Object, typeof (_c5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c5 : Object, typeof (_d4 = typeof CookieService2 !== "undefined" && CookieService2) === "function" ? _d4 : Object])
3230
+ CredentialSetupService = __decorate16([
3231
+ Injectable10(),
3232
+ __metadata16("design:paramtypes", [typeof (_a10 = typeof CredentialSetupRepository !== "undefined" && CredentialSetupRepository) === "function" ? _a10 : Object, typeof (_b8 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b8 : Object, typeof (_c5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c5 : Object, typeof (_d4 = typeof CookieService2 !== "undefined" && CookieService2) === "function" ? _d4 : Object])
2883
3233
  ], CredentialSetupService);
2884
3234
 
2885
3235
  // src/credentialSetup/PasswordSetupService.ts
2886
- var __decorate16 = function(decorators, target, key, desc) {
3236
+ var __decorate17 = function(decorators, target, key, desc) {
2887
3237
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2888
3238
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2889
3239
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2890
3240
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2891
3241
  };
2892
- var __metadata16 = function(k, v) {
3242
+ var __metadata17 = function(k, v) {
2893
3243
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2894
3244
  };
2895
- var _a10;
2896
- var _b8;
3245
+ var _a11;
3246
+ var _b9;
2897
3247
  var _c6;
2898
3248
  var _d5;
2899
- var _e3;
3249
+ var _e4;
2900
3250
  var _f3;
2901
3251
  var PasswordSetupService = class PasswordSetupService2 {
2902
3252
  static {
@@ -3013,38 +3363,38 @@ var PasswordSetupService = class PasswordSetupService2 {
3013
3363
  return this.validator.comparePassword(normalized, storedHash);
3014
3364
  }
3015
3365
  };
3016
- __decorate16([
3017
- Inject10(AUTH_CONFIG),
3018
- __metadata16("design:type", Object)
3366
+ __decorate17([
3367
+ Inject11(AUTH_CONFIG),
3368
+ __metadata17("design:type", Object)
3019
3369
  ], PasswordSetupService.prototype, "config", void 0);
3020
- __decorate16([
3370
+ __decorate17([
3021
3371
  I18n7("auth"),
3022
- __metadata16("design:type", Object)
3372
+ __metadata17("design:type", Object)
3023
3373
  ], PasswordSetupService.prototype, "t", void 0);
3024
- PasswordSetupService = __decorate16([
3025
- Injectable10(),
3026
- __metadata16("design:paramtypes", [typeof (_a10 = typeof CredentialSetupService !== "undefined" && CredentialSetupService) === "function" ? _a10 : Object, typeof (_b8 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _b8 : Object, typeof (_c6 = typeof UserService !== "undefined" && UserService) === "function" ? _c6 : Object, typeof (_d5 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _d5 : Object, typeof (_e3 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _e3 : Object, typeof (_f3 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _f3 : Object])
3374
+ PasswordSetupService = __decorate17([
3375
+ Injectable11(),
3376
+ __metadata17("design:paramtypes", [typeof (_a11 = typeof CredentialSetupService !== "undefined" && CredentialSetupService) === "function" ? _a11 : Object, typeof (_b9 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _b9 : Object, typeof (_c6 = typeof UserService !== "undefined" && UserService) === "function" ? _c6 : Object, typeof (_d5 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _d5 : Object, typeof (_e4 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _e4 : Object, typeof (_f3 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _f3 : Object])
3027
3377
  ], PasswordSetupService);
3028
3378
 
3029
3379
  // src/auth/AuthService.ts
3030
- var __decorate17 = function(decorators, target, key, desc) {
3380
+ var __decorate18 = function(decorators, target, key, desc) {
3031
3381
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3032
3382
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3033
3383
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3034
3384
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3035
3385
  };
3036
- var __metadata17 = function(k, v) {
3386
+ var __metadata18 = function(k, v) {
3037
3387
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3038
3388
  };
3039
- var _a11;
3040
- var _b9;
3389
+ var _a12;
3390
+ var _b10;
3041
3391
  var _c7;
3042
3392
  var _d6;
3043
- var _e4;
3393
+ var _e5;
3044
3394
  var _f4;
3045
3395
  var _g3;
3046
3396
  var _h2;
3047
- var _j;
3397
+ var _j2;
3048
3398
  var _k;
3049
3399
  var _l;
3050
3400
  var AuthService = class AuthService2 {
@@ -3083,7 +3433,7 @@ var AuthService = class AuthService2 {
3083
3433
  return new Date(lockoutUntil).getTime() > Date.now();
3084
3434
  }
3085
3435
  nextLockoutUntil() {
3086
- const durationMs = timestring3(this.config.lockout.duration, "ms");
3436
+ const durationMs = timestring4(this.config.lockout.duration, "ms");
3087
3437
  return new Date(Date.now() + durationMs).toISOString();
3088
3438
  }
3089
3439
  getDummyHash() {
@@ -3333,7 +3683,8 @@ var AuthService = class AuthService2 {
3333
3683
  user: { id: user.id, email: user.email, name: user.name, role: user.role, status: user.status ?? void 0 },
3334
3684
  roles: generated.roles,
3335
3685
  permissions: generated.permissions,
3336
- sessionVersion: generated.sessionVersion
3686
+ sessionVersion: generated.sessionVersion,
3687
+ tokenFamily: generated.tokenFamily
3337
3688
  });
3338
3689
  }
3339
3690
  const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sv, ...tokens } = generated;
@@ -3356,7 +3707,8 @@ var AuthService = class AuthService2 {
3356
3707
  },
3357
3708
  roles: recovered.roles,
3358
3709
  permissions: recovered.permissions,
3359
- sessionVersion: recovered.sessionVersion
3710
+ sessionVersion: recovered.sessionVersion,
3711
+ tokenFamily: recovered.tokenFamily
3360
3712
  });
3361
3713
  return { recovered: true };
3362
3714
  }
@@ -3408,7 +3760,12 @@ var AuthService = class AuthService2 {
3408
3760
  const lang = this.i18nService.getCurrentLanguage();
3409
3761
  result = { ...user, language: lang };
3410
3762
  const token = this.tokenService.decodeAccessToken(authorization.replace(/^Bearer\s+/i, ""));
3411
- cachePayload = { roles: token?.roles ?? [], permissions: token?.permissions ?? [], sessionVersion: token?.sessionVersion ?? 0 };
3763
+ cachePayload = token?.tokenFamily ? {
3764
+ roles: token.roles ?? [],
3765
+ permissions: token.permissions ?? [],
3766
+ sessionVersion: token.sessionVersion ?? 0,
3767
+ tokenFamily: token.tokenFamily
3768
+ } : null;
3412
3769
  } else {
3413
3770
  result = await this.getUserFromCookie();
3414
3771
  }
@@ -3420,7 +3777,8 @@ var AuthService = class AuthService2 {
3420
3777
  user: { id: result.id, email: result.email, name: result.name, role: result.role, status: result.status ?? void 0 },
3421
3778
  roles: cachePayload.roles,
3422
3779
  permissions: cachePayload.permissions,
3423
- sessionVersion: cachePayload.sessionVersion
3780
+ sessionVersion: cachePayload.sessionVersion,
3781
+ tokenFamily: cachePayload.tokenFamily
3424
3782
  });
3425
3783
  }
3426
3784
  return result;
@@ -3459,8 +3817,8 @@ var AuthService = class AuthService2 {
3459
3817
  return { message: this.t("success.passwordChanged") };
3460
3818
  }
3461
3819
  async resetPassword(token, newPassword) {
3462
- const userId = await this.tokenService.verifyResetToken(token);
3463
3820
  this.userValidator.validatePasswordStrength(newPassword);
3821
+ const userId = await this.tokenService.verifyResetToken(token);
3464
3822
  await this.userService.update(userId, { password: newPassword });
3465
3823
  await this.tokenService.invalidateUserAccessTokens(userId);
3466
3824
  await this.tokenService.revokeAllForUser(userId);
@@ -3469,39 +3827,39 @@ var AuthService = class AuthService2 {
3469
3827
  return { message: this.t("success.passwordReset") };
3470
3828
  }
3471
3829
  };
3472
- __decorate17([
3473
- Inject11(AUTH_CONFIG),
3474
- __metadata17("design:type", Object)
3830
+ __decorate18([
3831
+ Inject12(AUTH_CONFIG),
3832
+ __metadata18("design:type", Object)
3475
3833
  ], AuthService.prototype, "config", void 0);
3476
- __decorate17([
3834
+ __decorate18([
3477
3835
  I18n8("auth"),
3478
- __metadata17("design:type", Object)
3836
+ __metadata18("design:type", Object)
3479
3837
  ], AuthService.prototype, "t", void 0);
3480
- __decorate17([
3838
+ __decorate18([
3481
3839
  Log(),
3482
- __metadata17("design:type", Object)
3840
+ __metadata18("design:type", Object)
3483
3841
  ], AuthService.prototype, "logger", void 0);
3484
- __decorate17([
3842
+ __decorate18([
3485
3843
  Transaction4(),
3486
- __metadata17("design:type", Function),
3487
- __metadata17("design:paramtypes", [Object]),
3488
- __metadata17("design:returntype", typeof (_l = typeof Promise !== "undefined" && Promise) === "function" ? _l : Object)
3844
+ __metadata18("design:type", Function),
3845
+ __metadata18("design:paramtypes", [Object]),
3846
+ __metadata18("design:returntype", typeof (_l = typeof Promise !== "undefined" && Promise) === "function" ? _l : Object)
3489
3847
  ], AuthService.prototype, "provisionWithCredentialSetup", null);
3490
- AuthService = __decorate17([
3491
- Injectable11(),
3492
- __metadata17("design:paramtypes", [typeof (_a11 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a11 : Object, typeof (_b9 = typeof UserService !== "undefined" && UserService) === "function" ? _b9 : Object, typeof (_c7 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _c7 : Object, typeof (_d6 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _d6 : Object, typeof (_e4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _e4 : Object, typeof (_f4 = typeof I18nService2 !== "undefined" && I18nService2) === "function" ? _f4 : Object, typeof (_g3 = typeof EmailService !== "undefined" && EmailService) === "function" ? _g3 : Object, typeof (_h2 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _h2 : Object, typeof (_j = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _j : Object, typeof (_k = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _k : Object])
3848
+ AuthService = __decorate18([
3849
+ Injectable12(),
3850
+ __metadata18("design:paramtypes", [typeof (_a12 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a12 : Object, typeof (_b10 = typeof UserService !== "undefined" && UserService) === "function" ? _b10 : Object, typeof (_c7 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _c7 : Object, typeof (_d6 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _d6 : Object, typeof (_e5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _e5 : Object, typeof (_f4 = typeof I18nService2 !== "undefined" && I18nService2) === "function" ? _f4 : Object, typeof (_g3 = typeof EmailService !== "undefined" && EmailService) === "function" ? _g3 : Object, typeof (_h2 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _h2 : Object, typeof (_j2 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _j2 : Object, typeof (_k = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _k : Object])
3493
3851
  ], AuthService);
3494
3852
 
3495
3853
  // src/auth/AuthGuard.ts
3496
3854
  import { Service as Service2, User } from "najm-core";
3497
3855
  import { createGuard } from "najm-guard";
3498
- var __decorate18 = function(decorators, target, key, desc) {
3856
+ var __decorate19 = function(decorators, target, key, desc) {
3499
3857
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3500
3858
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3501
3859
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3502
3860
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3503
3861
  };
3504
- var __metadata18 = function(k, v) {
3862
+ var __metadata19 = function(k, v) {
3505
3863
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3506
3864
  };
3507
3865
  var __param3 = function(paramIndex, decorator) {
@@ -3513,17 +3871,27 @@ var AuthGuard = class AuthGuard2 {
3513
3871
  static {
3514
3872
  __name(this, "AuthGuard");
3515
3873
  }
3874
+ /**
3875
+ * A resolved principal is not automatically an authorized one.
3876
+ *
3877
+ * The resolvers ahead of this guard already reject deactivated accounts, so
3878
+ * this is the backstop for anything that publishes a principal by another
3879
+ * route: a truthy user record must still be an active one to pass. Records
3880
+ * whose projection omits `status` are unchanged.
3881
+ */
3516
3882
  canActivate(user) {
3517
- return !!user;
3883
+ if (!user)
3884
+ return false;
3885
+ return user.status === void 0 || user.status === "active";
3518
3886
  }
3519
3887
  };
3520
- __decorate18([
3888
+ __decorate19([
3521
3889
  __param3(0, User()),
3522
- __metadata18("design:type", Function),
3523
- __metadata18("design:paramtypes", [Object]),
3524
- __metadata18("design:returntype", Boolean)
3890
+ __metadata19("design:type", Function),
3891
+ __metadata19("design:paramtypes", [Object]),
3892
+ __metadata19("design:returntype", Boolean)
3525
3893
  ], AuthGuard.prototype, "canActivate", null);
3526
- AuthGuard = __decorate18([
3894
+ AuthGuard = __decorate19([
3527
3895
  Service2()
3528
3896
  ], AuthGuard);
3529
3897
  var isAuth = createGuard(AuthGuard);
@@ -3532,13 +3900,13 @@ var isAuth = createGuard(AuthGuard);
3532
3900
  import { Service as Service3 } from "najm-core";
3533
3901
  import { GuardParams, Role as RequestRole } from "najm-core";
3534
3902
  import { composeGuards, createGuard as createGuard2 } from "najm-guard";
3535
- var __decorate19 = function(decorators, target, key, desc) {
3903
+ var __decorate20 = function(decorators, target, key, desc) {
3536
3904
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3537
3905
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3538
3906
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3539
3907
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3540
3908
  };
3541
- var __metadata19 = function(k, v) {
3909
+ var __metadata20 = function(k, v) {
3542
3910
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3543
3911
  };
3544
3912
  var __param4 = function(paramIndex, decorator) {
@@ -3561,14 +3929,14 @@ var RoleGuard = class RoleGuard2 {
3561
3929
  return false;
3562
3930
  }
3563
3931
  };
3564
- __decorate19([
3932
+ __decorate20([
3565
3933
  __param4(0, GuardParams()),
3566
3934
  __param4(1, RequestRole()),
3567
- __metadata19("design:type", Function),
3568
- __metadata19("design:paramtypes", [Object, String]),
3569
- __metadata19("design:returntype", void 0)
3935
+ __metadata20("design:type", Function),
3936
+ __metadata20("design:paramtypes", [Object, String]),
3937
+ __metadata20("design:returntype", void 0)
3570
3938
  ], RoleGuard.prototype, "canActivate", null);
3571
- RoleGuard = __decorate19([
3939
+ RoleGuard = __decorate20([
3572
3940
  Service3()
3573
3941
  ], RoleGuard);
3574
3942
  var Role = createGuard2(RoleGuard);
@@ -3739,13 +4107,13 @@ var userListQuery = z.object({
3739
4107
  });
3740
4108
 
3741
4109
  // src/auth/AuthController.ts
3742
- var __decorate20 = function(decorators, target, key, desc) {
4110
+ var __decorate21 = function(decorators, target, key, desc) {
3743
4111
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3744
4112
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3745
4113
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3746
4114
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3747
4115
  };
3748
- var __metadata20 = function(k, v) {
4116
+ var __metadata21 = function(k, v) {
3749
4117
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3750
4118
  };
3751
4119
  var __param5 = function(paramIndex, decorator) {
@@ -3753,18 +4121,28 @@ var __param5 = function(paramIndex, decorator) {
3753
4121
  decorator(target, key, paramIndex);
3754
4122
  };
3755
4123
  };
3756
- var _a12;
4124
+ var _a13;
3757
4125
  var hashKeyPart = /* @__PURE__ */ __name((value) => createHash3("sha256").update(value).digest("base64url").slice(0, 32), "hashKeyPart");
3758
4126
  var cookieFingerprint = /* @__PURE__ */ __name(() => (ctx, { clientIp }) => {
3759
4127
  const cookie = ctx.req.raw.headers.get("cookie") ?? "";
3760
4128
  const fingerprint = cookie ? hashKeyPart(cookie) : "none";
3761
4129
  return `${clientIp}:${fingerprint}`;
3762
4130
  }, "cookieFingerprint");
3763
- var authIdentityRateLimitKey = /* @__PURE__ */ __name(async (ctx, keyContext) => {
4131
+ var readDeclaredIdentity = /* @__PURE__ */ __name((body, fields) => {
4132
+ if (typeof body !== "object" || body === null || Array.isArray(body))
4133
+ return void 0;
4134
+ for (const field of fields) {
4135
+ const value = body[field];
4136
+ if (typeof value === "string" && value.trim())
4137
+ return value;
4138
+ }
4139
+ return void 0;
4140
+ }, "readDeclaredIdentity");
4141
+ var identityRateLimitKey = /* @__PURE__ */ __name((fields) => async (ctx, keyContext) => {
3764
4142
  const ip = keyContext?.clientIp ?? UNRESOLVED_CLIENT_ADDRESS;
3765
4143
  try {
3766
4144
  const body = await ctx.req.json();
3767
- const identity = body?.identifier ?? body?.email;
4145
+ const identity = readDeclaredIdentity(body, fields);
3768
4146
  const normalizedIdentity = getRequestIdentityResolver(ctx)(identity);
3769
4147
  if (normalizedIdentity) {
3770
4148
  return `${ip}:${hashKeyPart(normalizedIdentity)}`;
@@ -3772,7 +4150,9 @@ var authIdentityRateLimitKey = /* @__PURE__ */ __name(async (ctx, keyContext) =>
3772
4150
  } catch {
3773
4151
  }
3774
4152
  return ip;
3775
- }, "authIdentityRateLimitKey");
4153
+ }, "identityRateLimitKey");
4154
+ var authIdentityRateLimitKey = identityRateLimitKey(["identifier", "email"]);
4155
+ var authEmailRateLimitKey = identityRateLimitKey(["email"]);
3776
4156
  var loginRateLimit = resolveAuthLoginRateLimitConfig();
3777
4157
  var AuthController = class AuthController2 {
3778
4158
  static {
@@ -3815,7 +4195,7 @@ var AuthController = class AuthController2 {
3815
4195
  return this.authService.resetPassword(body.token, body.newPassword);
3816
4196
  }
3817
4197
  };
3818
- __decorate20([
4198
+ __decorate21([
3819
4199
  Post("/login"),
3820
4200
  RateLimit({
3821
4201
  limit: loginRateLimit.limit,
@@ -3827,105 +4207,105 @@ __decorate20([
3827
4207
  Validate(loginDto),
3828
4208
  ResMsg("auth.success.login"),
3829
4209
  __param5(0, Body()),
3830
- __metadata20("design:type", Function),
3831
- __metadata20("design:paramtypes", [Object]),
3832
- __metadata20("design:returntype", Promise)
4210
+ __metadata21("design:type", Function),
4211
+ __metadata21("design:paramtypes", [Object]),
4212
+ __metadata21("design:returntype", Promise)
3833
4213
  ], AuthController.prototype, "loginUser", null);
3834
- __decorate20([
4214
+ __decorate21([
3835
4215
  Post("/invite"),
3836
4216
  isAdmin(),
3837
4217
  RateLimit({ limit: 20, window: "15m", key: "user" }),
3838
4218
  Validate(inviteUserDto),
3839
4219
  ResMsg("auth.success.accountInviteSent"),
3840
4220
  __param5(0, Body()),
3841
- __metadata20("design:type", Function),
3842
- __metadata20("design:paramtypes", [Object]),
3843
- __metadata20("design:returntype", Promise)
4221
+ __metadata21("design:type", Function),
4222
+ __metadata21("design:paramtypes", [Object]),
4223
+ __metadata21("design:returntype", Promise)
3844
4224
  ], AuthController.prototype, "inviteUser", null);
3845
- __decorate20([
4225
+ __decorate21([
3846
4226
  Post("/refresh"),
3847
4227
  RateLimit({ limit: 15, window: "15m", key: cookieFingerprint() }),
3848
4228
  ResMsg("auth.success.tokenRefreshed"),
3849
- __metadata20("design:type", Function),
3850
- __metadata20("design:paramtypes", []),
3851
- __metadata20("design:returntype", Promise)
4229
+ __metadata21("design:type", Function),
4230
+ __metadata21("design:paramtypes", []),
4231
+ __metadata21("design:returntype", Promise)
3852
4232
  ], AuthController.prototype, "refreshTokens", null);
3853
- __decorate20([
4233
+ __decorate21([
3854
4234
  Post("/session/recover"),
3855
4235
  RateLimit({ limit: 120, window: "1m", key: cookieFingerprint() }),
3856
4236
  ResMsg("auth.success.sessionRecovered"),
3857
4237
  __param5(0, Headers("x-najm-session-recovery")),
3858
4238
  __param5(1, Ctx()),
3859
- __metadata20("design:type", Function),
3860
- __metadata20("design:paramtypes", [String, Object]),
3861
- __metadata20("design:returntype", Promise)
4239
+ __metadata21("design:type", Function),
4240
+ __metadata21("design:paramtypes", [String, Object]),
4241
+ __metadata21("design:returntype", Promise)
3862
4242
  ], AuthController.prototype, "recoverSession", null);
3863
- __decorate20([
4243
+ __decorate21([
3864
4244
  Post("/logout"),
3865
4245
  __param5(0, User2("id")),
3866
4246
  __param5(1, Headers("authorization")),
3867
- __metadata20("design:type", Function),
3868
- __metadata20("design:paramtypes", [String, String]),
3869
- __metadata20("design:returntype", Promise)
4247
+ __metadata21("design:type", Function),
4248
+ __metadata21("design:paramtypes", [String, String]),
4249
+ __metadata21("design:returntype", Promise)
3870
4250
  ], AuthController.prototype, "logoutUser", null);
3871
- __decorate20([
4251
+ __decorate21([
3872
4252
  Post("/change-password"),
3873
4253
  isAuth(),
3874
4254
  Validate(changePasswordDto),
3875
4255
  ResMsg("auth.success.passwordChanged"),
3876
4256
  __param5(0, User2("id")),
3877
4257
  __param5(1, Body()),
3878
- __metadata20("design:type", Function),
3879
- __metadata20("design:paramtypes", [String, Object]),
3880
- __metadata20("design:returntype", Promise)
4258
+ __metadata21("design:type", Function),
4259
+ __metadata21("design:paramtypes", [String, Object]),
4260
+ __metadata21("design:returntype", Promise)
3881
4261
  ], AuthController.prototype, "changePassword", null);
3882
- __decorate20([
4262
+ __decorate21([
3883
4263
  Get("/me"),
3884
4264
  RateLimit({ limit: 30, window: "1m", key: cookieFingerprint() }),
3885
4265
  ResMsg("auth.users.success.retrieved"),
3886
4266
  __param5(0, Headers("authorization")),
3887
- __metadata20("design:type", Function),
3888
- __metadata20("design:paramtypes", [String]),
3889
- __metadata20("design:returntype", Promise)
4267
+ __metadata21("design:type", Function),
4268
+ __metadata21("design:paramtypes", [String]),
4269
+ __metadata21("design:returntype", Promise)
3890
4270
  ], AuthController.prototype, "userProfile", null);
3891
- __decorate20([
4271
+ __decorate21([
3892
4272
  Post("/forgot-password"),
3893
- RateLimit({ limit: 3, window: "15m", key: authIdentityRateLimitKey, message: "Too many password reset requests. Please try again later." }),
4273
+ RateLimit({ limit: 3, window: "15m", key: authEmailRateLimitKey, message: "Too many password reset requests. Please try again later." }),
3894
4274
  Validate(resetPasswordDto),
3895
4275
  ResMsg("auth.success.passwordResetSent"),
3896
4276
  __param5(0, Body()),
3897
- __metadata20("design:type", Function),
3898
- __metadata20("design:paramtypes", [Object]),
3899
- __metadata20("design:returntype", Promise)
4277
+ __metadata21("design:type", Function),
4278
+ __metadata21("design:paramtypes", [Object]),
4279
+ __metadata21("design:returntype", Promise)
3900
4280
  ], AuthController.prototype, "forgotPassword", null);
3901
- __decorate20([
4281
+ __decorate21([
3902
4282
  Post("/reset-password"),
3903
4283
  RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many password reset attempts. Please try again later." }),
3904
4284
  Validate(confirmResetPasswordDto),
3905
4285
  ResMsg("auth.success.passwordReset"),
3906
4286
  __param5(0, Body()),
3907
- __metadata20("design:type", Function),
3908
- __metadata20("design:paramtypes", [Object]),
3909
- __metadata20("design:returntype", Promise)
4287
+ __metadata21("design:type", Function),
4288
+ __metadata21("design:paramtypes", [Object]),
4289
+ __metadata21("design:returntype", Promise)
3910
4290
  ], AuthController.prototype, "resetPassword", null);
3911
- AuthController = __decorate20([
4291
+ AuthController = __decorate21([
3912
4292
  Controller("/auth"),
3913
- __metadata20("design:paramtypes", [typeof (_a12 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a12 : Object])
4293
+ __metadata21("design:paramtypes", [typeof (_a13 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a13 : Object])
3914
4294
  ], AuthController);
3915
4295
 
3916
4296
  // src/auth/AuthResolver.ts
3917
- import { APP, Container, DI, Inject as Inject12, LOGGER, Meta, Service as Service4 } from "najm-core";
4297
+ import { APP, Container, DI, Inject as Inject13, LOGGER, Meta, Service as Service4 } from "najm-core";
3918
4298
  import { USER, ROLE, PERMISSIONS } from "najm-guard";
3919
- var __decorate21 = function(decorators, target, key, desc) {
4299
+ var __decorate22 = function(decorators, target, key, desc) {
3920
4300
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3921
4301
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3922
4302
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3923
4303
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3924
4304
  };
3925
- var __metadata21 = function(k, v) {
4305
+ var __metadata22 = function(k, v) {
3926
4306
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3927
4307
  };
3928
- var _a13;
4308
+ var _a14;
3929
4309
  var AuthResolver = class AuthResolver2 {
3930
4310
  static {
3931
4311
  __name(this, "AuthResolver");
@@ -3976,6 +4356,12 @@ var AuthResolver = class AuthResolver2 {
3976
4356
  const currentVersion = await tokenService.getSessionVersion(session.user.id);
3977
4357
  if ((session.sessionVersion ?? 0) !== currentVersion)
3978
4358
  return false;
4359
+ if (!await tokenService.isSessionFamilyLive(session.tokenFamily, session.user.id)) {
4360
+ return false;
4361
+ }
4362
+ const status = session.user.status;
4363
+ if (status !== void 0 && status !== "active")
4364
+ return false;
3979
4365
  return {
3980
4366
  user: { ...session.user, permissions: session.permissions },
3981
4367
  role: session.user.role ?? session.roles[0],
@@ -4041,32 +4427,32 @@ var AuthResolver = class AuthResolver2 {
4041
4427
  await authService.warmupPasswordHash();
4042
4428
  }
4043
4429
  };
4044
- __decorate21([
4430
+ __decorate22([
4045
4431
  DI(),
4046
- __metadata21("design:type", typeof (_a13 = typeof Container !== "undefined" && Container) === "function" ? _a13 : Object)
4432
+ __metadata22("design:type", typeof (_a14 = typeof Container !== "undefined" && Container) === "function" ? _a14 : Object)
4047
4433
  ], AuthResolver.prototype, "container", void 0);
4048
- __decorate21([
4049
- Inject12(APP),
4050
- __metadata21("design:type", Object)
4434
+ __decorate22([
4435
+ Inject13(APP),
4436
+ __metadata22("design:type", Object)
4051
4437
  ], AuthResolver.prototype, "app", void 0);
4052
- __decorate21([
4053
- Inject12(LOGGER),
4054
- __metadata21("design:type", Object)
4438
+ __decorate22([
4439
+ Inject13(LOGGER),
4440
+ __metadata22("design:type", Object)
4055
4441
  ], AuthResolver.prototype, "log", void 0);
4056
- AuthResolver = __decorate21([
4442
+ AuthResolver = __decorate22([
4057
4443
  Service4(),
4058
4444
  Meta({ layer: "plugin", order: 30 })
4059
4445
  ], AuthResolver);
4060
4446
 
4061
4447
  // src/auth/AuthIdentityContextService.ts
4062
- import { DI as DI2, Inject as Inject13, INJECTION_TYPES, Meta as Meta2, Service as Service5 } from "najm-core";
4063
- var __decorate22 = function(decorators, target, key, desc) {
4448
+ import { DI as DI2, Inject as Inject14, INJECTION_TYPES, Meta as Meta2, Service as Service5 } from "najm-core";
4449
+ var __decorate23 = function(decorators, target, key, desc) {
4064
4450
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4065
4451
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4066
4452
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4067
4453
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4068
4454
  };
4069
- var __metadata22 = function(k, v) {
4455
+ var __metadata23 = function(k, v) {
4070
4456
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4071
4457
  };
4072
4458
  var __param6 = function(paramIndex, decorator) {
@@ -4096,28 +4482,28 @@ var AuthIdentityContextService = class AuthIdentityContextService2 {
4096
4482
  });
4097
4483
  }
4098
4484
  };
4099
- __decorate22([
4485
+ __decorate23([
4100
4486
  DI2(),
4101
- __metadata22("design:type", Object)
4487
+ __metadata23("design:type", Object)
4102
4488
  ], AuthIdentityContextService.prototype, "container", void 0);
4103
- AuthIdentityContextService = __decorate22([
4489
+ AuthIdentityContextService = __decorate23([
4104
4490
  Service5(),
4105
4491
  Meta2({ layer: "plugin", order: 14 }),
4106
- __param6(0, Inject13(AUTH_CONFIG)),
4107
- __metadata22("design:paramtypes", [Object])
4492
+ __param6(0, Inject14(AUTH_CONFIG)),
4493
+ __metadata23("design:paramtypes", [Object])
4108
4494
  ], AuthIdentityContextService);
4109
4495
 
4110
4496
  // src/auth/RegistrationController.ts
4111
4497
  import { Body as Body2, Controller as Controller2, Post as Post2, ResMsg as ResMsg2 } from "najm-core";
4112
4498
  import { RateLimit as RateLimit2 } from "najm-rate";
4113
4499
  import { Validate as Validate2 } from "najm-validation";
4114
- var __decorate23 = function(decorators, target, key, desc) {
4500
+ var __decorate24 = function(decorators, target, key, desc) {
4115
4501
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4116
4502
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4117
4503
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4118
4504
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4119
4505
  };
4120
- var __metadata23 = function(k, v) {
4506
+ var __metadata24 = function(k, v) {
4121
4507
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4122
4508
  };
4123
4509
  var __param7 = function(paramIndex, decorator) {
@@ -4125,7 +4511,7 @@ var __param7 = function(paramIndex, decorator) {
4125
4511
  decorator(target, key, paramIndex);
4126
4512
  };
4127
4513
  };
4128
- var _a14;
4514
+ var _a15;
4129
4515
  var RegistrationController = class RegistrationController2 {
4130
4516
  static {
4131
4517
  __name(this, "RegistrationController");
@@ -4138,19 +4524,19 @@ var RegistrationController = class RegistrationController2 {
4138
4524
  return this.authService.registerUser(body);
4139
4525
  }
4140
4526
  };
4141
- __decorate23([
4527
+ __decorate24([
4142
4528
  Post2("/register"),
4143
- RateLimit2({ limit: 5, window: "15m", key: authIdentityRateLimitKey }),
4529
+ RateLimit2({ limit: 5, window: "15m", key: authEmailRateLimitKey }),
4144
4530
  Validate2(registerDto),
4145
4531
  ResMsg2("auth.success.register"),
4146
4532
  __param7(0, Body2()),
4147
- __metadata23("design:type", Function),
4148
- __metadata23("design:paramtypes", [Object]),
4149
- __metadata23("design:returntype", Promise)
4533
+ __metadata24("design:type", Function),
4534
+ __metadata24("design:paramtypes", [Object]),
4535
+ __metadata24("design:returntype", Promise)
4150
4536
  ], RegistrationController.prototype, "registerUser", null);
4151
- RegistrationController = __decorate23([
4537
+ RegistrationController = __decorate24([
4152
4538
  Controller2("/auth"),
4153
- __metadata23("design:paramtypes", [typeof (_a14 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a14 : Object])
4539
+ __metadata24("design:paramtypes", [typeof (_a15 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a15 : Object])
4154
4540
  ], RegistrationController);
4155
4541
 
4156
4542
  // src/auth/runAsUser.ts
@@ -4301,13 +4687,13 @@ var assignRoleDto = z2.object({
4301
4687
  });
4302
4688
 
4303
4689
  // src/roles/RoleController.ts
4304
- var __decorate24 = function(decorators, target, key, desc) {
4690
+ var __decorate25 = function(decorators, target, key, desc) {
4305
4691
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4306
4692
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4307
4693
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4308
4694
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4309
4695
  };
4310
- var __metadata24 = function(k, v) {
4696
+ var __metadata25 = function(k, v) {
4311
4697
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4312
4698
  };
4313
4699
  var __param8 = function(paramIndex, decorator) {
@@ -4315,7 +4701,7 @@ var __param8 = function(paramIndex, decorator) {
4315
4701
  decorator(target, key, paramIndex);
4316
4702
  };
4317
4703
  };
4318
- var _a15;
4704
+ var _a16;
4319
4705
  var RoleController = class RoleController2 {
4320
4706
  static {
4321
4707
  __name(this, "RoleController");
@@ -4340,35 +4726,35 @@ var RoleController = class RoleController2 {
4340
4726
  return this.roleService.delete(params.id);
4341
4727
  }
4342
4728
  };
4343
- __decorate24([
4729
+ __decorate25([
4344
4730
  Get2(),
4345
4731
  isAdmin(),
4346
4732
  ResMsg3("roles.success.retrieved"),
4347
- __metadata24("design:type", Function),
4348
- __metadata24("design:paramtypes", []),
4349
- __metadata24("design:returntype", Promise)
4733
+ __metadata25("design:type", Function),
4734
+ __metadata25("design:paramtypes", []),
4735
+ __metadata25("design:returntype", Promise)
4350
4736
  ], RoleController.prototype, "getRoles", null);
4351
- __decorate24([
4737
+ __decorate25([
4352
4738
  Get2("/:id"),
4353
4739
  isAdmin(),
4354
4740
  Validate3({ params: roleIdParam }),
4355
4741
  ResMsg3("roles.success.retrieved"),
4356
4742
  __param8(0, Params()),
4357
- __metadata24("design:type", Function),
4358
- __metadata24("design:paramtypes", [Object]),
4359
- __metadata24("design:returntype", Promise)
4743
+ __metadata25("design:type", Function),
4744
+ __metadata25("design:paramtypes", [Object]),
4745
+ __metadata25("design:returntype", Promise)
4360
4746
  ], RoleController.prototype, "getRole", null);
4361
- __decorate24([
4747
+ __decorate25([
4362
4748
  Post3(),
4363
4749
  isAdmin(),
4364
4750
  Validate3(createRoleDto),
4365
4751
  ResMsg3("roles.success.created"),
4366
4752
  __param8(0, Body3()),
4367
- __metadata24("design:type", Function),
4368
- __metadata24("design:paramtypes", [Object]),
4369
- __metadata24("design:returntype", Promise)
4753
+ __metadata25("design:type", Function),
4754
+ __metadata25("design:paramtypes", [Object]),
4755
+ __metadata25("design:returntype", Promise)
4370
4756
  ], RoleController.prototype, "createRole", null);
4371
- __decorate24([
4757
+ __decorate25([
4372
4758
  Put("/:id"),
4373
4759
  isAdmin(),
4374
4760
  Validate3({
@@ -4378,34 +4764,34 @@ __decorate24([
4378
4764
  ResMsg3("roles.success.updated"),
4379
4765
  __param8(0, Params()),
4380
4766
  __param8(1, Body3()),
4381
- __metadata24("design:type", Function),
4382
- __metadata24("design:paramtypes", [Object, Object]),
4383
- __metadata24("design:returntype", Promise)
4767
+ __metadata25("design:type", Function),
4768
+ __metadata25("design:paramtypes", [Object, Object]),
4769
+ __metadata25("design:returntype", Promise)
4384
4770
  ], RoleController.prototype, "updateRole", null);
4385
- __decorate24([
4771
+ __decorate25([
4386
4772
  Delete("/:id"),
4387
4773
  isAdmin(),
4388
4774
  Validate3({ params: roleIdParam }),
4389
4775
  ResMsg3("roles.success.deleted"),
4390
4776
  __param8(0, Params()),
4391
- __metadata24("design:type", Function),
4392
- __metadata24("design:paramtypes", [Object]),
4393
- __metadata24("design:returntype", Promise)
4777
+ __metadata25("design:type", Function),
4778
+ __metadata25("design:paramtypes", [Object]),
4779
+ __metadata25("design:returntype", Promise)
4394
4780
  ], RoleController.prototype, "deleteRole", null);
4395
- RoleController = __decorate24([
4781
+ RoleController = __decorate25([
4396
4782
  Controller3("/roles"),
4397
- __metadata24("design:paramtypes", [typeof (_a15 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a15 : Object])
4783
+ __metadata25("design:paramtypes", [typeof (_a16 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a16 : Object])
4398
4784
  ], RoleController);
4399
4785
 
4400
4786
  // src/users/UserController.ts
4401
4787
  import { Validate as Validate4 } from "najm-validation";
4402
- var __decorate25 = function(decorators, target, key, desc) {
4788
+ var __decorate26 = function(decorators, target, key, desc) {
4403
4789
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4404
4790
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4405
4791
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4406
4792
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4407
4793
  };
4408
- var __metadata25 = function(k, v) {
4794
+ var __metadata26 = function(k, v) {
4409
4795
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4410
4796
  };
4411
4797
  var __param9 = function(paramIndex, decorator) {
@@ -4413,7 +4799,7 @@ var __param9 = function(paramIndex, decorator) {
4413
4799
  decorator(target, key, paramIndex);
4414
4800
  };
4415
4801
  };
4416
- var _a16;
4802
+ var _a17;
4417
4803
  var UserController = class UserController2 {
4418
4804
  static {
4419
4805
  __name(this, "UserController");
@@ -4460,75 +4846,75 @@ var UserController = class UserController2 {
4460
4846
  return this.userService.removeRole(params.userId);
4461
4847
  }
4462
4848
  };
4463
- __decorate25([
4849
+ __decorate26([
4464
4850
  Get3(),
4465
4851
  isAdmin(),
4466
4852
  Validate4({ query: userListQuery }),
4467
4853
  ResMsg4("users.success.retrieved"),
4468
4854
  __param9(0, Query()),
4469
- __metadata25("design:type", Function),
4470
- __metadata25("design:paramtypes", [Object]),
4471
- __metadata25("design:returntype", Promise)
4855
+ __metadata26("design:type", Function),
4856
+ __metadata26("design:paramtypes", [Object]),
4857
+ __metadata26("design:returntype", Promise)
4472
4858
  ], UserController.prototype, "getUsers", null);
4473
- __decorate25([
4859
+ __decorate26([
4474
4860
  Get3("/lang"),
4475
4861
  isAuth(),
4476
4862
  ResMsg4("users.success.retrieved"),
4477
- __metadata25("design:type", Function),
4478
- __metadata25("design:paramtypes", []),
4479
- __metadata25("design:returntype", Promise)
4863
+ __metadata26("design:type", Function),
4864
+ __metadata26("design:paramtypes", []),
4865
+ __metadata26("design:returntype", Promise)
4480
4866
  ], UserController.prototype, "getLang", null);
4481
- __decorate25([
4867
+ __decorate26([
4482
4868
  Post4("/lang/:language"),
4483
4869
  isAuth(),
4484
4870
  Validate4({ params: languageParam }),
4485
4871
  ResMsg4("users.success.updated"),
4486
4872
  __param9(0, Params2()),
4487
- __metadata25("design:type", Function),
4488
- __metadata25("design:paramtypes", [Object]),
4489
- __metadata25("design:returntype", Promise)
4873
+ __metadata26("design:type", Function),
4874
+ __metadata26("design:paramtypes", [Object]),
4875
+ __metadata26("design:returntype", Promise)
4490
4876
  ], UserController.prototype, "updateLang", null);
4491
- __decorate25([
4877
+ __decorate26([
4492
4878
  Get3("/:id"),
4493
4879
  isAdmin(),
4494
4880
  Validate4({ params: userIdParam }),
4495
4881
  ResMsg4("users.success.retrieved"),
4496
4882
  __param9(0, Params2()),
4497
- __metadata25("design:type", Function),
4498
- __metadata25("design:paramtypes", [Object]),
4499
- __metadata25("design:returntype", Promise)
4883
+ __metadata26("design:type", Function),
4884
+ __metadata26("design:paramtypes", [Object]),
4885
+ __metadata26("design:returntype", Promise)
4500
4886
  ], UserController.prototype, "getUser", null);
4501
- __decorate25([
4887
+ __decorate26([
4502
4888
  Get3("/email/:email"),
4503
4889
  isAdmin(),
4504
4890
  Validate4({ params: emailParam }),
4505
4891
  ResMsg4("users.success.retrieved"),
4506
4892
  __param9(0, Params2()),
4507
- __metadata25("design:type", Function),
4508
- __metadata25("design:paramtypes", [Object]),
4509
- __metadata25("design:returntype", Promise)
4893
+ __metadata26("design:type", Function),
4894
+ __metadata26("design:paramtypes", [Object]),
4895
+ __metadata26("design:returntype", Promise)
4510
4896
  ], UserController.prototype, "getByEmail", null);
4511
- __decorate25([
4897
+ __decorate26([
4512
4898
  Get3("/role/:userId"),
4513
4899
  isAdmin(),
4514
4900
  Validate4({ params: userIdInParam }),
4515
4901
  ResMsg4("users.success.retrieved"),
4516
4902
  __param9(0, Params2()),
4517
- __metadata25("design:type", Function),
4518
- __metadata25("design:paramtypes", [Object]),
4519
- __metadata25("design:returntype", Promise)
4903
+ __metadata26("design:type", Function),
4904
+ __metadata26("design:paramtypes", [Object]),
4905
+ __metadata26("design:returntype", Promise)
4520
4906
  ], UserController.prototype, "getRole", null);
4521
- __decorate25([
4907
+ __decorate26([
4522
4908
  Post4(),
4523
4909
  isAdmin(),
4524
4910
  Validate4(createUserDto),
4525
- ResMsg4("users.success.created"),
4526
- __param9(0, Body4()),
4527
- __metadata25("design:type", Function),
4528
- __metadata25("design:paramtypes", [Object]),
4529
- __metadata25("design:returntype", Promise)
4911
+ ResMsg4("users.success.created"),
4912
+ __param9(0, Body4()),
4913
+ __metadata26("design:type", Function),
4914
+ __metadata26("design:paramtypes", [Object]),
4915
+ __metadata26("design:returntype", Promise)
4530
4916
  ], UserController.prototype, "create", null);
4531
- __decorate25([
4917
+ __decorate26([
4532
4918
  Put2("/:id"),
4533
4919
  isAdmin(),
4534
4920
  Validate4({
@@ -4538,51 +4924,51 @@ __decorate25([
4538
4924
  ResMsg4("users.success.updated"),
4539
4925
  __param9(0, Params2()),
4540
4926
  __param9(1, Body4()),
4541
- __metadata25("design:type", Function),
4542
- __metadata25("design:paramtypes", [Object, Object]),
4543
- __metadata25("design:returntype", Promise)
4927
+ __metadata26("design:type", Function),
4928
+ __metadata26("design:paramtypes", [Object, Object]),
4929
+ __metadata26("design:returntype", Promise)
4544
4930
  ], UserController.prototype, "update", null);
4545
- __decorate25([
4931
+ __decorate26([
4546
4932
  Delete2("/:id"),
4547
4933
  isAdmin(),
4548
4934
  Validate4({ params: userIdParam }),
4549
4935
  ResMsg4("users.success.deleted"),
4550
4936
  __param9(0, Params2()),
4551
- __metadata25("design:type", Function),
4552
- __metadata25("design:paramtypes", [Object]),
4553
- __metadata25("design:returntype", Promise)
4937
+ __metadata26("design:type", Function),
4938
+ __metadata26("design:paramtypes", [Object]),
4939
+ __metadata26("design:returntype", Promise)
4554
4940
  ], UserController.prototype, "delete", null);
4555
- __decorate25([
4941
+ __decorate26([
4556
4942
  Delete2(),
4557
4943
  isAdmin(),
4558
4944
  ResMsg4("users.success.allDeleted"),
4559
- __metadata25("design:type", Function),
4560
- __metadata25("design:paramtypes", []),
4561
- __metadata25("design:returntype", Promise)
4945
+ __metadata26("design:type", Function),
4946
+ __metadata26("design:paramtypes", []),
4947
+ __metadata26("design:returntype", Promise)
4562
4948
  ], UserController.prototype, "deleteAll", null);
4563
- __decorate25([
4949
+ __decorate26([
4564
4950
  Post4("/assign/:userId/:roleId"),
4565
4951
  isAdmin(),
4566
4952
  Validate4({ params: assignRoleParams }),
4567
4953
  ResMsg4("users.success.updated"),
4568
4954
  __param9(0, Params2()),
4569
- __metadata25("design:type", Function),
4570
- __metadata25("design:paramtypes", [Object]),
4571
- __metadata25("design:returntype", Promise)
4955
+ __metadata26("design:type", Function),
4956
+ __metadata26("design:paramtypes", [Object]),
4957
+ __metadata26("design:returntype", Promise)
4572
4958
  ], UserController.prototype, "assignRole", null);
4573
- __decorate25([
4959
+ __decorate26([
4574
4960
  Delete2("/remove/:userId"),
4575
4961
  isAdmin(),
4576
4962
  Validate4({ params: userIdInParam }),
4577
4963
  ResMsg4("users.success.updated"),
4578
4964
  __param9(0, Params2()),
4579
- __metadata25("design:type", Function),
4580
- __metadata25("design:paramtypes", [Object]),
4581
- __metadata25("design:returntype", Promise)
4965
+ __metadata26("design:type", Function),
4966
+ __metadata26("design:paramtypes", [Object]),
4967
+ __metadata26("design:returntype", Promise)
4582
4968
  ], UserController.prototype, "removeRole", null);
4583
- UserController = __decorate25([
4969
+ UserController = __decorate26([
4584
4970
  Controller4("/users"),
4585
- __metadata25("design:paramtypes", [typeof (_a16 = typeof UserService !== "undefined" && UserService) === "function" ? _a16 : Object])
4971
+ __metadata26("design:paramtypes", [typeof (_a17 = typeof UserService !== "undefined" && UserService) === "function" ? _a17 : Object])
4586
4972
  ], UserController);
4587
4973
 
4588
4974
  // src/permissions/index.ts
@@ -4603,15 +4989,15 @@ __export(permissions_exports, {
4603
4989
 
4604
4990
  // src/permissions/PermissionRepository.ts
4605
4991
  import { eq as eq7, and as and4 } from "drizzle-orm";
4606
- import { Repository as Repository6, Inject as Inject14 } from "najm-core";
4992
+ import { Repository as Repository6, Inject as Inject15 } from "najm-core";
4607
4993
  import { DB as DB6 } from "najm-database";
4608
- var __decorate26 = function(decorators, target, key, desc) {
4994
+ var __decorate27 = function(decorators, target, key, desc) {
4609
4995
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4610
4996
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4611
4997
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4612
4998
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4613
4999
  };
4614
- var __metadata26 = function(k, v) {
5000
+ var __metadata27 = function(k, v) {
4615
5001
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4616
5002
  };
4617
5003
  var PermissionRepository = class PermissionRepository2 {
@@ -4689,29 +5075,29 @@ var PermissionRepository = class PermissionRepository2 {
4689
5075
  return deletedPermissions;
4690
5076
  }
4691
5077
  };
4692
- __decorate26([
5078
+ __decorate27([
4693
5079
  DB6(),
4694
- __metadata26("design:type", Object)
5080
+ __metadata27("design:type", Object)
4695
5081
  ], PermissionRepository.prototype, "db", void 0);
4696
- __decorate26([
4697
- Inject14(AUTH_SCHEMA),
4698
- __metadata26("design:type", Object)
5082
+ __decorate27([
5083
+ Inject15(AUTH_SCHEMA),
5084
+ __metadata27("design:type", Object)
4699
5085
  ], PermissionRepository.prototype, "schema", void 0);
4700
- PermissionRepository = __decorate26([
5086
+ PermissionRepository = __decorate27([
4701
5087
  Repository6()
4702
5088
  ], PermissionRepository);
4703
5089
 
4704
5090
  // src/permissions/PermissionGuards.ts
4705
- import { Injectable as Injectable12 } from "najm-core";
5091
+ import { Injectable as Injectable13 } from "najm-core";
4706
5092
  import { GuardParams as GuardParams2, User as User3 } from "najm-core";
4707
5093
  import { createGuard as createGuard4, composeGuards as composeGuards3 } from "najm-guard";
4708
- var __decorate27 = function(decorators, target, key, desc) {
5094
+ var __decorate28 = function(decorators, target, key, desc) {
4709
5095
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4710
5096
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4711
5097
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4712
5098
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4713
5099
  };
4714
- var __metadata27 = function(k, v) {
5100
+ var __metadata28 = function(k, v) {
4715
5101
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4716
5102
  };
4717
5103
  var __param10 = function(paramIndex, decorator) {
@@ -4747,15 +5133,15 @@ var PermissionGuard = class PermissionGuard2 {
4747
5133
  return false;
4748
5134
  }
4749
5135
  };
4750
- __decorate27([
5136
+ __decorate28([
4751
5137
  __param10(0, GuardParams2()),
4752
5138
  __param10(1, User3("permissions")),
4753
- __metadata27("design:type", Function),
4754
- __metadata27("design:paramtypes", [String, Array]),
4755
- __metadata27("design:returntype", Object)
5139
+ __metadata28("design:type", Function),
5140
+ __metadata28("design:paramtypes", [String, Array]),
5141
+ __metadata28("design:returntype", Object)
4756
5142
  ], PermissionGuard.prototype, "canActivate", null);
4757
- PermissionGuard = __decorate27([
4758
- Injectable12()
5143
+ PermissionGuard = __decorate28([
5144
+ Injectable13()
4759
5145
  ], PermissionGuard);
4760
5146
  var Permission = createGuard4(PermissionGuard);
4761
5147
  var Can = /* @__PURE__ */ __name((permission) => composeGuards3(isAuth(), Permission(permission))(), "Can");
@@ -4766,23 +5152,23 @@ import { Get as Get4, Post as Post5, Put as Put3, Delete as Delete3, ResMsg as R
4766
5152
  import { Params as Params3, Body as Body5 } from "najm-core";
4767
5153
 
4768
5154
  // src/permissions/PermissionService.ts
4769
- import { Injectable as Injectable14 } from "najm-core";
5155
+ import { Injectable as Injectable15 } from "najm-core";
4770
5156
 
4771
5157
  // src/permissions/PermissionValidator.ts
4772
- import { Injectable as Injectable13 } from "najm-core";
5158
+ import { Injectable as Injectable14 } from "najm-core";
4773
5159
  import { I18n as I18n9 } from "najm-i18n";
4774
5160
  import { Err as Err14 } from "najm-core";
4775
- var __decorate28 = function(decorators, target, key, desc) {
5161
+ var __decorate29 = function(decorators, target, key, desc) {
4776
5162
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4777
5163
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4778
5164
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4779
5165
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4780
5166
  };
4781
- var __metadata28 = function(k, v) {
5167
+ var __metadata29 = function(k, v) {
4782
5168
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4783
5169
  };
4784
- var _a17;
4785
- var _b10;
5170
+ var _a18;
5171
+ var _b11;
4786
5172
  var PermissionValidator = class PermissionValidator2 {
4787
5173
  static {
4788
5174
  __name(this, "PermissionValidator");
@@ -4849,28 +5235,30 @@ var PermissionValidator = class PermissionValidator2 {
4849
5235
  }
4850
5236
  }
4851
5237
  };
4852
- __decorate28([
5238
+ __decorate29([
4853
5239
  I18n9("permissions"),
4854
- __metadata28("design:type", Object)
5240
+ __metadata29("design:type", Object)
4855
5241
  ], PermissionValidator.prototype, "t", void 0);
4856
- PermissionValidator = __decorate28([
4857
- Injectable13(),
4858
- __metadata28("design:paramtypes", [typeof (_a17 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a17 : Object, typeof (_b10 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b10 : Object])
5242
+ PermissionValidator = __decorate29([
5243
+ Injectable14(),
5244
+ __metadata29("design:paramtypes", [typeof (_a18 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a18 : Object, typeof (_b11 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b11 : Object])
4859
5245
  ], PermissionValidator);
4860
5246
 
4861
5247
  // src/permissions/PermissionService.ts
4862
- var __decorate29 = function(decorators, target, key, desc) {
5248
+ var __decorate30 = function(decorators, target, key, desc) {
4863
5249
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4864
5250
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4865
5251
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4866
5252
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4867
5253
  };
4868
- var __metadata29 = function(k, v) {
5254
+ var __metadata30 = function(k, v) {
4869
5255
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4870
5256
  };
4871
- var _a18;
4872
- var _b11;
5257
+ var _a19;
5258
+ var _b12;
4873
5259
  var _c8;
5260
+ var _d7;
5261
+ var _e6;
4874
5262
  var PermissionService = class PermissionService2 {
4875
5263
  static {
4876
5264
  __name(this, "PermissionService");
@@ -4878,10 +5266,30 @@ var PermissionService = class PermissionService2 {
4878
5266
  permissionRepository;
4879
5267
  permissionValidator;
4880
5268
  roleService;
4881
- constructor(permissionRepository, permissionValidator, roleService) {
5269
+ userRepository;
5270
+ sessionInvalidation;
5271
+ constructor(permissionRepository, permissionValidator, roleService, userRepository, sessionInvalidation) {
4882
5272
  this.permissionRepository = permissionRepository;
4883
5273
  this.permissionValidator = permissionValidator;
4884
5274
  this.roleService = roleService;
5275
+ this.userRepository = userRepository;
5276
+ this.sessionInvalidation = sessionInvalidation;
5277
+ }
5278
+ /**
5279
+ * End the sessions of everyone holding a role whose permission set changed.
5280
+ *
5281
+ * Access tokens and signed session snapshots both carry permissions as
5282
+ * claims, so a permission removed from a role stays exercisable until the
5283
+ * sessions that captured it end. This is an infrequent administrative
5284
+ * action, and the work is proportional to the role's membership.
5285
+ */
5286
+ async invalidateRoleHolders(roleId) {
5287
+ if (!this.userRepository || !this.sessionInvalidation)
5288
+ return;
5289
+ const userIds = await this.userRepository.getIdsByRole(roleId);
5290
+ for (const userId of userIds) {
5291
+ await this.sessionInvalidation.invalidateAccessTokens(userId);
5292
+ }
4885
5293
  }
4886
5294
  async getAll() {
4887
5295
  return await this.permissionRepository.getAll();
@@ -4918,10 +5326,14 @@ var PermissionService = class PermissionService2 {
4918
5326
  }
4919
5327
  async assignPermissionToRole(roleId, permissionId) {
4920
5328
  await this.permissionValidator.checkRoleHasPermission(roleId, permissionId);
4921
- return await this.permissionRepository.assignPermissionToRole(roleId, permissionId);
5329
+ const assigned = await this.permissionRepository.assignPermissionToRole(roleId, permissionId);
5330
+ await this.invalidateRoleHolders(roleId);
5331
+ return assigned;
4922
5332
  }
4923
5333
  async removePermissionFromRole(roleId, permissionId) {
4924
- return await this.permissionRepository.removePermissionFromRole(roleId, permissionId);
5334
+ const removed = await this.permissionRepository.removePermissionFromRole(roleId, permissionId);
5335
+ await this.invalidateRoleHolders(roleId);
5336
+ return removed;
4925
5337
  }
4926
5338
  async seedDefaultPermissions(defaultPermissions) {
4927
5339
  const created = [];
@@ -4975,9 +5387,9 @@ var PermissionService = class PermissionService2 {
4975
5387
  return await this.permissionRepository.deleteAll();
4976
5388
  }
4977
5389
  };
4978
- PermissionService = __decorate29([
4979
- Injectable14(),
4980
- __metadata29("design:paramtypes", [typeof (_a18 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a18 : Object, typeof (_b11 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b11 : Object, typeof (_c8 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c8 : Object])
5390
+ PermissionService = __decorate30([
5391
+ Injectable15(),
5392
+ __metadata30("design:paramtypes", [typeof (_a19 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a19 : Object, typeof (_b12 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b12 : Object, typeof (_c8 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c8 : Object, typeof (_d7 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _d7 : Object, typeof (_e6 = typeof SessionInvalidationService !== "undefined" && SessionInvalidationService) === "function" ? _e6 : Object])
4981
5393
  ], PermissionService);
4982
5394
 
4983
5395
  // src/permissions/PermissionController.ts
@@ -5010,13 +5422,13 @@ var checkPermissionDto = z3.object({
5010
5422
  });
5011
5423
 
5012
5424
  // src/permissions/PermissionController.ts
5013
- var __decorate30 = function(decorators, target, key, desc) {
5425
+ var __decorate31 = function(decorators, target, key, desc) {
5014
5426
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5015
5427
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5016
5428
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5017
5429
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5018
5430
  };
5019
- var __metadata30 = function(k, v) {
5431
+ var __metadata31 = function(k, v) {
5020
5432
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5021
5433
  };
5022
5434
  var __param11 = function(paramIndex, decorator) {
@@ -5024,7 +5436,7 @@ var __param11 = function(paramIndex, decorator) {
5024
5436
  decorator(target, key, paramIndex);
5025
5437
  };
5026
5438
  };
5027
- var _a19;
5439
+ var _a20;
5028
5440
  var PermissionController = class PermissionController2 {
5029
5441
  static {
5030
5442
  __name(this, "PermissionController");
@@ -5070,32 +5482,32 @@ var PermissionController = class PermissionController2 {
5070
5482
  return this.permissionService.deleteAll();
5071
5483
  }
5072
5484
  };
5073
- __decorate30([
5485
+ __decorate31([
5074
5486
  Get4(),
5075
5487
  ResMsg5("permissions.success.retrieved"),
5076
- __metadata30("design:type", Function),
5077
- __metadata30("design:paramtypes", []),
5078
- __metadata30("design:returntype", Promise)
5488
+ __metadata31("design:type", Function),
5489
+ __metadata31("design:paramtypes", []),
5490
+ __metadata31("design:returntype", Promise)
5079
5491
  ], PermissionController.prototype, "getPermissions", null);
5080
- __decorate30([
5492
+ __decorate31([
5081
5493
  Get4("/:id"),
5082
5494
  Validate5({ params: permissionIdParam }),
5083
5495
  ResMsg5("permissions.success.retrieved"),
5084
5496
  __param11(0, Params3()),
5085
- __metadata30("design:type", Function),
5086
- __metadata30("design:paramtypes", [Object]),
5087
- __metadata30("design:returntype", Promise)
5497
+ __metadata31("design:type", Function),
5498
+ __metadata31("design:paramtypes", [Object]),
5499
+ __metadata31("design:returntype", Promise)
5088
5500
  ], PermissionController.prototype, "getPermission", null);
5089
- __decorate30([
5501
+ __decorate31([
5090
5502
  Post5(),
5091
5503
  Validate5(createPermissionDto),
5092
5504
  ResMsg5({ message: "Permission created successfully", status: 201 }),
5093
5505
  __param11(0, Body5()),
5094
- __metadata30("design:type", Function),
5095
- __metadata30("design:paramtypes", [Object]),
5096
- __metadata30("design:returntype", Promise)
5506
+ __metadata31("design:type", Function),
5507
+ __metadata31("design:paramtypes", [Object]),
5508
+ __metadata31("design:returntype", Promise)
5097
5509
  ], PermissionController.prototype, "create", null);
5098
- __decorate30([
5510
+ __decorate31([
5099
5511
  Put3("/:id"),
5100
5512
  Validate5({
5101
5513
  params: permissionIdParam,
@@ -5104,72 +5516,73 @@ __decorate30([
5104
5516
  ResMsg5("permissions.success.updated"),
5105
5517
  __param11(0, Params3()),
5106
5518
  __param11(1, Body5()),
5107
- __metadata30("design:type", Function),
5108
- __metadata30("design:paramtypes", [Object, Object]),
5109
- __metadata30("design:returntype", Promise)
5519
+ __metadata31("design:type", Function),
5520
+ __metadata31("design:paramtypes", [Object, Object]),
5521
+ __metadata31("design:returntype", Promise)
5110
5522
  ], PermissionController.prototype, "update", null);
5111
- __decorate30([
5523
+ __decorate31([
5112
5524
  Delete3("/:id"),
5113
5525
  Validate5({ params: permissionIdParam }),
5114
5526
  ResMsg5("permissions.success.deleted"),
5115
5527
  __param11(0, Params3()),
5116
- __metadata30("design:type", Function),
5117
- __metadata30("design:paramtypes", [Object]),
5118
- __metadata30("design:returntype", Promise)
5528
+ __metadata31("design:type", Function),
5529
+ __metadata31("design:paramtypes", [Object]),
5530
+ __metadata31("design:returntype", Promise)
5119
5531
  ], PermissionController.prototype, "delete", null);
5120
- __decorate30([
5532
+ __decorate31([
5121
5533
  Get4("/role/:id"),
5122
5534
  Validate5({ params: roleIdParam }),
5123
5535
  ResMsg5("permissions.success.retrieved"),
5124
5536
  __param11(0, Params3()),
5125
- __metadata30("design:type", Function),
5126
- __metadata30("design:paramtypes", [Object]),
5127
- __metadata30("design:returntype", Promise)
5537
+ __metadata31("design:type", Function),
5538
+ __metadata31("design:paramtypes", [Object]),
5539
+ __metadata31("design:returntype", Promise)
5128
5540
  ], PermissionController.prototype, "getByRole", null);
5129
- __decorate30([
5541
+ __decorate31([
5130
5542
  Get4("/roles/:id"),
5131
5543
  Validate5({ params: permissionIdParam }),
5132
5544
  ResMsg5("permissions.success.retrieved"),
5133
5545
  __param11(0, Params3()),
5134
- __metadata30("design:type", Function),
5135
- __metadata30("design:paramtypes", [Object]),
5136
- __metadata30("design:returntype", Promise)
5546
+ __metadata31("design:type", Function),
5547
+ __metadata31("design:paramtypes", [Object]),
5548
+ __metadata31("design:returntype", Promise)
5137
5549
  ], PermissionController.prototype, "getRolesByPermission", null);
5138
- __decorate30([
5550
+ __decorate31([
5139
5551
  Post5("/assign/:roleId/:permissionId"),
5140
5552
  Validate5({ params: assignPermissionDto }),
5141
5553
  ResMsg5("permissions.success.assigned"),
5142
5554
  __param11(0, Params3()),
5143
- __metadata30("design:type", Function),
5144
- __metadata30("design:paramtypes", [Object]),
5145
- __metadata30("design:returntype", Promise)
5555
+ __metadata31("design:type", Function),
5556
+ __metadata31("design:paramtypes", [Object]),
5557
+ __metadata31("design:returntype", Promise)
5146
5558
  ], PermissionController.prototype, "assignToRole", null);
5147
- __decorate30([
5559
+ __decorate31([
5148
5560
  Delete3("/remove/:roleId/:permissionId"),
5149
5561
  Validate5({ params: assignPermissionDto }),
5150
5562
  ResMsg5("permissions.success.removed"),
5151
5563
  __param11(0, Params3()),
5152
- __metadata30("design:type", Function),
5153
- __metadata30("design:paramtypes", [Object]),
5154
- __metadata30("design:returntype", Promise)
5564
+ __metadata31("design:type", Function),
5565
+ __metadata31("design:paramtypes", [Object]),
5566
+ __metadata31("design:returntype", Promise)
5155
5567
  ], PermissionController.prototype, "removeFromRole", null);
5156
- __decorate30([
5568
+ __decorate31([
5157
5569
  Delete3(),
5158
5570
  isAdmin(),
5159
5571
  ResMsg5("permissions.success.allDeleted"),
5160
- __metadata30("design:type", Function),
5161
- __metadata30("design:paramtypes", []),
5162
- __metadata30("design:returntype", Promise)
5572
+ __metadata31("design:type", Function),
5573
+ __metadata31("design:paramtypes", []),
5574
+ __metadata31("design:returntype", Promise)
5163
5575
  ], PermissionController.prototype, "deleteAll", null);
5164
- PermissionController = __decorate30([
5576
+ PermissionController = __decorate31([
5165
5577
  Controller5("/permissions"),
5166
5578
  isAdmin(),
5167
- __metadata30("design:paramtypes", [typeof (_a19 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a19 : Object])
5579
+ __metadata31("design:paramtypes", [typeof (_a20 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a20 : Object])
5168
5580
  ], PermissionController);
5169
5581
 
5170
5582
  // src/tokens/index.ts
5171
5583
  var tokens_exports = {};
5172
5584
  __export(tokens_exports, {
5585
+ SessionInvalidationService: () => SessionInvalidationService,
5173
5586
  TokenRepository: () => TokenRepository,
5174
5587
  TokenService: () => TokenService,
5175
5588
  createTokenDto: () => createTokenDto,
@@ -5371,15 +5784,15 @@ function own(table, opts) {
5371
5784
  __name(own, "own");
5372
5785
 
5373
5786
  // src/ownership/configureOwnership.ts
5374
- import { Injectable as Injectable15, Inject as Inject15, User as User4, Body as Body6, Params as Params4 } from "najm-core";
5787
+ import { Injectable as Injectable16, Inject as Inject16, User as User4, Body as Body6, Params as Params4 } from "najm-core";
5375
5788
  import { createGuard as createGuard5, composeGuards as composeGuards4 } from "najm-guard";
5376
- var __decorate31 = function(decorators, target, key, desc) {
5789
+ var __decorate32 = function(decorators, target, key, desc) {
5377
5790
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5378
5791
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5379
5792
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5380
5793
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5381
5794
  };
5382
- var __metadata31 = function(k, v) {
5795
+ var __metadata32 = function(k, v) {
5383
5796
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5384
5797
  };
5385
5798
  var __param12 = function(paramIndex, decorator) {
@@ -5399,7 +5812,7 @@ function toSingular(plural) {
5399
5812
  }
5400
5813
  __name(toSingular, "toSingular");
5401
5814
  function createResourceGuards(ownershipClass, resourceType, resource, options) {
5402
- var _a28, _b15;
5815
+ var _a29, _b16;
5403
5816
  const writeGuard = options?.adminGuard ?? isAdmin;
5404
5817
  let AccessGuard = class AccessGuard {
5405
5818
  static {
@@ -5411,19 +5824,19 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
5411
5824
  return allowed ? { owner: user } : false;
5412
5825
  }
5413
5826
  };
5414
- __decorate31([
5415
- Inject15(ownershipClass),
5416
- __metadata31("design:type", Object)
5827
+ __decorate32([
5828
+ Inject16(ownershipClass),
5829
+ __metadata32("design:type", Object)
5417
5830
  ], AccessGuard.prototype, "ownership", void 0);
5418
- __decorate31([
5831
+ __decorate32([
5419
5832
  __param12(0, User4()),
5420
5833
  __param12(1, Params4("id")),
5421
- __metadata31("design:type", Function),
5422
- __metadata31("design:paramtypes", [Object, String]),
5423
- __metadata31("design:returntype", typeof (_a28 = typeof Promise !== "undefined" && Promise) === "function" ? _a28 : Object)
5834
+ __metadata32("design:type", Function),
5835
+ __metadata32("design:paramtypes", [Object, String]),
5836
+ __metadata32("design:returntype", typeof (_a29 = typeof Promise !== "undefined" && Promise) === "function" ? _a29 : Object)
5424
5837
  ], AccessGuard.prototype, "canActivate", null);
5425
- AccessGuard = __decorate31([
5426
- Injectable15()
5838
+ AccessGuard = __decorate32([
5839
+ Injectable16()
5427
5840
  ], AccessGuard);
5428
5841
  let ListGuard = class ListGuard {
5429
5842
  static {
@@ -5435,18 +5848,18 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
5435
5848
  return { filter: ids };
5436
5849
  }
5437
5850
  };
5438
- __decorate31([
5439
- Inject15(ownershipClass),
5440
- __metadata31("design:type", Object)
5851
+ __decorate32([
5852
+ Inject16(ownershipClass),
5853
+ __metadata32("design:type", Object)
5441
5854
  ], ListGuard.prototype, "ownership", void 0);
5442
- __decorate31([
5855
+ __decorate32([
5443
5856
  __param12(0, User4()),
5444
- __metadata31("design:type", Function),
5445
- __metadata31("design:paramtypes", [Object]),
5446
- __metadata31("design:returntype", typeof (_b15 = typeof Promise !== "undefined" && Promise) === "function" ? _b15 : Object)
5857
+ __metadata32("design:type", Function),
5858
+ __metadata32("design:paramtypes", [Object]),
5859
+ __metadata32("design:returntype", typeof (_b16 = typeof Promise !== "undefined" && Promise) === "function" ? _b16 : Object)
5447
5860
  ], ListGuard.prototype, "canActivate", null);
5448
- ListGuard = __decorate31([
5449
- Injectable15()
5861
+ ListGuard = __decorate32([
5862
+ Injectable16()
5450
5863
  ], ListGuard);
5451
5864
  const access = createGuard5(AccessGuard);
5452
5865
  const list = createGuard5(ListGuard);
@@ -5577,11 +5990,11 @@ function configureOwnership(config) {
5577
5990
  }
5578
5991
  }
5579
5992
  };
5580
- GeneratedOwnershipService = __decorate31([
5581
- Injectable15()
5993
+ GeneratedOwnershipService = __decorate32([
5994
+ Injectable16()
5582
5995
  ], GeneratedOwnershipService);
5583
5996
  function bodyGuard(resourceType, bodyField, optional = false) {
5584
- var _a28;
5997
+ var _a29;
5585
5998
  let BodyAccessGuard = class BodyAccessGuard {
5586
5999
  static {
5587
6000
  __name(this, "BodyAccessGuard");
@@ -5594,19 +6007,19 @@ function configureOwnership(config) {
5594
6007
  return this.ownership.canAccess(user, resourceType, id);
5595
6008
  }
5596
6009
  };
5597
- __decorate31([
5598
- Inject15(GeneratedOwnershipService),
5599
- __metadata31("design:type", GeneratedOwnershipService)
6010
+ __decorate32([
6011
+ Inject16(GeneratedOwnershipService),
6012
+ __metadata32("design:type", GeneratedOwnershipService)
5600
6013
  ], BodyAccessGuard.prototype, "ownership", void 0);
5601
- __decorate31([
6014
+ __decorate32([
5602
6015
  __param12(0, User4()),
5603
6016
  __param12(1, Body6()),
5604
- __metadata31("design:type", Function),
5605
- __metadata31("design:paramtypes", [Object, Object]),
5606
- __metadata31("design:returntype", typeof (_a28 = typeof Promise !== "undefined" && Promise) === "function" ? _a28 : Object)
6017
+ __metadata32("design:type", Function),
6018
+ __metadata32("design:paramtypes", [Object, Object]),
6019
+ __metadata32("design:returntype", typeof (_a29 = typeof Promise !== "undefined" && Promise) === "function" ? _a29 : Object)
5607
6020
  ], BodyAccessGuard.prototype, "canActivate", null);
5608
- BodyAccessGuard = __decorate31([
5609
- Injectable15()
6021
+ BodyAccessGuard = __decorate32([
6022
+ Injectable16()
5610
6023
  ], BodyAccessGuard);
5611
6024
  return createGuard5(BodyAccessGuard);
5612
6025
  }
@@ -5721,18 +6134,18 @@ __name(Policy, "Policy");
5721
6134
  // src/ownership/OwnedDecorator.ts
5722
6135
  import "reflect-metadata";
5723
6136
  import { sql as sql5, and as and5 } from "drizzle-orm";
5724
- import { Injectable as Injectable16, Inject as Inject16, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
6137
+ import { Injectable as Injectable17, Inject as Inject17, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
5725
6138
  import { USER as USER2 } from "najm-guard";
5726
- var __decorate32 = function(decorators, target, key, desc) {
6139
+ var __decorate33 = function(decorators, target, key, desc) {
5727
6140
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5728
6141
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5729
6142
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5730
6143
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5731
6144
  };
5732
- var __metadata32 = function(k, v) {
6145
+ var __metadata33 = function(k, v) {
5733
6146
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5734
6147
  };
5735
- var _a20;
6148
+ var _a21;
5736
6149
  var OWNED_META = Symbol.for("najm:owned");
5737
6150
  var ScopeContext = class ScopeContext2 {
5738
6151
  static {
@@ -5764,18 +6177,18 @@ var ScopeContext = class ScopeContext2 {
5764
6177
  }
5765
6178
  }
5766
6179
  };
5767
- __decorate32([
6180
+ __decorate33([
5768
6181
  DI3(),
5769
- __metadata32("design:type", typeof (_a20 = typeof Container2 !== "undefined" && Container2) === "function" ? _a20 : Object)
6182
+ __metadata33("design:type", typeof (_a21 = typeof Container2 !== "undefined" && Container2) === "function" ? _a21 : Object)
5770
6183
  ], ScopeContext.prototype, "container", void 0);
5771
- ScopeContext = __decorate32([
5772
- Injectable16()
6184
+ ScopeContext = __decorate33([
6185
+ Injectable17()
5773
6186
  ], ScopeContext);
5774
6187
  function Owned(token) {
5775
6188
  return function(target) {
5776
6189
  Reflect.defineMetadata(OWNED_META, token, target);
5777
6190
  const proto = target.prototype;
5778
- Inject16(ScopeContext)(proto, "_scopeCtx");
6191
+ Inject17(ScopeContext)(proto, "_scopeCtx");
5779
6192
  function getUser(self) {
5780
6193
  return self._scopeCtx?.getUser() ?? null;
5781
6194
  }
@@ -5985,7 +6398,7 @@ __name(getAuthLocale, "getAuthLocale");
5985
6398
  var AUTH_SUPPORTED_LANGUAGES = Object.keys(AUTH_LOCALES);
5986
6399
 
5987
6400
  // src/oauth/google/GoogleOAuthProvider.ts
5988
- import { Inject as Inject18, Injectable as Injectable18 } from "najm-core";
6401
+ import { Inject as Inject19, Injectable as Injectable19 } from "najm-core";
5989
6402
 
5990
6403
  // src/oauth/types.ts
5991
6404
  var OAuthFlowError = class extends Error {
@@ -6003,15 +6416,15 @@ var OAuthFlowError = class extends Error {
6003
6416
  };
6004
6417
 
6005
6418
  // src/oauth/google/GoogleTokenVerifier.ts
6006
- import { Inject as Inject17, Injectable as Injectable17 } from "najm-core";
6419
+ import { Inject as Inject18, Injectable as Injectable18 } from "najm-core";
6007
6420
  import { createRemoteJWKSet, jwtVerify } from "jose";
6008
- var __decorate33 = function(decorators, target, key, desc) {
6421
+ var __decorate34 = function(decorators, target, key, desc) {
6009
6422
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6010
6423
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6011
6424
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6012
6425
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6013
6426
  };
6014
- var __metadata33 = function(k, v) {
6427
+ var __metadata34 = function(k, v) {
6015
6428
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6016
6429
  };
6017
6430
  var GOOGLE_JWKS = createRemoteJWKSet(new URL("https://www.googleapis.com/oauth2/v3/certs"));
@@ -6063,25 +6476,25 @@ var GoogleTokenVerifier = class GoogleTokenVerifier2 {
6063
6476
  return google;
6064
6477
  }
6065
6478
  };
6066
- __decorate33([
6067
- Inject17(AUTH_CONFIG),
6068
- __metadata33("design:type", Object)
6479
+ __decorate34([
6480
+ Inject18(AUTH_CONFIG),
6481
+ __metadata34("design:type", Object)
6069
6482
  ], GoogleTokenVerifier.prototype, "config", void 0);
6070
- GoogleTokenVerifier = __decorate33([
6071
- Injectable17()
6483
+ GoogleTokenVerifier = __decorate34([
6484
+ Injectable18()
6072
6485
  ], GoogleTokenVerifier);
6073
6486
 
6074
6487
  // src/oauth/google/GoogleOAuthProvider.ts
6075
- var __decorate34 = function(decorators, target, key, desc) {
6488
+ var __decorate35 = function(decorators, target, key, desc) {
6076
6489
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6077
6490
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6078
6491
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6079
6492
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6080
6493
  };
6081
- var __metadata34 = function(k, v) {
6494
+ var __metadata35 = function(k, v) {
6082
6495
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6083
6496
  };
6084
- var _a21;
6497
+ var _a22;
6085
6498
  var AUTHORIZATION_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth";
6086
6499
  var TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token";
6087
6500
  var GoogleOAuthProvider = class GoogleOAuthProvider2 {
@@ -6149,24 +6562,24 @@ var GoogleOAuthProvider = class GoogleOAuthProvider2 {
6149
6562
  return google;
6150
6563
  }
6151
6564
  };
6152
- __decorate34([
6153
- Inject18(AUTH_CONFIG),
6154
- __metadata34("design:type", Object)
6565
+ __decorate35([
6566
+ Inject19(AUTH_CONFIG),
6567
+ __metadata35("design:type", Object)
6155
6568
  ], GoogleOAuthProvider.prototype, "config", void 0);
6156
- GoogleOAuthProvider = __decorate34([
6157
- Injectable18(),
6158
- __metadata34("design:paramtypes", [typeof (_a21 = typeof GoogleTokenVerifier !== "undefined" && GoogleTokenVerifier) === "function" ? _a21 : Object])
6569
+ GoogleOAuthProvider = __decorate35([
6570
+ Injectable19(),
6571
+ __metadata35("design:paramtypes", [typeof (_a22 = typeof GoogleTokenVerifier !== "undefined" && GoogleTokenVerifier) === "function" ? _a22 : Object])
6159
6572
  ], GoogleOAuthProvider);
6160
6573
 
6161
6574
  // src/oauth/github/GitHubOAuthProvider.ts
6162
- import { Inject as Inject19, Injectable as Injectable19 } from "najm-core";
6163
- var __decorate35 = function(decorators, target, key, desc) {
6575
+ import { Inject as Inject20, Injectable as Injectable20 } from "najm-core";
6576
+ var __decorate36 = function(decorators, target, key, desc) {
6164
6577
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6165
6578
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6166
6579
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6167
6580
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6168
6581
  };
6169
- var __metadata35 = function(k, v) {
6582
+ var __metadata36 = function(k, v) {
6170
6583
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6171
6584
  };
6172
6585
  var AUTHORIZATION_ENDPOINT2 = "https://github.com/login/oauth/authorize";
@@ -6282,12 +6695,12 @@ var GitHubOAuthProvider = class GitHubOAuthProvider2 {
6282
6695
  return github;
6283
6696
  }
6284
6697
  };
6285
- __decorate35([
6286
- Inject19(AUTH_CONFIG),
6287
- __metadata35("design:type", Object)
6698
+ __decorate36([
6699
+ Inject20(AUTH_CONFIG),
6700
+ __metadata36("design:type", Object)
6288
6701
  ], GitHubOAuthProvider.prototype, "config", void 0);
6289
- GitHubOAuthProvider = __decorate35([
6290
- Injectable19()
6702
+ GitHubOAuthProvider = __decorate36([
6703
+ Injectable20()
6291
6704
  ], GitHubOAuthProvider);
6292
6705
 
6293
6706
  // src/oauth/GitHubOAuthController.ts
@@ -6296,24 +6709,24 @@ import { Controller as Controller6, Ctx as Ctx2, Get as Get5, Post as Post6, Que
6296
6709
  import { RateLimit as RateLimit3 } from "najm-rate";
6297
6710
 
6298
6711
  // src/oauth/OAuthService.ts
6299
- import { Inject as Inject22, Injectable as Injectable22, Log as Log2 } from "najm-core";
6712
+ import { Err as Err15, Inject as Inject23, Injectable as Injectable23, Log as Log2 } from "najm-core";
6300
6713
 
6301
6714
  // src/oauth/OAuthAccountService.ts
6302
6715
  import { randomBytes as randomBytes3 } from "crypto";
6303
- import { Inject as Inject21, Injectable as Injectable20 } from "najm-core";
6716
+ import { Inject as Inject22, Injectable as Injectable21 } from "najm-core";
6304
6717
  import { Transaction as Transaction5 } from "najm-database";
6305
6718
 
6306
6719
  // src/oauth/OAuthAccountRepository.ts
6307
6720
  import { and as and6, eq as eq9 } from "drizzle-orm";
6308
- import { Inject as Inject20, Repository as Repository7 } from "najm-core";
6721
+ import { Inject as Inject21, Repository as Repository7 } from "najm-core";
6309
6722
  import { DB as DB7 } from "najm-database";
6310
- var __decorate36 = function(decorators, target, key, desc) {
6723
+ var __decorate37 = function(decorators, target, key, desc) {
6311
6724
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6312
6725
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6313
6726
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6314
6727
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6315
6728
  };
6316
- var __metadata36 = function(k, v) {
6729
+ var __metadata37 = function(k, v) {
6317
6730
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6318
6731
  };
6319
6732
  var OAuthAccountRepository = class OAuthAccountRepository2 {
@@ -6341,32 +6754,32 @@ var OAuthAccountRepository = class OAuthAccountRepository2 {
6341
6754
  return account;
6342
6755
  }
6343
6756
  };
6344
- __decorate36([
6757
+ __decorate37([
6345
6758
  DB7(),
6346
- __metadata36("design:type", Object)
6759
+ __metadata37("design:type", Object)
6347
6760
  ], OAuthAccountRepository.prototype, "db", void 0);
6348
- __decorate36([
6349
- Inject20(AUTH_SCHEMA),
6350
- __metadata36("design:type", Object)
6761
+ __decorate37([
6762
+ Inject21(AUTH_SCHEMA),
6763
+ __metadata37("design:type", Object)
6351
6764
  ], OAuthAccountRepository.prototype, "schema", void 0);
6352
- OAuthAccountRepository = __decorate36([
6765
+ OAuthAccountRepository = __decorate37([
6353
6766
  Repository7()
6354
6767
  ], OAuthAccountRepository);
6355
6768
 
6356
6769
  // src/oauth/OAuthAccountService.ts
6357
- var __decorate37 = function(decorators, target, key, desc) {
6770
+ var __decorate38 = function(decorators, target, key, desc) {
6358
6771
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6359
6772
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6360
6773
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6361
6774
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6362
6775
  };
6363
- var __metadata37 = function(k, v) {
6776
+ var __metadata38 = function(k, v) {
6364
6777
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6365
6778
  };
6366
- var _a22;
6367
- var _b12;
6779
+ var _a23;
6780
+ var _b13;
6368
6781
  var _c9;
6369
- var _d7;
6782
+ var _d8;
6370
6783
  var OAuthAccountService = class OAuthAccountService2 {
6371
6784
  static {
6372
6785
  __name(this, "OAuthAccountService");
@@ -6442,42 +6855,42 @@ var OAuthAccountService = class OAuthAccountService2 {
6442
6855
  return providerConfig;
6443
6856
  }
6444
6857
  };
6445
- __decorate37([
6446
- Inject21(AUTH_CONFIG),
6447
- __metadata37("design:type", Object)
6858
+ __decorate38([
6859
+ Inject22(AUTH_CONFIG),
6860
+ __metadata38("design:type", Object)
6448
6861
  ], OAuthAccountService.prototype, "config", void 0);
6449
- __decorate37([
6862
+ __decorate38([
6450
6863
  Transaction5(),
6451
- __metadata37("design:type", Function),
6452
- __metadata37("design:paramtypes", [Object]),
6453
- __metadata37("design:returntype", typeof (_c9 = typeof Promise !== "undefined" && Promise) === "function" ? _c9 : Object)
6864
+ __metadata38("design:type", Function),
6865
+ __metadata38("design:paramtypes", [Object]),
6866
+ __metadata38("design:returntype", typeof (_c9 = typeof Promise !== "undefined" && Promise) === "function" ? _c9 : Object)
6454
6867
  ], OAuthAccountService.prototype, "resolveForLogin", null);
6455
- __decorate37([
6868
+ __decorate38([
6456
6869
  Transaction5(),
6457
- __metadata37("design:type", Function),
6458
- __metadata37("design:paramtypes", [String, Object]),
6459
- __metadata37("design:returntype", typeof (_d7 = typeof Promise !== "undefined" && Promise) === "function" ? _d7 : Object)
6870
+ __metadata38("design:type", Function),
6871
+ __metadata38("design:paramtypes", [String, Object]),
6872
+ __metadata38("design:returntype", typeof (_d8 = typeof Promise !== "undefined" && Promise) === "function" ? _d8 : Object)
6460
6873
  ], OAuthAccountService.prototype, "linkUser", null);
6461
- OAuthAccountService = __decorate37([
6462
- Injectable20(),
6463
- __metadata37("design:paramtypes", [typeof (_a22 = typeof OAuthAccountRepository !== "undefined" && OAuthAccountRepository) === "function" ? _a22 : Object, typeof (_b12 = typeof UserService !== "undefined" && UserService) === "function" ? _b12 : Object])
6874
+ OAuthAccountService = __decorate38([
6875
+ Injectable21(),
6876
+ __metadata38("design:paramtypes", [typeof (_a23 = typeof OAuthAccountRepository !== "undefined" && OAuthAccountRepository) === "function" ? _a23 : Object, typeof (_b13 = typeof UserService !== "undefined" && UserService) === "function" ? _b13 : Object])
6464
6877
  ], OAuthAccountService);
6465
6878
 
6466
6879
  // src/oauth/OAuthStateService.ts
6467
6880
  import { createHash as createHash4, randomBytes as randomBytes4, timingSafeEqual } from "crypto";
6468
- import { Injectable as Injectable21 } from "najm-core";
6881
+ import { Injectable as Injectable22 } from "najm-core";
6469
6882
  import { CookieService as CookieService3 } from "najm-cookies";
6470
- var __decorate38 = function(decorators, target, key, desc) {
6883
+ var __decorate39 = function(decorators, target, key, desc) {
6471
6884
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6472
6885
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6473
6886
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6474
6887
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6475
6888
  };
6476
- var __metadata38 = function(k, v) {
6889
+ var __metadata39 = function(k, v) {
6477
6890
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6478
6891
  };
6479
- var _a23;
6480
- var _b13;
6892
+ var _a24;
6893
+ var _b14;
6481
6894
  var ATTEMPT_TTL_MS = 10 * 60 * 1e3;
6482
6895
  var COOKIE_PREFIX = "najm.oauth.";
6483
6896
  var OAuthStateService = class OAuthStateService2 {
@@ -6566,26 +6979,26 @@ var OAuthStateService = class OAuthStateService2 {
6566
6979
  return /^[A-Za-z0-9_-]{40,128}$/.test(state);
6567
6980
  }
6568
6981
  };
6569
- OAuthStateService = __decorate38([
6570
- Injectable21(),
6571
- __metadata38("design:paramtypes", [typeof (_a23 = typeof CookieService3 !== "undefined" && CookieService3) === "function" ? _a23 : Object, typeof (_b13 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b13 : Object])
6982
+ OAuthStateService = __decorate39([
6983
+ Injectable22(),
6984
+ __metadata39("design:paramtypes", [typeof (_a24 = typeof CookieService3 !== "undefined" && CookieService3) === "function" ? _a24 : Object, typeof (_b14 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b14 : Object])
6572
6985
  ], OAuthStateService);
6573
6986
 
6574
6987
  // src/oauth/OAuthService.ts
6575
- var __decorate39 = function(decorators, target, key, desc) {
6988
+ var __decorate40 = function(decorators, target, key, desc) {
6576
6989
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6577
6990
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6578
6991
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6579
6992
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6580
6993
  };
6581
- var __metadata39 = function(k, v) {
6994
+ var __metadata40 = function(k, v) {
6582
6995
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6583
6996
  };
6584
- var _a24;
6585
- var _b14;
6997
+ var _a25;
6998
+ var _b15;
6586
6999
  var _c10;
6587
- var _d8;
6588
- var _e5;
7000
+ var _d9;
7001
+ var _e7;
6589
7002
  var _f5;
6590
7003
  var _g4;
6591
7004
  var _h3;
@@ -6631,16 +7044,47 @@ var OAuthService = class OAuthService2 {
6631
7044
  finishGitHubCallback(params) {
6632
7045
  return this.finishCallback("github", params);
6633
7046
  }
7047
+ /**
7048
+ * Turn an expected OAuth start failure into the HTTP response it describes.
7049
+ *
7050
+ * `OAuthFlowError` carries the status it means — 404 for a provider that is
7051
+ * not configured, 400 for a return path the caller chose badly — but it is a
7052
+ * plain Error, so the framework's handler could only classify it as an
7053
+ * unhandled 500. A disabled provider and a bad query string are ordinary
7054
+ * client-visible outcomes, and reporting them as server faults hides real
7055
+ * ones. Only the stable `oauth_*` code crosses the boundary; provider
7056
+ * secrets, state, and codes never appear in it.
7057
+ *
7058
+ * The callback path deliberately does not go through here: it answers with a
7059
+ * redirect carrying the same code, and that contract is unchanged.
7060
+ */
7061
+ failStart(error) {
7062
+ if (error instanceof OAuthFlowError) {
7063
+ Err15(error.oauthCode, error.status);
7064
+ }
7065
+ throw error;
7066
+ }
6634
7067
  startLogin(provider, returnTo) {
6635
- this.providerConfig(provider);
6636
- const { attempt, codeChallenge } = this.state.create({
6637
- provider,
6638
- intent: "login",
6639
- returnTo
6640
- });
6641
- return this.provider(provider).authorizationUrl(attempt, codeChallenge);
7068
+ try {
7069
+ this.providerConfig(provider);
7070
+ const { attempt, codeChallenge } = this.state.create({
7071
+ provider,
7072
+ intent: "login",
7073
+ returnTo
7074
+ });
7075
+ return this.provider(provider).authorizationUrl(attempt, codeChallenge);
7076
+ } catch (error) {
7077
+ this.failStart(error);
7078
+ }
6642
7079
  }
6643
7080
  async startLink(provider, userId, returnTo) {
7081
+ try {
7082
+ return await this.buildLinkStart(provider, userId, returnTo);
7083
+ } catch (error) {
7084
+ this.failStart(error);
7085
+ }
7086
+ }
7087
+ async buildLinkStart(provider, userId, returnTo) {
6644
7088
  this.providerConfig(provider);
6645
7089
  const user = await this.users.getById(userId);
6646
7090
  if (user.status !== "active")
@@ -6722,27 +7166,27 @@ var OAuthService = class OAuthService2 {
6722
7166
  return providerConfig;
6723
7167
  }
6724
7168
  };
6725
- __decorate39([
6726
- Inject22(AUTH_CONFIG),
6727
- __metadata39("design:type", Object)
7169
+ __decorate40([
7170
+ Inject23(AUTH_CONFIG),
7171
+ __metadata40("design:type", Object)
6728
7172
  ], OAuthService.prototype, "config", void 0);
6729
- __decorate39([
7173
+ __decorate40([
6730
7174
  Log2(),
6731
- __metadata39("design:type", Object)
7175
+ __metadata40("design:type", Object)
6732
7176
  ], OAuthService.prototype, "logger", void 0);
6733
- OAuthService = __decorate39([
6734
- Injectable22(),
6735
- __metadata39("design:paramtypes", [typeof (_a24 = typeof OAuthStateService !== "undefined" && OAuthStateService) === "function" ? _a24 : Object, typeof (_b14 = typeof GoogleOAuthProvider !== "undefined" && GoogleOAuthProvider) === "function" ? _b14 : Object, typeof (_c10 = typeof GitHubOAuthProvider !== "undefined" && GitHubOAuthProvider) === "function" ? _c10 : Object, typeof (_d8 = typeof OAuthAccountService !== "undefined" && OAuthAccountService) === "function" ? _d8 : Object, typeof (_e5 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _e5 : Object, typeof (_f5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _f5 : Object, typeof (_g4 = typeof UserService !== "undefined" && UserService) === "function" ? _g4 : Object, typeof (_h3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _h3 : Object])
7177
+ OAuthService = __decorate40([
7178
+ Injectable23(),
7179
+ __metadata40("design:paramtypes", [typeof (_a25 = typeof OAuthStateService !== "undefined" && OAuthStateService) === "function" ? _a25 : Object, typeof (_b15 = typeof GoogleOAuthProvider !== "undefined" && GoogleOAuthProvider) === "function" ? _b15 : Object, typeof (_c10 = typeof GitHubOAuthProvider !== "undefined" && GitHubOAuthProvider) === "function" ? _c10 : Object, typeof (_d9 = typeof OAuthAccountService !== "undefined" && OAuthAccountService) === "function" ? _d9 : Object, typeof (_e7 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _e7 : Object, typeof (_f5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _f5 : Object, typeof (_g4 = typeof UserService !== "undefined" && UserService) === "function" ? _g4 : Object, typeof (_h3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _h3 : Object])
6736
7180
  ], OAuthService);
6737
7181
 
6738
7182
  // src/oauth/GitHubOAuthController.ts
6739
- var __decorate40 = function(decorators, target, key, desc) {
7183
+ var __decorate41 = function(decorators, target, key, desc) {
6740
7184
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6741
7185
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6742
7186
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6743
7187
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6744
7188
  };
6745
- var __metadata40 = function(k, v) {
7189
+ var __metadata41 = function(k, v) {
6746
7190
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6747
7191
  };
6748
7192
  var __param13 = function(paramIndex, decorator) {
@@ -6750,7 +7194,7 @@ var __param13 = function(paramIndex, decorator) {
6750
7194
  decorator(target, key, paramIndex);
6751
7195
  };
6752
7196
  };
6753
- var _a25;
7197
+ var _a26;
6754
7198
  var callbackKey = /* @__PURE__ */ __name((ctx, { clientIp }) => {
6755
7199
  const state = ctx.req.query("state") ?? "none";
6756
7200
  const fingerprint = createHash5("sha256").update(state).digest("base64url").slice(0, 24);
@@ -6775,52 +7219,52 @@ var GitHubOAuthController = class GitHubOAuthController2 {
6775
7219
  return this.oauth.startGitHubLink(userId, returnTo);
6776
7220
  }
6777
7221
  };
6778
- __decorate40([
7222
+ __decorate41([
6779
7223
  Get5("/start"),
6780
7224
  RateLimit3({ limit: 20, window: "15m", key: "ip" }),
6781
7225
  __param13(0, Ctx2()),
6782
7226
  __param13(1, Query2("returnTo")),
6783
- __metadata40("design:type", Function),
6784
- __metadata40("design:paramtypes", [Object, String]),
6785
- __metadata40("design:returntype", void 0)
7227
+ __metadata41("design:type", Function),
7228
+ __metadata41("design:paramtypes", [Object, String]),
7229
+ __metadata41("design:returntype", void 0)
6786
7230
  ], GitHubOAuthController.prototype, "start", null);
6787
- __decorate40([
7231
+ __decorate41([
6788
7232
  Get5("/callback"),
6789
7233
  RateLimit3({ limit: 20, window: "15m", key: callbackKey }),
6790
7234
  __param13(0, Ctx2()),
6791
7235
  __param13(1, Query2("code")),
6792
7236
  __param13(2, Query2("state")),
6793
7237
  __param13(3, Query2("error")),
6794
- __metadata40("design:type", Function),
6795
- __metadata40("design:paramtypes", [Object, String, String, String]),
6796
- __metadata40("design:returntype", Promise)
7238
+ __metadata41("design:type", Function),
7239
+ __metadata41("design:paramtypes", [Object, String, String, String]),
7240
+ __metadata41("design:returntype", Promise)
6797
7241
  ], GitHubOAuthController.prototype, "callback", null);
6798
- __decorate40([
7242
+ __decorate41([
6799
7243
  Post6("/link"),
6800
7244
  isAuth(),
6801
7245
  RateLimit3({ limit: 10, window: "15m", key: "user" }),
6802
7246
  __param13(0, User5("id")),
6803
7247
  __param13(1, Query2("returnTo")),
6804
- __metadata40("design:type", Function),
6805
- __metadata40("design:paramtypes", [String, String]),
6806
- __metadata40("design:returntype", void 0)
7248
+ __metadata41("design:type", Function),
7249
+ __metadata41("design:paramtypes", [String, String]),
7250
+ __metadata41("design:returntype", void 0)
6807
7251
  ], GitHubOAuthController.prototype, "link", null);
6808
- GitHubOAuthController = __decorate40([
7252
+ GitHubOAuthController = __decorate41([
6809
7253
  Controller6("/auth/oauth/github"),
6810
- __metadata40("design:paramtypes", [typeof (_a25 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a25 : Object])
7254
+ __metadata41("design:paramtypes", [typeof (_a26 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a26 : Object])
6811
7255
  ], GitHubOAuthController);
6812
7256
 
6813
7257
  // src/oauth/OAuthController.ts
6814
7258
  import { createHash as createHash6 } from "crypto";
6815
7259
  import { Controller as Controller7, Ctx as Ctx3, Get as Get6, Post as Post7, Query as Query3, User as User6 } from "najm-core";
6816
7260
  import { RateLimit as RateLimit4 } from "najm-rate";
6817
- var __decorate41 = function(decorators, target, key, desc) {
7261
+ var __decorate42 = function(decorators, target, key, desc) {
6818
7262
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6819
7263
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6820
7264
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6821
7265
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6822
7266
  };
6823
- var __metadata41 = function(k, v) {
7267
+ var __metadata42 = function(k, v) {
6824
7268
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6825
7269
  };
6826
7270
  var __param14 = function(paramIndex, decorator) {
@@ -6828,7 +7272,7 @@ var __param14 = function(paramIndex, decorator) {
6828
7272
  decorator(target, key, paramIndex);
6829
7273
  };
6830
7274
  };
6831
- var _a26;
7275
+ var _a27;
6832
7276
  var callbackKey2 = /* @__PURE__ */ __name((ctx, { clientIp }) => {
6833
7277
  const ip = clientIp;
6834
7278
  const state = ctx.req.query("state") ?? "none";
@@ -6854,39 +7298,39 @@ var OAuthController = class OAuthController2 {
6854
7298
  return this.oauth.startGoogleLink(userId, returnTo);
6855
7299
  }
6856
7300
  };
6857
- __decorate41([
7301
+ __decorate42([
6858
7302
  Get6("/start"),
6859
7303
  RateLimit4({ limit: 20, window: "15m", key: "ip" }),
6860
7304
  __param14(0, Ctx3()),
6861
7305
  __param14(1, Query3("returnTo")),
6862
- __metadata41("design:type", Function),
6863
- __metadata41("design:paramtypes", [Object, String]),
6864
- __metadata41("design:returntype", void 0)
7306
+ __metadata42("design:type", Function),
7307
+ __metadata42("design:paramtypes", [Object, String]),
7308
+ __metadata42("design:returntype", void 0)
6865
7309
  ], OAuthController.prototype, "start", null);
6866
- __decorate41([
7310
+ __decorate42([
6867
7311
  Get6("/callback"),
6868
7312
  RateLimit4({ limit: 20, window: "15m", key: callbackKey2 }),
6869
7313
  __param14(0, Ctx3()),
6870
7314
  __param14(1, Query3("code")),
6871
7315
  __param14(2, Query3("state")),
6872
7316
  __param14(3, Query3("error")),
6873
- __metadata41("design:type", Function),
6874
- __metadata41("design:paramtypes", [Object, String, String, String]),
6875
- __metadata41("design:returntype", Promise)
7317
+ __metadata42("design:type", Function),
7318
+ __metadata42("design:paramtypes", [Object, String, String, String]),
7319
+ __metadata42("design:returntype", Promise)
6876
7320
  ], OAuthController.prototype, "callback", null);
6877
- __decorate41([
7321
+ __decorate42([
6878
7322
  Post7("/link"),
6879
7323
  isAuth(),
6880
7324
  RateLimit4({ limit: 10, window: "15m", key: "user" }),
6881
7325
  __param14(0, User6("id")),
6882
7326
  __param14(1, Query3("returnTo")),
6883
- __metadata41("design:type", Function),
6884
- __metadata41("design:paramtypes", [String, String]),
6885
- __metadata41("design:returntype", void 0)
7327
+ __metadata42("design:type", Function),
7328
+ __metadata42("design:paramtypes", [String, String]),
7329
+ __metadata42("design:returntype", void 0)
6886
7330
  ], OAuthController.prototype, "link", null);
6887
- OAuthController = __decorate41([
7331
+ OAuthController = __decorate42([
6888
7332
  Controller7("/auth/oauth/google"),
6889
- __metadata41("design:paramtypes", [typeof (_a26 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a26 : Object])
7333
+ __metadata42("design:paramtypes", [typeof (_a27 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a27 : Object])
6890
7334
  ], OAuthController);
6891
7335
 
6892
7336
  // src/oauth/index.ts
@@ -6915,13 +7359,13 @@ var credentialSetupChangeDto = z5.object({
6915
7359
  });
6916
7360
 
6917
7361
  // src/credentialSetup/CredentialSetupController.ts
6918
- var __decorate42 = function(decorators, target, key, desc) {
7362
+ var __decorate43 = function(decorators, target, key, desc) {
6919
7363
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6920
7364
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6921
7365
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6922
7366
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6923
7367
  };
6924
- var __metadata42 = function(k, v) {
7368
+ var __metadata43 = function(k, v) {
6925
7369
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6926
7370
  };
6927
7371
  var __param15 = function(paramIndex, decorator) {
@@ -6929,7 +7373,7 @@ var __param15 = function(paramIndex, decorator) {
6929
7373
  decorator(target, key, paramIndex);
6930
7374
  };
6931
7375
  };
6932
- var _a27;
7376
+ var _a28;
6933
7377
  var CredentialSetupController = class CredentialSetupController2 {
6934
7378
  static {
6935
7379
  __name(this, "CredentialSetupController");
@@ -6948,35 +7392,35 @@ var CredentialSetupController = class CredentialSetupController2 {
6948
7392
  return this.passwords.cancel();
6949
7393
  }
6950
7394
  };
6951
- __decorate42([
7395
+ __decorate43([
6952
7396
  Get7("/setup"),
6953
7397
  RateLimit5({ limit: 30, window: "15m", key: "ip" }),
6954
7398
  ResMsg6("auth.success.credentialSetupPending"),
6955
- __metadata42("design:type", Function),
6956
- __metadata42("design:paramtypes", []),
6957
- __metadata42("design:returntype", void 0)
7399
+ __metadata43("design:type", Function),
7400
+ __metadata43("design:paramtypes", []),
7401
+ __metadata43("design:returntype", void 0)
6958
7402
  ], CredentialSetupController.prototype, "status", null);
6959
- __decorate42([
7403
+ __decorate43([
6960
7404
  Post8("/change"),
6961
7405
  RateLimit5({ limit: 5, window: "15m", key: "ip" }),
6962
7406
  Validate6(credentialSetupChangeDto),
6963
7407
  ResMsg6("auth.success.credentialSetupPasswordReplaced"),
6964
7408
  __param15(0, Body7()),
6965
- __metadata42("design:type", Function),
6966
- __metadata42("design:paramtypes", [Object]),
6967
- __metadata42("design:returntype", void 0)
7409
+ __metadata43("design:type", Function),
7410
+ __metadata43("design:paramtypes", [Object]),
7411
+ __metadata43("design:returntype", void 0)
6968
7412
  ], CredentialSetupController.prototype, "change", null);
6969
- __decorate42([
7413
+ __decorate43([
6970
7414
  Post8("/cancel"),
6971
7415
  RateLimit5({ limit: 10, window: "15m", key: "ip" }),
6972
7416
  ResMsg6("auth.success.credentialSetupCancelled"),
6973
- __metadata42("design:type", Function),
6974
- __metadata42("design:paramtypes", []),
6975
- __metadata42("design:returntype", void 0)
7417
+ __metadata43("design:type", Function),
7418
+ __metadata43("design:paramtypes", []),
7419
+ __metadata43("design:returntype", void 0)
6976
7420
  ], CredentialSetupController.prototype, "cancel", null);
6977
- CredentialSetupController = __decorate42([
7421
+ CredentialSetupController = __decorate43([
6978
7422
  Controller8("/auth/credential-setup"),
6979
- __metadata42("design:paramtypes", [typeof (_a27 = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _a27 : Object])
7423
+ __metadata43("design:paramtypes", [typeof (_a28 = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _a28 : Object])
6980
7424
  ], CredentialSetupController);
6981
7425
 
6982
7426
  // src/credentialSetup/index.ts
@@ -7023,9 +7467,9 @@ var resolveGoogleConfig = /* @__PURE__ */ __name((config) => {
7023
7467
  const clientId = google.clientId ?? process.env.GOOGLE_CLIENT_ID ?? "";
7024
7468
  const clientSecret = google.clientSecret ?? process.env.GOOGLE_CLIENT_SECRET ?? "";
7025
7469
  if (!clientId)
7026
- throw Err15.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
7470
+ throw Err16.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
7027
7471
  if (!clientSecret)
7028
- throw Err15.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
7472
+ throw Err16.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
7029
7473
  const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
7030
7474
  const callbackUrl = google.callbackUrl ?? process.env.GOOGLE_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/google/callback`;
7031
7475
  return {
@@ -7047,9 +7491,9 @@ var resolveGitHubConfig = /* @__PURE__ */ __name((config) => {
7047
7491
  const clientId = github.clientId ?? process.env.GITHUB_CLIENT_ID ?? "";
7048
7492
  const clientSecret = github.clientSecret ?? process.env.GITHUB_CLIENT_SECRET ?? "";
7049
7493
  if (!clientId)
7050
- throw Err15.configRequired("auth.oauth.github", "GITHUB_CLIENT_ID");
7494
+ throw Err16.configRequired("auth.oauth.github", "GITHUB_CLIENT_ID");
7051
7495
  if (!clientSecret)
7052
- throw Err15.configRequired("auth.oauth.github", "GITHUB_CLIENT_SECRET");
7496
+ throw Err16.configRequired("auth.oauth.github", "GITHUB_CLIENT_SECRET");
7053
7497
  const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
7054
7498
  const callbackUrl = github.callbackUrl ?? process.env.GITHUB_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/github/callback`;
7055
7499
  return {
@@ -7117,10 +7561,10 @@ var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
7117
7561
  }
7118
7562
  };
7119
7563
  if (!finalConfig.jwt.accessSecret) {
7120
- throw Err15.configRequired("auth", "JWT_ACCESS_SECRET");
7564
+ throw Err16.configRequired("auth", "JWT_ACCESS_SECRET");
7121
7565
  }
7122
7566
  if (!finalConfig.jwt.refreshSecret) {
7123
- throw Err15.configRequired("auth", "JWT_REFRESH_SECRET");
7567
+ throw Err16.configRequired("auth", "JWT_REFRESH_SECRET");
7124
7568
  }
7125
7569
  return finalConfig;
7126
7570
  }, "resolveAuthConfig");
@@ -7338,6 +7782,7 @@ export {
7338
7782
  RoleService,
7339
7783
  RoleValidator,
7340
7784
  ScopeContext,
7785
+ SessionInvalidationService,
7341
7786
  TOKEN_STATUS,
7342
7787
  TOKEN_TYPE,
7343
7788
  TokenRepository,
@@ -7351,6 +7796,7 @@ export {
7351
7796
  assignRoleDto,
7352
7797
  assignRoleParams,
7353
7798
  auth,
7799
+ authEmailRateLimitKey,
7354
7800
  authIdentityRateLimitKey,
7355
7801
  authSchema,
7356
7802
  authSeed,