najm-auth 4.2.3 → 5.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.
@@ -228,6 +228,20 @@ var TabSync = class {
228
228
  }
229
229
  };
230
230
 
231
+ // src/client/redirectPath.ts
232
+ function normalizeLocalRedirectPath(value) {
233
+ if (typeof value !== "string" || !value.startsWith("/") || value.startsWith("//") || value.includes("\\") || /[\u0000-\u001f\u007f]/.test(value)) return null;
234
+ try {
235
+ const base = new URL("https://najm.invalid");
236
+ const parsed = new URL(value, base);
237
+ if (parsed.origin !== base.origin || parsed.pathname.startsWith("//")) return null;
238
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
239
+ } catch {
240
+ return null;
241
+ }
242
+ }
243
+ __name(normalizeLocalRedirectPath, "normalizeLocalRedirectPath");
244
+
231
245
  // src/client/NajmAuthClient.ts
232
246
  function isCredentialSetupPending(payload) {
233
247
  return typeof payload === "object" && payload !== null && payload.nextStep === "credential_setup";
@@ -702,16 +716,9 @@ var NajmAuthClient = class _NajmAuthClient {
702
716
  }
703
717
  }
704
718
  validateReturnTo(value) {
705
- const candidate = value.trim();
706
- if (!candidate.startsWith("/") || candidate.startsWith("//") || candidate.includes("\\")) {
707
- throw new Error("returnTo must be a same-origin path");
708
- }
709
- const base = new URL("https://najm.invalid");
710
- const parsed = new URL(candidate, base);
711
- if (parsed.origin !== base.origin || parsed.username || parsed.password) {
712
- throw new Error("returnTo must be a same-origin path");
713
- }
714
- return `${parsed.pathname}${parsed.search}${parsed.hash}`;
719
+ const path = normalizeLocalRedirectPath(value.trim());
720
+ if (!path) throw new Error("returnTo must be a same-origin path");
721
+ return path;
715
722
  }
716
723
  };
717
724
  function createAuthClient(config) {
@@ -771,18 +771,25 @@ __name(GitHubLoginButton, "GitHubLoginButton");
771
771
 
772
772
  // src/client/react/OAuthCallback.tsx
773
773
  import { useEffect as useEffect7 } from "react";
774
- import { Fragment as Fragment14, jsx as jsx16 } from "react/jsx-runtime";
775
- var safeReturnTo = /* @__PURE__ */ __name((value, fallback) => {
776
- const safeFallback = fallback.startsWith("/") && !fallback.startsWith("//") && !fallback.includes("\\") ? fallback : "/";
777
- if (!value || !value.startsWith("/") || value.startsWith("//") || value.includes("\\")) return safeFallback;
774
+
775
+ // src/client/redirectPath.ts
776
+ function normalizeLocalRedirectPath(value) {
777
+ if (typeof value !== "string" || !value.startsWith("/") || value.startsWith("//") || value.includes("\\") || /[\u0000-\u001f\u007f]/.test(value)) return null;
778
778
  try {
779
779
  const base = new URL("https://najm.invalid");
780
780
  const parsed = new URL(value, base);
781
- if (parsed.origin !== base.origin) return safeFallback;
781
+ if (parsed.origin !== base.origin || parsed.pathname.startsWith("//")) return null;
782
782
  return `${parsed.pathname}${parsed.search}${parsed.hash}`;
783
783
  } catch {
784
- return safeFallback;
784
+ return null;
785
785
  }
786
+ }
787
+ __name(normalizeLocalRedirectPath, "normalizeLocalRedirectPath");
788
+
789
+ // src/client/react/OAuthCallback.tsx
790
+ import { Fragment as Fragment14, jsx as jsx16 } from "react/jsx-runtime";
791
+ var safeReturnTo = /* @__PURE__ */ __name((value, fallback) => {
792
+ return normalizeLocalRedirectPath(value) ?? normalizeLocalRedirectPath(fallback) ?? "/";
786
793
  }, "safeReturnTo");
787
794
  function OAuthCallback({
788
795
  fallback = null,
@@ -957,6 +957,20 @@ var TabSync = class {
957
957
  }
958
958
  };
959
959
 
960
+ // src/client/redirectPath.ts
961
+ function normalizeLocalRedirectPath(value) {
962
+ if (typeof value !== "string" || !value.startsWith("/") || value.startsWith("//") || value.includes("\\") || /[\u0000-\u001f\u007f]/.test(value)) return null;
963
+ try {
964
+ const base = new URL("https://najm.invalid");
965
+ const parsed = new URL(value, base);
966
+ if (parsed.origin !== base.origin || parsed.pathname.startsWith("//")) return null;
967
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
968
+ } catch {
969
+ return null;
970
+ }
971
+ }
972
+ __name(normalizeLocalRedirectPath, "normalizeLocalRedirectPath");
973
+
960
974
  // src/client/NajmAuthClient.ts
961
975
  function isCredentialSetupPending(payload) {
962
976
  return typeof payload === "object" && payload !== null && payload.nextStep === "credential_setup";
@@ -1431,16 +1445,9 @@ var NajmAuthClient = class _NajmAuthClient {
1431
1445
  }
1432
1446
  }
1433
1447
  validateReturnTo(value) {
1434
- const candidate = value.trim();
1435
- if (!candidate.startsWith("/") || candidate.startsWith("//") || candidate.includes("\\")) {
1436
- throw new Error("returnTo must be a same-origin path");
1437
- }
1438
- const base = new URL("https://najm.invalid");
1439
- const parsed = new URL(candidate, base);
1440
- if (parsed.origin !== base.origin || parsed.username || parsed.password) {
1441
- throw new Error("returnTo must be a same-origin path");
1442
- }
1443
- return `${parsed.pathname}${parsed.search}${parsed.hash}`;
1448
+ const path = normalizeLocalRedirectPath(value.trim());
1449
+ if (!path) throw new Error("returnTo must be a same-origin path");
1450
+ return path;
1444
1451
  }
1445
1452
  };
1446
1453
  function createAuthClient(config) {
@@ -1800,13 +1807,9 @@ function getSafeRedirectPath(value, options = {}) {
1800
1807
  fallback = "/dashboard",
1801
1808
  blockedPrefixes = DEFAULT_BLOCKED_PREFIXES
1802
1809
  } = typeof options === "string" ? { fallback: options } : options;
1803
- const path = Array.isArray(value) ? value[0] : value;
1804
- if (!path || !path.startsWith("/") || // Protocol-relative: the browser treats `//host/x` as off-site.
1805
- path.startsWith("//") || // A backslash is normalized to a forward slash by some browsers, so
1806
- // `/\evil.test` is another way to spell the case above.
1807
- path.startsWith("/\\") || blockedPrefixes.some((prefix) => path.startsWith(prefix)) || ASSET_EXTENSIONS.test(path.split("?")[0] ?? path)) {
1808
- return fallback;
1809
- }
1810
+ const path = normalizeLocalRedirectPath(Array.isArray(value) ? value[0] : value);
1811
+ const pathname = path?.split(/[?#]/)[0] ?? "";
1812
+ if (!path || blockedPrefixes.some((prefix) => pathname.startsWith(prefix)) || ASSET_EXTENSIONS.test(pathname)) return fallback;
1810
1813
  return path;
1811
1814
  }
1812
1815
  __name(getSafeRedirectPath, "getSafeRedirectPath");
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import { R as ResolvedIdentityConfig, I as IdentityConfig, T as TemporaryCredent
8
8
  export { D as DEFAULT_IDENTITY_PRESET, E as EXACT_TEMPORARY_CREDENTIAL_KIND, a as IDENTITY_PRESETS, b as IdentityNormalizer, c as IdentityPreset, d as IdentityPresetName, M as MOROCCAN_CIN_TEMPORARY_CREDENTIAL_KIND, e as TemporaryCredential, f as TemporaryCredentialKind, g as compactPhone, i as isMoroccanCin, h as isTemporaryCredentialKind, m as moroccanCinTemporaryCredential, j as moroccoIdentityPreset, n as normalizeMoroccanCin, k as normalizeMoroccanPhone, l as normalizeTunisianPhone, r as resolveTemporaryCredentialKind, t as toTemporaryCredential, o as tunisiaIdentityPreset } from './ma-Cu6xUMez.js';
9
9
  import { ZodType, z } from 'zod';
10
10
  import { I18nService } from 'najm-i18n';
11
- import { TDb, SeedEntry } from 'najm-database';
11
+ import { TDb, TransactionService, SeedEntry } from 'najm-database';
12
12
  import { User, NewUser, RoleEntity, NewRoleEntity, Permission, NewPermission, RolePermission } from './schema/pg.js';
13
13
  export { CredentialSetupRequirement, CredentialSetupSession, NewCredentialSetupRequirement, NewCredentialSetupSession, NewOAuthAccount, NewRolePermission, NewToken, OAuthAccount, Token, authSchema, baseFields, credentialSetupRequirementsTable, credentialSetupSessionsTable, oauthAccountsTable, permissionsTable, rolePermissionsTable, rolesTable, tokenStatusEnum, tokenTypeEnum, tokensTable, userStatusEnum, usersTable } from './schema/pg.js';
14
14
  import { CookieService } from 'najm-cookies';
@@ -61,6 +61,7 @@ interface CredentialSetupPasswordOptions {
61
61
  * Replacement-password schema. Default: 8–72 bytes with at least one letter
62
62
  * and one digit — deliberately case-agnostic, because a first-login
63
63
  * replacement is typed by someone who just proved they own the account.
64
+ * Every policy is still subject to the 1-72 UTF-8 byte limit for bcrypt.
64
65
  */
65
66
  passwordSchema?: ZodType<string>;
66
67
  /** Setup-session lifetime in milliseconds (default: 10 minutes). */
@@ -717,6 +718,8 @@ declare class CookieManager {
717
718
  clearSessionCookie(): void;
718
719
  }
719
720
 
721
+ type CredentialState = Pick<User, 'id' | 'password' | 'email' | 'status' | 'emailVerified'>;
722
+
720
723
  interface UserWithPermissions extends Omit<User, 'password'> {
721
724
  role?: string | null;
722
725
  permissions: string[];
@@ -747,6 +750,8 @@ declare class UserRepository {
747
750
  */
748
751
  getIdsByRole(roleId: string): Promise<string[]>;
749
752
  update(id: string, data: Partial<NewUser>): Promise<User | undefined>;
753
+ /** The credential that authorized a delayed write must still own the account. */
754
+ updateWithCredential(id: string, data: Partial<NewUser>, expected: CredentialState): Promise<User | undefined>;
750
755
  updateLastLogin(id: string): Promise<User>;
751
756
  incrementFailedAttempts(id: string): Promise<User>;
752
757
  resetFailedAttempts(id: string): Promise<User>;
@@ -777,6 +782,9 @@ declare class UserValidator {
777
782
  * Check that a normalized phone number is not already taken.
778
783
  */
779
784
  checkPhoneUnique(phone: string, excludeId?: string): Promise<void>;
785
+ /** The database remains authoritative when two validation reads both pass. */
786
+ writeUnique<T>(write: () => Promise<T>): Promise<T>;
787
+ checkCredentialUnchanged(updated: unknown): void;
780
788
  /**
781
789
  * Check if user exists by ID
782
790
  */
@@ -919,78 +927,12 @@ declare class RoleValidator {
919
927
  isRoleNameExists(roleName: string): Promise<boolean>;
920
928
  }
921
929
 
922
- declare class RoleService {
923
- private roleRepository;
924
- private roleValidator;
925
- private t;
926
- constructor(roleRepository: RoleRepository, roleValidator: RoleValidator);
927
- getAll(): Promise<{
928
- id: string;
929
- name: string;
930
- description: string;
931
- createdAt: string;
932
- updatedAt: string;
933
- }[]>;
934
- getById(id: any): Promise<{
935
- id: string;
936
- name: string;
937
- description: string;
938
- createdAt: string;
939
- updatedAt: string;
940
- }>;
941
- getByName(name: any): Promise<{
942
- id: string;
943
- name: string;
944
- description: string;
945
- createdAt: string;
946
- updatedAt: string;
947
- }>;
948
- create(data: any): Promise<{
949
- id: string;
950
- name: string;
951
- description: string;
952
- createdAt: string;
953
- updatedAt: string;
954
- }>;
955
- update(id: string, data: {
956
- name?: string;
957
- description?: string;
958
- }): Promise<{
959
- id: string;
960
- name: string;
961
- description: string;
962
- createdAt: string;
963
- updatedAt: string;
964
- }>;
965
- delete(id: string): Promise<{
966
- id: string;
967
- name: string;
968
- description: string;
969
- createdAt: string;
970
- updatedAt: string;
971
- }>;
972
- seedDefaultRoles(defaultRoles: any): Promise<{
973
- id: string;
974
- name: string;
975
- description: string;
976
- createdAt: string;
977
- updatedAt: string;
978
- }[]>;
979
- getRoleIdByName(name: any): Promise<string>;
980
- /**
981
- * checkNameUnique() reads before it writes, so two concurrent requests can
982
- * both pass it and race to insert the same name. The database rejects the
983
- * loser; answer it with the same 409 the validator would have given rather
984
- * than leaking a raw driver error as a 500.
985
- */
986
- private onDuplicateName;
987
- }
988
-
989
930
  declare class TokenRepository {
990
931
  db: TDb;
991
932
  private schema;
992
933
  private get tokens();
993
934
  private get users();
935
+ getCredentialState(userId: string): Promise<any>;
994
936
  /** Shared query helper, scoped to the current database/transaction identity. */
995
937
  private queryHelper?;
996
938
  private get q();
@@ -1073,8 +1015,9 @@ declare class TokenRepository {
1073
1015
  declare class SessionInvalidationService {
1074
1016
  private cache;
1075
1017
  private tokens;
1018
+ private transactions?;
1076
1019
  private config;
1077
- constructor(cache: CacheService, tokens: TokenRepository);
1020
+ constructor(cache: CacheService, tokens: TokenRepository, transactions?: TransactionService);
1078
1021
  /**
1079
1022
  * Fields whose change ends existing sessions. Everything absent from this set
1080
1023
  * — display name, avatar, language — is a profile edit and must leave the
@@ -1117,17 +1060,20 @@ declare class SessionInvalidationService {
1117
1060
  * the same version and write the same successor back.
1118
1061
  */
1119
1062
  invalidateAccessTokens(userId: string): Promise<number>;
1063
+ private invalidateAccessTokensNow;
1120
1064
  dropUserCache(userId: string): Promise<void>;
1121
1065
  /**
1122
1066
  * End every session a user holds: access tokens by version, refresh sessions
1123
1067
  * by row, and each family's liveness marker.
1124
1068
  *
1125
- * Callers run this AFTER their database mutation has committed. Running it
1126
- * before would leave a window in which a concurrent login re-established a
1127
- * session against the state the mutation was about to remove; running it
1128
- * after a rollback merely signs the user out again, which is safe.
1069
+ * Repeat invalidation when a caller-owned transaction completes. Readers can
1070
+ * recover from the previous committed state before commit, or from transient
1071
+ * state on a shared connection before rollback. Neither snapshot may survive.
1129
1072
  */
1130
1073
  invalidateUser(userId: string): Promise<void>;
1074
+ revokeAllForUser(userId: string): Promise<any>;
1075
+ private afterTransaction;
1076
+ private revokeAllForUserNow;
1131
1077
  /**
1132
1078
  * Record that a family is live, and whose it is. Called wherever the family's
1133
1079
  * refresh row is written.
@@ -1177,6 +1123,75 @@ declare class SessionInvalidationService {
1177
1123
  isFamilyRevoked(tokenFamily: string): Promise<boolean>;
1178
1124
  }
1179
1125
 
1126
+ declare class RoleService {
1127
+ private roleRepository;
1128
+ private roleValidator;
1129
+ private userRepository?;
1130
+ private sessionInvalidation?;
1131
+ private t;
1132
+ constructor(roleRepository: RoleRepository, roleValidator: RoleValidator, userRepository?: UserRepository, sessionInvalidation?: SessionInvalidationService);
1133
+ getAll(): Promise<{
1134
+ id: string;
1135
+ name: string;
1136
+ description: string;
1137
+ createdAt: string;
1138
+ updatedAt: string;
1139
+ }[]>;
1140
+ getById(id: any): Promise<{
1141
+ id: string;
1142
+ name: string;
1143
+ description: string;
1144
+ createdAt: string;
1145
+ updatedAt: string;
1146
+ }>;
1147
+ getByName(name: any): Promise<{
1148
+ id: string;
1149
+ name: string;
1150
+ description: string;
1151
+ createdAt: string;
1152
+ updatedAt: string;
1153
+ }>;
1154
+ create(data: any): Promise<{
1155
+ id: string;
1156
+ name: string;
1157
+ description: string;
1158
+ createdAt: string;
1159
+ updatedAt: string;
1160
+ }>;
1161
+ update(id: string, data: {
1162
+ name?: string;
1163
+ description?: string;
1164
+ }): Promise<{
1165
+ id: string;
1166
+ name: string;
1167
+ description: string;
1168
+ createdAt: string;
1169
+ updatedAt: string;
1170
+ }>;
1171
+ delete(id: string): Promise<{
1172
+ id: string;
1173
+ name: string;
1174
+ description: string;
1175
+ createdAt: string;
1176
+ updatedAt: string;
1177
+ }>;
1178
+ seedDefaultRoles(defaultRoles: any): Promise<{
1179
+ id: string;
1180
+ name: string;
1181
+ description: string;
1182
+ createdAt: string;
1183
+ updatedAt: string;
1184
+ }[]>;
1185
+ getRoleIdByName(name: any): Promise<string>;
1186
+ /**
1187
+ * checkNameUnique() reads before it writes, so two concurrent requests can
1188
+ * both pass it and race to insert the same name. The database rejects the
1189
+ * loser; answer it with the same 409 the validator would have given rather
1190
+ * than leaking a raw driver error as a 500.
1191
+ */
1192
+ private onDuplicateName;
1193
+ }
1194
+
1180
1195
  type SanitizedUser = Omit<User, 'password' | 'failedLoginAttempts' | 'lockoutUntil'> & {
1181
1196
  role?: string | null;
1182
1197
  permissions?: string[];
@@ -1235,6 +1250,7 @@ declare class UserService {
1235
1250
  */
1236
1251
  update(id: string, data: Record<string, any>, options?: {
1237
1252
  validatePasswordStrength?: boolean;
1253
+ expectedCredential?: CredentialState;
1238
1254
  }): Promise<SanitizedUser>;
1239
1255
  delete(id: string): Promise<SanitizedUser>;
1240
1256
  deleteAll(): Promise<SanitizedUser[]>;
@@ -1270,6 +1286,7 @@ type SetPasswordTokenType = 'reset' | 'invite';
1270
1286
  interface ConsumedSetPasswordToken {
1271
1287
  userId: string;
1272
1288
  type: SetPasswordTokenType;
1289
+ credentialState: string;
1273
1290
  }
1274
1291
  /**
1275
1292
  * A freshly minted one-time set-password token. `jti` identifies this exact
@@ -1422,7 +1439,7 @@ declare class TokenService {
1422
1439
  tokenFamily?: string;
1423
1440
  }): string;
1424
1441
  private createTokenPair;
1425
- generateTokens(userId: string, tokenFamily?: string): Promise<{
1442
+ generateTokens(userId: string, tokenFamily?: string, capturedVersion?: number): Promise<{
1426
1443
  userId: string;
1427
1444
  tokenFamily: string;
1428
1445
  roles: string[];
@@ -1433,6 +1450,7 @@ declare class TokenService {
1433
1450
  accessTokenExpiresAt: number;
1434
1451
  refreshTokenExpiresAt: number;
1435
1452
  }>;
1453
+ private assertSessionVersion;
1436
1454
  /**
1437
1455
  * Blacklist an access token by its jti
1438
1456
  * Token will be rejected until it naturally expires
@@ -1533,13 +1551,13 @@ declare class TokenService {
1533
1551
  * Generate secure password reset token
1534
1552
  * Returns both the plain token (to send via email) and userId for identification
1535
1553
  */
1536
- generateResetToken(userId: string): Promise<SetPasswordToken>;
1554
+ generateResetToken(userId: string, expectedEmail?: string): Promise<SetPasswordToken>;
1537
1555
  /**
1538
1556
  * Generate secure account-invite token.
1539
1557
  * Longer expiry (3d) than reset because an invited user may not check
1540
1558
  * their email immediately. Consumed via the same reset-password endpoint.
1541
1559
  */
1542
- generateInviteToken(userId: string): Promise<SetPasswordToken>;
1560
+ generateInviteToken(userId: string, expectedEmail?: string): Promise<SetPasswordToken>;
1543
1561
  /**
1544
1562
  * Discard a set-password token this process just minted, identified by the
1545
1563
  * `jti` its generator returned. For the caller whose email send failed:
@@ -1728,8 +1746,10 @@ declare class CredentialSetupService {
1728
1746
  private readonly tokens;
1729
1747
  private readonly authCookies;
1730
1748
  private readonly cookies;
1749
+ private readonly users;
1731
1750
  private t?;
1732
- constructor(repository: CredentialSetupRepository, tokens: TokenService, authCookies: CookieManager, cookies: CookieService);
1751
+ private config;
1752
+ constructor(repository: CredentialSetupRepository, tokens: TokenService, authCookies: CookieManager, cookies: CookieService, users: UserRepository);
1733
1753
  /**
1734
1754
  * Revoke normal auth sessions and issue a single-purpose, short-lived,
1735
1755
  * browser-session cookie. No access or refresh token is minted.
@@ -1743,6 +1763,7 @@ declare class CredentialSetupService {
1743
1763
  * fails, consumption rolls back and the browser may safely retry.
1744
1764
  */
1745
1765
  consume<T>(options: CredentialSetupOptions, complete: (session: CredentialSetupSessionInfo) => Promise<T> | T): Promise<T>;
1766
+ private requireCurrentCredential;
1746
1767
  cancel(options: CredentialSetupOptions): Promise<{
1747
1768
  cancelled: true;
1748
1769
  }>;
@@ -2272,6 +2293,22 @@ declare class PermissionRepository {
2272
2293
  delete(id: string): Promise<Permission>;
2273
2294
  getPermissionsByRole(roleId: string): Promise<Array<Pick<Permission, 'id' | 'name' | 'description' | 'resource' | 'action'>>>;
2274
2295
  getRolesByPermission(permissionId: string): Promise<Array<Pick<RoleEntity, 'id' | 'name' | 'description'>>>;
2296
+ /**
2297
+ * Capture grants and mutate their parent in one database transaction. A
2298
+ * PostgreSQL parent-row lock conflicts with the FK check of a concurrent
2299
+ * grant. SQLite executes the whole callback synchronously under its write
2300
+ * lock; an async callback would commit before its awaited queries finish.
2301
+ */
2302
+ private mutateWithRoles;
2303
+ updateWithRoles(id: string, data: Partial<NewPermission>): Promise<{
2304
+ permission: any;
2305
+ roleIds: any;
2306
+ }>;
2307
+ deleteWithRoles(id: string): Promise<{
2308
+ permission: any;
2309
+ roleIds: any;
2310
+ }>;
2311
+ deleteAllWithRoles(): Promise<any>;
2275
2312
  assignPermissionToRole(roleId: string, permissionId: string): Promise<RolePermission>;
2276
2313
  removePermissionFromRole(roleId: string, permissionId: string): Promise<RolePermission>;
2277
2314
  checkRoleHasPermission(roleId: string, permissionId: string): Promise<boolean>;
@@ -2529,24 +2566,8 @@ declare class PermissionService {
2529
2566
  resource: string;
2530
2567
  action: string;
2531
2568
  }>;
2532
- update(id: string, data: any): Promise<{
2533
- id: string;
2534
- name: string;
2535
- description: string;
2536
- createdAt: string;
2537
- updatedAt: string;
2538
- resource: string;
2539
- action: string;
2540
- }>;
2541
- delete(id: string): Promise<{
2542
- id: string;
2543
- name: string;
2544
- description: string;
2545
- createdAt: string;
2546
- updatedAt: string;
2547
- resource: string;
2548
- action: string;
2549
- }>;
2569
+ update(id: string, data: any): Promise<any>;
2570
+ delete(id: string): Promise<any>;
2550
2571
  getPermissionsByRole(roleId: string): Promise<Pick<{
2551
2572
  id: string;
2552
2573
  name: string;
@@ -2581,15 +2602,7 @@ declare class PermissionService {
2581
2602
  assigned: any[];
2582
2603
  skipped: any[];
2583
2604
  }>;
2584
- deleteAll(): Promise<{
2585
- id: string;
2586
- name: string;
2587
- description: string;
2588
- createdAt: string;
2589
- updatedAt: string;
2590
- resource: string;
2591
- action: string;
2592
- }[]>;
2605
+ deleteAll(): Promise<any>;
2593
2606
  }
2594
2607
 
2595
2608
  declare const createPermissionDto: z.ZodObject<{
@@ -2652,24 +2665,8 @@ declare class PermissionController {
2652
2665
  resource: string;
2653
2666
  action: string;
2654
2667
  }>;
2655
- update(params: PermissionIdParam, body: UpdatePermissionDto): Promise<{
2656
- id: string;
2657
- name: string;
2658
- description: string;
2659
- createdAt: string;
2660
- updatedAt: string;
2661
- resource: string;
2662
- action: string;
2663
- }>;
2664
- delete(params: PermissionIdParam): Promise<{
2665
- id: string;
2666
- name: string;
2667
- description: string;
2668
- createdAt: string;
2669
- updatedAt: string;
2670
- resource: string;
2671
- action: string;
2672
- }>;
2668
+ update(params: PermissionIdParam, body: UpdatePermissionDto): Promise<any>;
2669
+ delete(params: PermissionIdParam): Promise<any>;
2673
2670
  getByRole(params: RoleIdParam): Promise<Pick<{
2674
2671
  id: string;
2675
2672
  name: string;
@@ -2696,15 +2693,7 @@ declare class PermissionController {
2696
2693
  roleId: string;
2697
2694
  permissionId: string;
2698
2695
  }>;
2699
- deleteAll(): Promise<{
2700
- id: string;
2701
- name: string;
2702
- description: string;
2703
- createdAt: string;
2704
- updatedAt: string;
2705
- resource: string;
2706
- action: string;
2707
- }[]>;
2696
+ deleteAll(): Promise<any>;
2708
2697
  }
2709
2698
 
2710
2699
  interface JoinStep {
@@ -3210,6 +3199,7 @@ declare const authSeed: (config: AuthSeedConfig) => Record<string, SeedEntry>;
3210
3199
  /**
3211
3200
  * Standalone function to seed authentication data.
3212
3201
  * Handles Server setup, seeding, and cleanup automatically.
3202
+ * The caller retains ownership of db; stopping the temporary server leaves it open.
3213
3203
  *
3214
3204
  * @example
3215
3205
  * ```typescript