@spfn/auth 0.2.0-beta.23 → 0.2.0-beta.25

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.
@@ -541,7 +541,7 @@ declare const mainAuthRouter: _spfn_core_route.Router<{
541
541
  id: number;
542
542
  name: string;
543
543
  displayName: string;
544
- category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
544
+ category: "custom" | "user" | "auth" | "rbac" | "system" | undefined;
545
545
  }[];
546
546
  userId: number;
547
547
  email: string | null;
@@ -799,6 +799,7 @@ interface AuthContext {
799
799
  user: User;
800
800
  userId: string;
801
801
  keyId: string;
802
+ role: string | null;
802
803
  }
803
804
  declare module 'hono' {
804
805
  interface ContextVariableMap {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _spfn_core_nextjs from '@spfn/core/nextjs';
2
- import { R as RoleConfig, P as PermissionConfig, C as CheckAccountExistsResult, S as SendVerificationCodeResult, a as RegisterResult, L as LoginResult, b as RotateKeyResult, O as OAuthStartResult, U as UserProfile, c as ProfileInfo, m as mainAuthRouter } from './authenticate-BmzJ6hTF.js';
3
- export { k as AuthInitOptions, A as AuthSession, I as INVITATION_STATUSES, n as InvitationStatus, K as KEY_ALGORITHM, l as KeyAlgorithmType, i as PERMISSION_CATEGORIES, j as PermissionCategory, e as SOCIAL_PROVIDERS, p as SocialProvider, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, f as VerificationPurpose, V as VerificationTargetType } from './authenticate-BmzJ6hTF.js';
2
+ import { R as RoleConfig, P as PermissionConfig, C as CheckAccountExistsResult, S as SendVerificationCodeResult, a as RegisterResult, L as LoginResult, b as RotateKeyResult, O as OAuthStartResult, U as UserProfile, c as ProfileInfo, m as mainAuthRouter } from './authenticate-DAAEfzxa.js';
3
+ export { k as AuthInitOptions, A as AuthSession, I as INVITATION_STATUSES, n as InvitationStatus, K as KEY_ALGORITHM, l as KeyAlgorithmType, i as PERMISSION_CATEGORIES, j as PermissionCategory, e as SOCIAL_PROVIDERS, p as SocialProvider, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, f as VerificationPurpose, V as VerificationTargetType } from './authenticate-DAAEfzxa.js';
4
4
  import * as _spfn_core_route from '@spfn/core/route';
5
5
  import { HttpMethod } from '@spfn/core/route';
6
6
  import * as _sinclair_typebox from '@sinclair/typebox';
@@ -168,7 +168,7 @@ declare const authApi: _spfn_core_nextjs.Client<_spfn_core_route.Router<{
168
168
  id: number;
169
169
  name: string;
170
170
  displayName: string;
171
- category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
171
+ category: "custom" | "user" | "auth" | "rbac" | "system" | undefined;
172
172
  }[];
173
173
  userId: number;
174
174
  email: string | null;
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { k as AuthInitOptions, l as KeyAlgorithmType, n as InvitationStatus, f as VerificationPurpose, j as PermissionCategory, p as SocialProvider, q as AuthContext } from './authenticate-BmzJ6hTF.js';
2
- export { B as ChangePasswordParams, w as CheckAccountExistsParams, C as CheckAccountExistsResult, a5 as EmailSchema, I as INVITATION_STATUSES, K as KEY_ALGORITHM, y as LoginParams, L as LoginResult, z as LogoutParams, a2 as OAuthCallbackParams, a3 as OAuthCallbackResult, a1 as OAuthStartParams, O as OAuthStartResult, a7 as PasswordSchema, a6 as PhoneSchema, x as RegisterParams, Q as RegisterPublicKeyParams, a as RegisterResult, W as RevokeKeyParams, T as RotateKeyParams, b as RotateKeyResult, e as SOCIAL_PROVIDERS, F as SendVerificationCodeParams, S as SendVerificationCodeResult, a8 as TargetTypeSchema, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, a9 as VerificationPurposeSchema, V as VerificationTargetType, G as VerifyCodeParams, H as VerifyCodeResult, m as authRouter, a4 as authenticate, Z as buildOAuthErrorUrl, v as changePasswordService, r as checkAccountExistsService, $ as getEnabledOAuthProviders, a0 as getGoogleAccessToken, _ as isOAuthProviderEnabled, t as loginService, u as logoutService, Y as oauthCallbackService, X as oauthStartService, J as registerPublicKeyService, s as registerService, N as revokeKeyService, M as rotateKeyService, D as sendVerificationCodeService, E as verifyCodeService } from './authenticate-BmzJ6hTF.js';
1
+ import { k as AuthInitOptions, l as KeyAlgorithmType, n as InvitationStatus, f as VerificationPurpose, j as PermissionCategory, p as SocialProvider, q as AuthContext } from './authenticate-DAAEfzxa.js';
2
+ export { B as ChangePasswordParams, w as CheckAccountExistsParams, C as CheckAccountExistsResult, a5 as EmailSchema, I as INVITATION_STATUSES, K as KEY_ALGORITHM, y as LoginParams, L as LoginResult, z as LogoutParams, a2 as OAuthCallbackParams, a3 as OAuthCallbackResult, a1 as OAuthStartParams, O as OAuthStartResult, a7 as PasswordSchema, a6 as PhoneSchema, x as RegisterParams, Q as RegisterPublicKeyParams, a as RegisterResult, W as RevokeKeyParams, T as RotateKeyParams, b as RotateKeyResult, e as SOCIAL_PROVIDERS, F as SendVerificationCodeParams, S as SendVerificationCodeResult, a8 as TargetTypeSchema, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, a9 as VerificationPurposeSchema, V as VerificationTargetType, G as VerifyCodeParams, H as VerifyCodeResult, m as authRouter, a4 as authenticate, Z as buildOAuthErrorUrl, v as changePasswordService, r as checkAccountExistsService, $ as getEnabledOAuthProviders, a0 as getGoogleAccessToken, _ as isOAuthProviderEnabled, t as loginService, u as logoutService, Y as oauthCallbackService, X as oauthStartService, J as registerPublicKeyService, s as registerService, N as revokeKeyService, M as rotateKeyService, D as sendVerificationCodeService, E as verifyCodeService } from './authenticate-DAAEfzxa.js';
3
3
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
4
4
  import { UserProfile as UserProfile$1, ProfileInfo } from '@spfn/auth';
5
5
  import { BaseRepository } from '@spfn/core/db';
@@ -1256,7 +1256,7 @@ declare function getAuthSessionService(userId: string | number | bigint): Promis
1256
1256
  id: number;
1257
1257
  name: string;
1258
1258
  displayName: string;
1259
- category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
1259
+ category: "custom" | "user" | "auth" | "rbac" | "system" | undefined;
1260
1260
  }[];
1261
1261
  userId: number;
1262
1262
  email: string | null;
@@ -2385,7 +2385,7 @@ declare const permissions: drizzle_orm_pg_core.PgTableWithColumns<{
2385
2385
  tableName: "permissions";
2386
2386
  dataType: "string";
2387
2387
  columnType: "PgText";
2388
- data: "auth" | "custom" | "user" | "rbac" | "system";
2388
+ data: "custom" | "user" | "auth" | "rbac" | "system";
2389
2389
  driverParam: string;
2390
2390
  notNull: false;
2391
2391
  hasDefault: false;
@@ -2827,6 +2827,33 @@ declare class UsersRepository extends BaseRepository {
2827
2827
  phoneVerifiedAt: Date | null;
2828
2828
  lastLoginAt: Date | null;
2829
2829
  } | null>;
2830
+ /**
2831
+ * ID로 사용자 + Role 조회 (leftJoin)
2832
+ * Read replica 사용
2833
+ *
2834
+ * roleId가 null인 유저는 role: null 반환
2835
+ */
2836
+ findByIdWithRole(id: number): Promise<{
2837
+ user: {
2838
+ createdAt: Date;
2839
+ updatedAt: Date;
2840
+ id: number;
2841
+ email: string | null;
2842
+ phone: string | null;
2843
+ passwordHash: string | null;
2844
+ passwordChangeRequired: boolean;
2845
+ roleId: number;
2846
+ status: "active" | "inactive" | "suspended";
2847
+ emailVerifiedAt: Date | null;
2848
+ phoneVerifiedAt: Date | null;
2849
+ lastLoginAt: Date | null;
2850
+ };
2851
+ role: {
2852
+ name: string;
2853
+ displayName: string;
2854
+ priority: number;
2855
+ } | null;
2856
+ } | null>;
2830
2857
  /**
2831
2858
  * 사용자 생성
2832
2859
  * Write primary 사용
@@ -2834,13 +2861,13 @@ declare class UsersRepository extends BaseRepository {
2834
2861
  create(data: NewUser): Promise<{
2835
2862
  email: string | null;
2836
2863
  phone: string | null;
2864
+ status: "active" | "inactive" | "suspended";
2837
2865
  id: number;
2866
+ createdAt: Date;
2867
+ updatedAt: Date;
2838
2868
  passwordHash: string | null;
2839
2869
  passwordChangeRequired: boolean;
2840
2870
  roleId: number;
2841
- createdAt: Date;
2842
- updatedAt: Date;
2843
- status: "active" | "inactive" | "suspended";
2844
2871
  emailVerifiedAt: Date | null;
2845
2872
  phoneVerifiedAt: Date | null;
2846
2873
  lastLoginAt: Date | null;
@@ -2906,13 +2933,13 @@ declare class UsersRepository extends BaseRepository {
2906
2933
  deleteById(id: number): Promise<{
2907
2934
  email: string | null;
2908
2935
  phone: string | null;
2936
+ status: "active" | "inactive" | "suspended";
2909
2937
  id: number;
2938
+ createdAt: Date;
2939
+ updatedAt: Date;
2910
2940
  passwordHash: string | null;
2911
2941
  passwordChangeRequired: boolean;
2912
2942
  roleId: number;
2913
- createdAt: Date;
2914
- updatedAt: Date;
2915
- status: "active" | "inactive" | "suspended";
2916
2943
  emailVerifiedAt: Date | null;
2917
2944
  phoneVerifiedAt: Date | null;
2918
2945
  lastLoginAt: Date | null;
@@ -2935,7 +2962,7 @@ declare class UsersRepository extends BaseRepository {
2935
2962
  id: number;
2936
2963
  name: string;
2937
2964
  displayName: string;
2938
- category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
2965
+ category: "custom" | "user" | "auth" | "rbac" | "system" | undefined;
2939
2966
  }[];
2940
2967
  }>;
2941
2968
  /**
@@ -3045,16 +3072,16 @@ declare class KeysRepository extends BaseRepository {
3045
3072
  * Write primary 사용
3046
3073
  */
3047
3074
  create(data: NewUserPublicKey): Promise<{
3048
- publicKey: string;
3049
- keyId: string;
3050
- fingerprint: string;
3051
- algorithm: "ES256" | "RS256";
3052
3075
  userId: number;
3076
+ keyId: string;
3053
3077
  id: number;
3054
3078
  isActive: boolean;
3055
3079
  createdAt: Date;
3056
- expiresAt: Date | null;
3080
+ publicKey: string;
3081
+ algorithm: "ES256" | "RS256";
3082
+ fingerprint: string;
3057
3083
  lastUsedAt: Date | null;
3084
+ expiresAt: Date | null;
3058
3085
  revokedAt: Date | null;
3059
3086
  revokedReason: string | null;
3060
3087
  }>;
@@ -3081,16 +3108,16 @@ declare class KeysRepository extends BaseRepository {
3081
3108
  * Write primary 사용
3082
3109
  */
3083
3110
  deleteByKeyIdAndUserId(keyId: string, userId: number): Promise<{
3084
- publicKey: string;
3085
- keyId: string;
3086
- fingerprint: string;
3087
- algorithm: "ES256" | "RS256";
3088
3111
  userId: number;
3112
+ keyId: string;
3089
3113
  id: number;
3090
3114
  isActive: boolean;
3091
3115
  createdAt: Date;
3092
- expiresAt: Date | null;
3116
+ publicKey: string;
3117
+ algorithm: "ES256" | "RS256";
3118
+ fingerprint: string;
3093
3119
  lastUsedAt: Date | null;
3120
+ expiresAt: Date | null;
3094
3121
  revokedAt: Date | null;
3095
3122
  revokedReason: string | null;
3096
3123
  }>;
@@ -3205,14 +3232,14 @@ declare class VerificationCodesRepository extends BaseRepository {
3205
3232
  * Write primary 사용
3206
3233
  */
3207
3234
  create(data: NewVerificationCode): Promise<{
3208
- target: string;
3209
- targetType: "email" | "phone";
3210
- purpose: "registration" | "login" | "password_reset" | "email_change" | "phone_change";
3211
- code: string;
3212
3235
  id: number;
3213
3236
  createdAt: Date;
3214
3237
  updatedAt: Date;
3215
3238
  expiresAt: Date;
3239
+ target: string;
3240
+ targetType: "email" | "phone";
3241
+ code: string;
3242
+ purpose: "registration" | "login" | "password_reset" | "email_change" | "phone_change";
3216
3243
  usedAt: Date | null;
3217
3244
  attempts: number;
3218
3245
  }>;
@@ -3401,7 +3428,7 @@ declare class PermissionsRepository extends BaseRepository {
3401
3428
  name: string;
3402
3429
  displayName: string;
3403
3430
  description: string | null;
3404
- category: "auth" | "custom" | "user" | "rbac" | "system" | null;
3431
+ category: "custom" | "user" | "auth" | "rbac" | "system" | null;
3405
3432
  isBuiltin: boolean;
3406
3433
  isSystem: boolean;
3407
3434
  isActive: boolean;
@@ -3417,7 +3444,7 @@ declare class PermissionsRepository extends BaseRepository {
3417
3444
  name: string;
3418
3445
  displayName: string;
3419
3446
  description: string | null;
3420
- category: "auth" | "custom" | "user" | "rbac" | "system" | null;
3447
+ category: "custom" | "user" | "auth" | "rbac" | "system" | null;
3421
3448
  isBuiltin: boolean;
3422
3449
  isSystem: boolean;
3423
3450
  isActive: boolean;
@@ -3457,7 +3484,7 @@ declare class PermissionsRepository extends BaseRepository {
3457
3484
  name: string;
3458
3485
  displayName: string;
3459
3486
  description: string | null;
3460
- category: "auth" | "custom" | "user" | "rbac" | "system" | null;
3487
+ category: "custom" | "user" | "auth" | "rbac" | "system" | null;
3461
3488
  isBuiltin: boolean;
3462
3489
  isSystem: boolean;
3463
3490
  isActive: boolean;
@@ -3476,8 +3503,8 @@ declare class PermissionsRepository extends BaseRepository {
3476
3503
  isActive: boolean;
3477
3504
  createdAt: Date;
3478
3505
  updatedAt: Date;
3479
- category: "auth" | "custom" | "user" | "rbac" | "system" | null;
3480
3506
  metadata: Record<string, any> | null;
3507
+ category: "custom" | "user" | "auth" | "rbac" | "system" | null;
3481
3508
  }>;
3482
3509
  }
3483
3510
  declare const permissionsRepository: PermissionsRepository;
@@ -3522,9 +3549,9 @@ declare class RolePermissionsRepository extends BaseRepository {
3522
3549
  */
3523
3550
  createMany(data: NewRolePermission[]): Promise<{
3524
3551
  id: number;
3525
- roleId: number;
3526
3552
  createdAt: Date;
3527
3553
  updatedAt: Date;
3554
+ roleId: number;
3528
3555
  permissionId: number;
3529
3556
  }[]>;
3530
3557
  /**
@@ -3540,9 +3567,9 @@ declare class RolePermissionsRepository extends BaseRepository {
3540
3567
  */
3541
3568
  setPermissionsForRole(roleId: number, permissionIds: number[]): Promise<{
3542
3569
  id: number;
3543
- roleId: number;
3544
3570
  createdAt: Date;
3545
3571
  updatedAt: Date;
3572
+ roleId: number;
3546
3573
  permissionId: number;
3547
3574
  }[]>;
3548
3575
  }
@@ -3607,10 +3634,10 @@ declare class UserPermissionsRepository extends BaseRepository {
3607
3634
  id: number;
3608
3635
  createdAt: Date;
3609
3636
  updatedAt: Date;
3610
- permissionId: number;
3611
3637
  expiresAt: Date | null;
3612
- reason: string | null;
3638
+ permissionId: number;
3613
3639
  granted: boolean;
3640
+ reason: string | null;
3614
3641
  }>;
3615
3642
  /**
3616
3643
  * 사용자 권한 오버라이드 업데이트
@@ -3633,10 +3660,10 @@ declare class UserPermissionsRepository extends BaseRepository {
3633
3660
  id: number;
3634
3661
  createdAt: Date;
3635
3662
  updatedAt: Date;
3636
- permissionId: number;
3637
3663
  expiresAt: Date | null;
3638
- reason: string | null;
3664
+ permissionId: number;
3639
3665
  granted: boolean;
3666
+ reason: string | null;
3640
3667
  }>;
3641
3668
  /**
3642
3669
  * 사용자의 모든 권한 오버라이드 삭제
@@ -3715,7 +3742,6 @@ declare class UserProfilesRepository extends BaseRepository {
3715
3742
  displayName: string;
3716
3743
  createdAt: Date;
3717
3744
  updatedAt: Date;
3718
- metadata: Record<string, any> | null;
3719
3745
  firstName: string | null;
3720
3746
  lastName: string | null;
3721
3747
  avatarUrl: string | null;
@@ -3728,6 +3754,7 @@ declare class UserProfilesRepository extends BaseRepository {
3728
3754
  location: string | null;
3729
3755
  company: string | null;
3730
3756
  jobTitle: string | null;
3757
+ metadata: Record<string, any> | null;
3731
3758
  }>;
3732
3759
  /**
3733
3760
  * 프로필 업데이트 (by ID)
@@ -3784,7 +3811,6 @@ declare class UserProfilesRepository extends BaseRepository {
3784
3811
  displayName: string;
3785
3812
  createdAt: Date;
3786
3813
  updatedAt: Date;
3787
- metadata: Record<string, any> | null;
3788
3814
  firstName: string | null;
3789
3815
  lastName: string | null;
3790
3816
  avatarUrl: string | null;
@@ -3797,6 +3823,7 @@ declare class UserProfilesRepository extends BaseRepository {
3797
3823
  location: string | null;
3798
3824
  company: string | null;
3799
3825
  jobTitle: string | null;
3826
+ metadata: Record<string, any> | null;
3800
3827
  }>;
3801
3828
  /**
3802
3829
  * 프로필 삭제 (by User ID)
@@ -3807,7 +3834,6 @@ declare class UserProfilesRepository extends BaseRepository {
3807
3834
  displayName: string;
3808
3835
  createdAt: Date;
3809
3836
  updatedAt: Date;
3810
- metadata: Record<string, any> | null;
3811
3837
  firstName: string | null;
3812
3838
  lastName: string | null;
3813
3839
  avatarUrl: string | null;
@@ -3820,6 +3846,7 @@ declare class UserProfilesRepository extends BaseRepository {
3820
3846
  location: string | null;
3821
3847
  company: string | null;
3822
3848
  jobTitle: string | null;
3849
+ metadata: Record<string, any> | null;
3823
3850
  }>;
3824
3851
  /**
3825
3852
  * 프로필 Upsert (by User ID)
@@ -3833,7 +3860,6 @@ declare class UserProfilesRepository extends BaseRepository {
3833
3860
  displayName: string;
3834
3861
  createdAt: Date;
3835
3862
  updatedAt: Date;
3836
- metadata: Record<string, any> | null;
3837
3863
  firstName: string | null;
3838
3864
  lastName: string | null;
3839
3865
  avatarUrl: string | null;
@@ -3846,6 +3872,7 @@ declare class UserProfilesRepository extends BaseRepository {
3846
3872
  location: string | null;
3847
3873
  company: string | null;
3848
3874
  jobTitle: string | null;
3875
+ metadata: Record<string, any> | null;
3849
3876
  }>;
3850
3877
  /**
3851
3878
  * User ID로 프로필 데이터 조회 (formatted)
@@ -3973,15 +4000,15 @@ declare class InvitationsRepository extends BaseRepository {
3973
4000
  */
3974
4001
  create(data: NewInvitation): Promise<{
3975
4002
  email: string;
4003
+ status: "pending" | "accepted" | "expired" | "cancelled";
3976
4004
  id: number;
3977
- roleId: number;
3978
4005
  createdAt: Date;
3979
4006
  updatedAt: Date;
3980
- status: "pending" | "accepted" | "expired" | "cancelled";
4007
+ roleId: number;
3981
4008
  metadata: Record<string, any> | null;
4009
+ expiresAt: Date;
3982
4010
  token: string;
3983
4011
  invitedBy: number;
3984
- expiresAt: Date;
3985
4012
  acceptedAt: Date | null;
3986
4013
  cancelledAt: Date | null;
3987
4014
  }>;
@@ -4007,15 +4034,15 @@ declare class InvitationsRepository extends BaseRepository {
4007
4034
  */
4008
4035
  deleteById(id: number): Promise<{
4009
4036
  email: string;
4037
+ status: "pending" | "accepted" | "expired" | "cancelled";
4010
4038
  id: number;
4011
- roleId: number;
4012
4039
  createdAt: Date;
4013
4040
  updatedAt: Date;
4014
- status: "pending" | "accepted" | "expired" | "cancelled";
4041
+ roleId: number;
4015
4042
  metadata: Record<string, any> | null;
4043
+ expiresAt: Date;
4016
4044
  token: string;
4017
4045
  invitedBy: number;
4018
- expiresAt: Date;
4019
4046
  acceptedAt: Date | null;
4020
4047
  cancelledAt: Date | null;
4021
4048
  }>;
@@ -4656,13 +4683,13 @@ declare function getUser(c: Context | {
4656
4683
  }): {
4657
4684
  email: string | null;
4658
4685
  phone: string | null;
4686
+ status: "active" | "inactive" | "suspended";
4659
4687
  id: number;
4688
+ createdAt: Date;
4689
+ updatedAt: Date;
4660
4690
  passwordHash: string | null;
4661
4691
  passwordChangeRequired: boolean;
4662
4692
  roleId: number;
4663
- createdAt: Date;
4664
- updatedAt: Date;
4665
- status: "active" | "inactive" | "suspended";
4666
4693
  emailVerifiedAt: Date | null;
4667
4694
  phoneVerifiedAt: Date | null;
4668
4695
  lastLoginAt: Date | null;
@@ -4681,6 +4708,22 @@ declare function getUser(c: Context | {
4681
4708
  declare function getUserId(c: Context | {
4682
4709
  raw: Context;
4683
4710
  }): string;
4711
+ /**
4712
+ * Get authenticated user's role from route context
4713
+ *
4714
+ * @returns Role name or null if user has no role
4715
+ *
4716
+ * @example
4717
+ * ```typescript
4718
+ * app.bind(adminContract, [authenticate], async (c) => {
4719
+ * const role = getRole(c);
4720
+ * // 'admin' | 'superadmin' | null
4721
+ * });
4722
+ * ```
4723
+ */
4724
+ declare function getRole(c: Context | {
4725
+ raw: Context;
4726
+ }): string | null;
4684
4727
  /**
4685
4728
  * Get current key ID from route context
4686
4729
  *
@@ -5135,4 +5178,4 @@ declare const authRegisterEvent: _spfn_core_event.EventDef<{
5135
5178
  type AuthLoginPayload = typeof authLoginEvent._payload;
5136
5179
  type AuthRegisterPayload = typeof authRegisterEvent._payload;
5137
5180
 
5138
- export { type AuthConfig, AuthContext, type AuthLoginPayload, AuthProviderSchema, type AuthRegisterPayload, COOKIE_NAMES, type CreateOAuthStateParams, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, InvitationStatus, InvitationsRepository, KeyAlgorithmType, type KeyPair, KeysRepository, type NewInvitation, type NewPermission, type NewPermissionEntity, type NewRole, type NewRoleEntity, type NewRolePermission, type NewUser, type NewUserPermission, type NewUserProfile, type NewUserPublicKey, type NewUserSocialAccount, type NewVerificationCode, type OAuthState, type Permission, type PermissionEntity, PermissionsRepository, type Role, type RoleEntity, type RoleGuardOptions, type RolePermission, RolePermissionsRepository, RolesRepository, type SessionData, type SessionPayload, SocialAccountsRepository, SocialProvider, type TokenPayload, type UpdateProfileParams, type User, type UserPermission, UserPermissionsRepository, type UserProfile, UserProfilesRepository, type UserPublicKey, type UserSocialAccount, UsersRepository, type VerificationCode, VerificationCodesRepository, VerificationPurpose, acceptInvitation, addPermissionToRole, authLogger, authLoginEvent, authRegisterEvent, authSchema, cancelInvitation, configureAuth, createAuthLifecycle, createInvitation, createOAuthState, createRole, decodeToken, deleteInvitation, deleteRole, exchangeCodeForTokens, expireOldInvitations, generateClientToken, generateKeyPair, generateKeyPairES256, generateKeyPairRS256, generateToken, getAllRoles, getAuth, getAuthConfig, getAuthSessionService, getGoogleAuthUrl, getGoogleOAuthConfig, getGoogleUserInfo, getInvitationByToken, getInvitationWithDetails, getKeyId, getKeySize, getRoleByName, getRolePermissions, getSessionInfo, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initializeAuth, invitationsRepository, isGoogleOAuthEnabled, keysRepository, listInvitations, parseDuration, permissions, permissionsRepository, refreshAccessToken, removePermissionFromRole, requireAnyPermission, requirePermissions, requireRole, resendInvitation, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, sealSession, setRolePermissions, shouldRefreshSession, shouldRotateKey, socialAccountsRepository, unsealSession, updateLastLoginService, updateRole, updateUserProfileService, updateUserService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyKeyFingerprint, verifyOAuthState, verifyPassword, verifyToken };
5181
+ export { type AuthConfig, AuthContext, type AuthLoginPayload, AuthProviderSchema, type AuthRegisterPayload, COOKIE_NAMES, type CreateOAuthStateParams, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, InvitationStatus, InvitationsRepository, KeyAlgorithmType, type KeyPair, KeysRepository, type NewInvitation, type NewPermission, type NewPermissionEntity, type NewRole, type NewRoleEntity, type NewRolePermission, type NewUser, type NewUserPermission, type NewUserProfile, type NewUserPublicKey, type NewUserSocialAccount, type NewVerificationCode, type OAuthState, type Permission, type PermissionEntity, PermissionsRepository, type Role, type RoleEntity, type RoleGuardOptions, type RolePermission, RolePermissionsRepository, RolesRepository, type SessionData, type SessionPayload, SocialAccountsRepository, SocialProvider, type TokenPayload, type UpdateProfileParams, type User, type UserPermission, UserPermissionsRepository, type UserProfile, UserProfilesRepository, type UserPublicKey, type UserSocialAccount, UsersRepository, type VerificationCode, VerificationCodesRepository, VerificationPurpose, acceptInvitation, addPermissionToRole, authLogger, authLoginEvent, authRegisterEvent, authSchema, cancelInvitation, configureAuth, createAuthLifecycle, createInvitation, createOAuthState, createRole, decodeToken, deleteInvitation, deleteRole, exchangeCodeForTokens, expireOldInvitations, generateClientToken, generateKeyPair, generateKeyPairES256, generateKeyPairRS256, generateToken, getAllRoles, getAuth, getAuthConfig, getAuthSessionService, getGoogleAuthUrl, getGoogleOAuthConfig, getGoogleUserInfo, getInvitationByToken, getInvitationWithDetails, getKeyId, getKeySize, getRole, getRoleByName, getRolePermissions, getSessionInfo, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initializeAuth, invitationsRepository, isGoogleOAuthEnabled, keysRepository, listInvitations, parseDuration, permissions, permissionsRepository, refreshAccessToken, removePermissionFromRole, requireAnyPermission, requirePermissions, requireRole, resendInvitation, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, sealSession, setRolePermissions, shouldRefreshSession, shouldRotateKey, socialAccountsRepository, unsealSession, updateLastLoginService, updateRole, updateUserProfileService, updateUserService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyKeyFingerprint, verifyOAuthState, verifyPassword, verifyToken };
package/dist/server.js CHANGED
@@ -5355,6 +5355,28 @@ var init_users_repository = __esm({
5355
5355
  }
5356
5356
  return null;
5357
5357
  }
5358
+ /**
5359
+ * ID로 사용자 + Role 조회 (leftJoin)
5360
+ * Read replica 사용
5361
+ *
5362
+ * roleId가 null인 유저는 role: null 반환
5363
+ */
5364
+ async findByIdWithRole(id11) {
5365
+ const result = await this.readDb.select({
5366
+ user: users,
5367
+ roleName: roles.name,
5368
+ roleDisplayName: roles.displayName,
5369
+ rolePriority: roles.priority
5370
+ }).from(users).leftJoin(roles, eq(users.roleId, roles.id)).where(eq(users.id, id11)).limit(1);
5371
+ const row = result[0];
5372
+ if (!row) {
5373
+ return null;
5374
+ }
5375
+ return {
5376
+ user: row.user,
5377
+ role: row.roleName ? { name: row.roleName, displayName: row.roleDisplayName, priority: row.rolePriority } : null
5378
+ };
5379
+ }
5358
5380
  /**
5359
5381
  * 사용자 생성
5360
5382
  * Write primary 사용
@@ -6766,6 +6788,9 @@ function getUser(c) {
6766
6788
  function getUserId(c) {
6767
6789
  return getAuth(c).userId;
6768
6790
  }
6791
+ function getRole(c) {
6792
+ return getAuth(c).role;
6793
+ }
6769
6794
  function getKeyId(c) {
6770
6795
  return getAuth(c).keyId;
6771
6796
  }
@@ -8244,10 +8269,11 @@ var authenticate = defineMiddleware("auth", async (c, next) => {
8244
8269
  }
8245
8270
  throw new UnauthorizedError({ message: "Authentication failed" });
8246
8271
  }
8247
- const user = await usersRepository2.findById(keyRecord.userId);
8248
- if (!user) {
8272
+ const result = await usersRepository2.findByIdWithRole(keyRecord.userId);
8273
+ if (!result) {
8249
8274
  throw new UnauthorizedError({ message: "User not found" });
8250
8275
  }
8276
+ const { user, role } = result;
8251
8277
  if (user.status !== "active") {
8252
8278
  throw new AccountDisabledError2({ status: user.status });
8253
8279
  }
@@ -8255,7 +8281,8 @@ var authenticate = defineMiddleware("auth", async (c, next) => {
8255
8281
  c.set("auth", {
8256
8282
  user,
8257
8283
  userId: String(user.id),
8258
- keyId
8284
+ keyId,
8285
+ role: role?.name ?? null
8259
8286
  });
8260
8287
  const method = c.req.method;
8261
8288
  const path = c.req.path;
@@ -8335,7 +8362,7 @@ var requireAnyPermission = defineMiddleware2(
8335
8362
 
8336
8363
  // src/server/middleware/require-role.ts
8337
8364
  import { defineMiddleware as defineMiddleware3 } from "@spfn/core/route";
8338
- import { getAuth as getAuth3, hasAnyRole as hasAnyRole2, authLogger as authLogger4 } from "@spfn/auth/server";
8365
+ import { getAuth as getAuth3, authLogger as authLogger4 } from "@spfn/auth/server";
8339
8366
  import { ForbiddenError as ForbiddenError2 } from "@spfn/core/errors";
8340
8367
  import { InsufficientRoleError } from "@spfn/auth/errors";
8341
8368
  var requireRole = defineMiddleware3(
@@ -8349,11 +8376,11 @@ var requireRole = defineMiddleware3(
8349
8376
  });
8350
8377
  throw new ForbiddenError2({ message: "Authentication required" });
8351
8378
  }
8352
- const { userId } = auth;
8353
- const allowed = await hasAnyRole2(userId, roleNames);
8354
- if (!allowed) {
8379
+ const { userId, role: userRole } = auth;
8380
+ if (!userRole || !roleNames.includes(userRole)) {
8355
8381
  authLogger4.middleware.warn("Role check failed", {
8356
8382
  userId,
8383
+ userRole,
8357
8384
  requiredRoles: roleNames,
8358
8385
  path: c.req.path
8359
8386
  });
@@ -8361,6 +8388,7 @@ var requireRole = defineMiddleware3(
8361
8388
  }
8362
8389
  authLogger4.middleware.debug("Role check passed", {
8363
8390
  userId,
8391
+ userRole,
8364
8392
  roles: roleNames
8365
8393
  });
8366
8394
  await next();
@@ -8369,7 +8397,7 @@ var requireRole = defineMiddleware3(
8369
8397
 
8370
8398
  // src/server/middleware/role-guard.ts
8371
8399
  import { defineMiddleware as defineMiddleware4 } from "@spfn/core/route";
8372
- import { getAuth as getAuth4, getUserRole as getUserRole2, authLogger as authLogger5 } from "@spfn/auth/server";
8400
+ import { getAuth as getAuth4, authLogger as authLogger5 } from "@spfn/auth/server";
8373
8401
  import { ForbiddenError as ForbiddenError3 } from "@spfn/core/errors";
8374
8402
  import { InsufficientRoleError as InsufficientRoleError2 } from "@spfn/auth/errors";
8375
8403
  var roleGuard = defineMiddleware4(
@@ -8386,8 +8414,7 @@ var roleGuard = defineMiddleware4(
8386
8414
  });
8387
8415
  throw new ForbiddenError3({ message: "Authentication required" });
8388
8416
  }
8389
- const { userId } = auth;
8390
- const userRole = await getUserRole2(userId);
8417
+ const { userId, role: userRole } = auth;
8391
8418
  if (deny && deny.length > 0) {
8392
8419
  if (userRole && deny.includes(userRole)) {
8393
8420
  authLogger5.middleware.warn("Role guard denied", {
@@ -9257,6 +9284,7 @@ export {
9257
9284
  getInvitationWithDetails,
9258
9285
  getKeyId,
9259
9286
  getKeySize,
9287
+ getRole,
9260
9288
  getRoleByName,
9261
9289
  getRolePermissions,
9262
9290
  getSessionInfo,