@spfn/auth 0.2.0-beta.8 → 0.2.1

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.
@@ -1,8 +1,88 @@
1
+ import * as _spfn_core_route from '@spfn/core/route';
1
2
  import * as _sinclair_typebox from '@sinclair/typebox';
2
3
  import { Static } from '@sinclair/typebox';
3
- import * as _spfn_core_route from '@spfn/core/route';
4
4
  import { User } from '@spfn/auth/server';
5
5
 
6
+ /**
7
+ * Role information for client/API responses
8
+ */
9
+ interface Role {
10
+ id: number;
11
+ name: string;
12
+ displayName: string;
13
+ description: string | null;
14
+ isBuiltin: boolean;
15
+ isSystem: boolean;
16
+ isActive: boolean;
17
+ priority: number;
18
+ createdAt: Date;
19
+ updatedAt: Date;
20
+ }
21
+ /**
22
+ * Permission information for client/API responses
23
+ */
24
+ interface Permission {
25
+ id: number;
26
+ name: string;
27
+ displayName: string;
28
+ description: string | null;
29
+ category: string | null;
30
+ isBuiltin: boolean;
31
+ isSystem: boolean;
32
+ isActive: boolean;
33
+ metadata: Record<string, any> | null;
34
+ createdAt: Date;
35
+ updatedAt: Date;
36
+ }
37
+ interface AuthSession {
38
+ userId: number;
39
+ publicId: string;
40
+ email: string | null;
41
+ emailVerified: boolean;
42
+ phoneVerified: boolean;
43
+ role: Role;
44
+ permissions: Permission[];
45
+ }
46
+ interface ProfileInfo {
47
+ profileId: number;
48
+ displayName: string | null;
49
+ firstName: string | null;
50
+ lastName: string | null;
51
+ avatarUrl: string | null;
52
+ bio: string | null;
53
+ locale: string;
54
+ timezone: string;
55
+ website: string | null;
56
+ location: string | null;
57
+ company: string | null;
58
+ jobTitle: string | null;
59
+ metadata: Record<string, any> | null;
60
+ createdAt: Date;
61
+ updatedAt: Date;
62
+ }
63
+ /**
64
+ * User Profile Response
65
+ *
66
+ * Complete user data including:
67
+ * - User fields at top level (userId, email, etc.)
68
+ * - Profile data as nested field (optional)
69
+ *
70
+ * Excludes:
71
+ * - Role and permissions (use auth session API)
72
+ */
73
+ interface UserProfile {
74
+ userId: number;
75
+ publicId: string;
76
+ email: string | null;
77
+ username: string | null;
78
+ emailVerified: boolean;
79
+ phoneVerified: boolean;
80
+ lastLoginAt: Date | null;
81
+ createdAt: Date;
82
+ updatedAt: Date;
83
+ profile: ProfileInfo | null;
84
+ }
85
+
6
86
  /**
7
87
  * @spfn/auth - Shared Types
8
88
  *
@@ -71,9 +151,11 @@ interface RegisterParams {
71
151
  keyId: string;
72
152
  fingerprint: string;
73
153
  algorithm?: KeyAlgorithmType;
154
+ metadata?: Record<string, unknown>;
74
155
  }
75
156
  interface RegisterResult {
76
157
  userId: string;
158
+ publicId: string;
77
159
  email?: string;
78
160
  phone?: string;
79
161
  }
@@ -89,6 +171,7 @@ interface LoginParams {
89
171
  }
90
172
  interface LoginResult {
91
173
  userId: string;
174
+ publicId: string;
92
175
  email?: string;
93
176
  phone?: string;
94
177
  passwordChangeRequired: boolean;
@@ -299,6 +382,98 @@ interface AuthInitOptions {
299
382
  sessionTtl?: string | number;
300
383
  }
301
384
 
385
+ /**
386
+ * One-Time Token Service
387
+ *
388
+ * Issues and verifies one-time tokens for direct API access.
389
+ */
390
+ interface IssueOneTimeTokenResult {
391
+ token: string;
392
+ expiresAt: string;
393
+ }
394
+ /**
395
+ * Issue a one-time token for the authenticated user
396
+ *
397
+ * @param userId - Authenticated user's ID
398
+ * @returns Token string and ISO expiration timestamp
399
+ */
400
+ declare function issueOneTimeTokenService(userId: string): Promise<IssueOneTimeTokenResult>;
401
+ /**
402
+ * Verify and consume a one-time token
403
+ *
404
+ * @param token - The one-time token to verify
405
+ * @returns userId if valid, null if invalid/expired/consumed
406
+ */
407
+ declare function verifyOneTimeTokenService(token: string): Promise<string | null>;
408
+
409
+ /**
410
+ * @spfn/auth - OAuth Service
411
+ *
412
+ * OAuth 인증 비즈니스 로직
413
+ * - Google OAuth Authorization Code Flow
414
+ * - 소셜 계정 연결/생성
415
+ * - publicKey는 state에서 추출하여 등록
416
+ */
417
+
418
+ interface OAuthStartParams {
419
+ provider: SocialProvider;
420
+ returnUrl: string;
421
+ publicKey: string;
422
+ keyId: string;
423
+ fingerprint: string;
424
+ algorithm: KeyAlgorithmType;
425
+ metadata?: Record<string, unknown>;
426
+ }
427
+ interface OAuthStartResult {
428
+ authUrl: string;
429
+ }
430
+ interface OAuthCallbackParams {
431
+ provider: SocialProvider;
432
+ code: string;
433
+ state: string;
434
+ }
435
+ interface OAuthCallbackResult {
436
+ redirectUrl: string;
437
+ userId: string;
438
+ keyId: string;
439
+ isNewUser: boolean;
440
+ }
441
+ /**
442
+ * OAuth 로그인 시작 - Provider 로그인 페이지로 리다이렉트할 URL 생성
443
+ *
444
+ * Next.js에서 키쌍을 생성한 후, publicKey를 state에 포함하여 호출
445
+ */
446
+ declare function oauthStartService(params: OAuthStartParams): Promise<OAuthStartResult>;
447
+ /**
448
+ * OAuth 콜백 처리 - Code를 Token으로 교환하고 사용자 생성/연결
449
+ *
450
+ * state에서 publicKey를 추출하여 서버에 등록
451
+ * Next.js는 반환된 userId, keyId로 세션을 구성
452
+ */
453
+ declare function oauthCallbackService(params: OAuthCallbackParams): Promise<OAuthCallbackResult>;
454
+ /**
455
+ * OAuth 에러 리다이렉트 URL 생성
456
+ */
457
+ declare function buildOAuthErrorUrl(error: string): string;
458
+ /**
459
+ * OAuth provider가 활성화되어 있는지 확인
460
+ */
461
+ declare function isOAuthProviderEnabled(provider: SocialProvider): boolean;
462
+ /**
463
+ * 활성화된 모든 OAuth provider 목록
464
+ */
465
+ declare function getEnabledOAuthProviders(): SocialProvider[];
466
+ /**
467
+ * Google access token 조회 (만료 시 자동 리프레시)
468
+ *
469
+ * 저장된 토큰이 만료 임박(5분 이내) 또는 만료 상태이면
470
+ * refresh token으로 자동 갱신 후 DB 업데이트하여 유효한 토큰 반환.
471
+ *
472
+ * @param userId - 사용자 ID
473
+ * @returns 유효한 Google access token
474
+ */
475
+ declare function getGoogleAccessToken(userId: number): Promise<string>;
476
+
302
477
  /**
303
478
  * @spfn/auth - Main Router
304
479
  *
@@ -310,29 +485,150 @@ interface AuthInitOptions {
310
485
  *
311
486
  * Routes:
312
487
  * - Auth: /_auth/exists, /_auth/codes, /_auth/login, /_auth/logout, etc.
488
+ * - OAuth: /_auth/oauth/google, /_auth/oauth/google/callback, etc.
313
489
  * - Invitations: /_auth/invitations/*
314
490
  * - Users: /_auth/users/*
491
+ * - Admin: /_auth/admin/* (superadmin only)
315
492
  */
316
493
  declare const mainAuthRouter: _spfn_core_route.Router<{
317
- getUserProfile: _spfn_core_route.RouteDef<{}, {}, UserProfile>;
318
- updateUserProfile: _spfn_core_route.RouteDef<{
494
+ checkAccountExists: _spfn_core_route.RouteDef<{
495
+ body: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
496
+ email: _sinclair_typebox.TString;
497
+ }>, _sinclair_typebox.TObject<{
498
+ phone: _sinclair_typebox.TString;
499
+ }>]>;
500
+ }, {}, CheckAccountExistsResult>;
501
+ sendVerificationCode: _spfn_core_route.RouteDef<{
319
502
  body: _sinclair_typebox.TObject<{
320
- displayName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
321
- firstName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
322
- lastName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
323
- avatarUrl: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
324
- bio: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
325
- locale: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
326
- timezone: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
327
- dateOfBirth: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
328
- gender: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
329
- website: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
330
- location: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
331
- company: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
332
- jobTitle: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
333
- metadata: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TAny>>;
503
+ target: _sinclair_typebox.TString;
504
+ targetType: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"email">, _sinclair_typebox.TLiteral<"phone">]>;
505
+ purpose: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"registration">, _sinclair_typebox.TLiteral<"login">, _sinclair_typebox.TLiteral<"password_reset">, _sinclair_typebox.TLiteral<"email_change">, _sinclair_typebox.TLiteral<"phone_change">]>;
334
506
  }>;
335
- }, {}, ProfileInfo>;
507
+ }, {}, SendVerificationCodeResult>;
508
+ verifyCode: _spfn_core_route.RouteDef<{
509
+ body: _sinclair_typebox.TObject<{
510
+ target: _sinclair_typebox.TString;
511
+ targetType: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"email">, _sinclair_typebox.TLiteral<"phone">]>;
512
+ code: _sinclair_typebox.TString;
513
+ purpose: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"registration">, _sinclair_typebox.TLiteral<"login">, _sinclair_typebox.TLiteral<"password_reset">, _sinclair_typebox.TLiteral<"email_change">, _sinclair_typebox.TLiteral<"phone_change">]>;
514
+ }>;
515
+ }, {}, {
516
+ valid: boolean;
517
+ verificationToken: string;
518
+ }>;
519
+ register: _spfn_core_route.RouteDef<{
520
+ body: _sinclair_typebox.TObject<{
521
+ email: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
522
+ phone: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
523
+ verificationToken: _sinclair_typebox.TString;
524
+ password: _sinclair_typebox.TString;
525
+ metadata: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnknown>>;
526
+ }>;
527
+ }, {
528
+ body: _sinclair_typebox.TObject<{
529
+ publicKey: _sinclair_typebox.TString;
530
+ keyId: _sinclair_typebox.TString;
531
+ fingerprint: _sinclair_typebox.TString;
532
+ algorithm: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"ES256" | "RS256">[]>;
533
+ }>;
534
+ }, RegisterResult>;
535
+ login: _spfn_core_route.RouteDef<{
536
+ body: _sinclair_typebox.TObject<{
537
+ email: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
538
+ phone: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
539
+ password: _sinclair_typebox.TString;
540
+ }>;
541
+ }, {
542
+ body: _sinclair_typebox.TObject<{
543
+ publicKey: _sinclair_typebox.TString;
544
+ keyId: _sinclair_typebox.TString;
545
+ fingerprint: _sinclair_typebox.TString;
546
+ algorithm: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"ES256" | "RS256">[]>;
547
+ oldKeyId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
548
+ }>;
549
+ }, LoginResult>;
550
+ logout: _spfn_core_route.RouteDef<{}, {}, void>;
551
+ rotateKey: _spfn_core_route.RouteDef<{}, {
552
+ body: _sinclair_typebox.TObject<{
553
+ publicKey: _sinclair_typebox.TString;
554
+ keyId: _sinclair_typebox.TString;
555
+ fingerprint: _sinclair_typebox.TString;
556
+ algorithm: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"ES256" | "RS256">[]>;
557
+ }>;
558
+ }, RotateKeyResult>;
559
+ changePassword: _spfn_core_route.RouteDef<{
560
+ body: _sinclair_typebox.TObject<{
561
+ currentPassword: _sinclair_typebox.TString;
562
+ newPassword: _sinclair_typebox.TString;
563
+ }>;
564
+ }, {}, void>;
565
+ getAuthSession: _spfn_core_route.RouteDef<{}, {}, {
566
+ role: {
567
+ id: number;
568
+ name: string;
569
+ displayName: string;
570
+ priority: number;
571
+ };
572
+ permissions: {
573
+ id: number;
574
+ name: string;
575
+ displayName: string;
576
+ category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
577
+ }[];
578
+ userId: number;
579
+ publicId: string;
580
+ email: string | null;
581
+ emailVerified: boolean;
582
+ phoneVerified: boolean;
583
+ }>;
584
+ issueOneTimeToken: _spfn_core_route.RouteDef<{}, {}, IssueOneTimeTokenResult>;
585
+ oauthGoogleStart: _spfn_core_route.RouteDef<{
586
+ query: _sinclair_typebox.TObject<{
587
+ state: _sinclair_typebox.TString;
588
+ }>;
589
+ }, {}, Response>;
590
+ oauthGoogleCallback: _spfn_core_route.RouteDef<{
591
+ query: _sinclair_typebox.TObject<{
592
+ code: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
593
+ state: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
594
+ error: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
595
+ error_description: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
596
+ }>;
597
+ }, {}, Response>;
598
+ oauthStart: _spfn_core_route.RouteDef<{
599
+ body: _sinclair_typebox.TObject<{
600
+ provider: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"google" | "github" | "kakao" | "naver">[]>;
601
+ returnUrl: _sinclair_typebox.TString;
602
+ publicKey: _sinclair_typebox.TString;
603
+ keyId: _sinclair_typebox.TString;
604
+ fingerprint: _sinclair_typebox.TString;
605
+ algorithm: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"ES256" | "RS256">[]>;
606
+ metadata: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnknown>>;
607
+ }>;
608
+ }, {}, OAuthStartResult>;
609
+ oauthProviders: _spfn_core_route.RouteDef<{}, {}, {
610
+ providers: ("google" | "github" | "kakao" | "naver")[];
611
+ }>;
612
+ getGoogleOAuthUrl: _spfn_core_route.RouteDef<{
613
+ body: _sinclair_typebox.TObject<{
614
+ returnUrl: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
615
+ state: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
616
+ }>;
617
+ }, {}, {
618
+ authUrl: string;
619
+ }>;
620
+ oauthFinalize: _spfn_core_route.RouteDef<{
621
+ body: _sinclair_typebox.TObject<{
622
+ userId: _sinclair_typebox.TString;
623
+ keyId: _sinclair_typebox.TString;
624
+ returnUrl: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
625
+ }>;
626
+ }, {}, {
627
+ success: boolean;
628
+ userId: string;
629
+ keyId: string;
630
+ returnUrl: string;
631
+ }>;
336
632
  getInvitation: _spfn_core_route.RouteDef<{
337
633
  params: _sinclair_typebox.TObject<{
338
634
  token: _sinclair_typebox.TString;
@@ -367,6 +663,7 @@ declare const mainAuthRouter: _spfn_core_route.Router<{
367
663
  email: _sinclair_typebox.TString;
368
664
  roleId: _sinclair_typebox.TNumber;
369
665
  expiresInDays: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
666
+ expiresAt: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
370
667
  metadata: _sinclair_typebox.TOptional<_sinclair_typebox.TAny>;
371
668
  }>;
372
669
  }, {}, {
@@ -433,93 +730,138 @@ declare const mainAuthRouter: _spfn_core_route.Router<{
433
730
  id: _sinclair_typebox.TNumber;
434
731
  }>;
435
732
  }, {}, void>;
436
- checkAccountExists: _spfn_core_route.RouteDef<{
437
- body: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
438
- email: _sinclair_typebox.TString;
439
- }>, _sinclair_typebox.TObject<{
440
- phone: _sinclair_typebox.TString;
441
- }>]>;
442
- }, {}, CheckAccountExistsResult>;
443
- sendVerificationCode: _spfn_core_route.RouteDef<{
733
+ getUserProfile: _spfn_core_route.RouteDef<{}, {}, UserProfile>;
734
+ updateUserProfile: _spfn_core_route.RouteDef<{
444
735
  body: _sinclair_typebox.TObject<{
445
- target: _sinclair_typebox.TString;
446
- targetType: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"email">, _sinclair_typebox.TLiteral<"phone">]>;
447
- purpose: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"registration">, _sinclair_typebox.TLiteral<"login">, _sinclair_typebox.TLiteral<"password_reset">, _sinclair_typebox.TLiteral<"email_change">, _sinclair_typebox.TLiteral<"phone_change">]>;
736
+ displayName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
737
+ firstName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
738
+ lastName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
739
+ avatarUrl: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
740
+ bio: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
741
+ locale: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
742
+ timezone: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
743
+ dateOfBirth: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
744
+ gender: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
745
+ website: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
746
+ location: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
747
+ company: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
748
+ jobTitle: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
749
+ metadata: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TAny>>;
448
750
  }>;
449
- }, {}, SendVerificationCodeResult>;
450
- verifyCode: _spfn_core_route.RouteDef<{
451
- body: _sinclair_typebox.TObject<{
452
- target: _sinclair_typebox.TString;
453
- targetType: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"email">, _sinclair_typebox.TLiteral<"phone">]>;
454
- code: _sinclair_typebox.TString;
455
- purpose: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"registration">, _sinclair_typebox.TLiteral<"login">, _sinclair_typebox.TLiteral<"password_reset">, _sinclair_typebox.TLiteral<"email_change">, _sinclair_typebox.TLiteral<"phone_change">]>;
751
+ }, {}, ProfileInfo>;
752
+ checkUsername: _spfn_core_route.RouteDef<{
753
+ query: _sinclair_typebox.TObject<{
754
+ username: _sinclair_typebox.TString;
456
755
  }>;
457
756
  }, {}, {
458
- valid: boolean;
459
- verificationToken: string;
757
+ available: boolean;
460
758
  }>;
461
- register: _spfn_core_route.RouteDef<{
759
+ updateUsername: _spfn_core_route.RouteDef<{
462
760
  body: _sinclair_typebox.TObject<{
463
- email: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
464
- phone: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
465
- verificationToken: _sinclair_typebox.TString;
466
- password: _sinclair_typebox.TString;
467
- }>;
468
- }, {
469
- body: _sinclair_typebox.TObject<{
470
- publicKey: _sinclair_typebox.TString;
471
- keyId: _sinclair_typebox.TString;
472
- fingerprint: _sinclair_typebox.TString;
473
- algorithm: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"ES256" | "RS256">[]>;
474
- }>;
475
- }, RegisterResult>;
476
- login: _spfn_core_route.RouteDef<{
477
- body: _sinclair_typebox.TObject<{
478
- email: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
479
- phone: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
480
- password: _sinclair_typebox.TString;
761
+ username: _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNull]>;
481
762
  }>;
482
- }, {
763
+ }, {}, {
764
+ createdAt: Date;
765
+ updatedAt: Date;
766
+ id: number;
767
+ publicId: string;
768
+ email: string | null;
769
+ phone: string | null;
770
+ username: string | null;
771
+ passwordHash: string | null;
772
+ passwordChangeRequired: boolean;
773
+ roleId: number;
774
+ status: "active" | "inactive" | "suspended";
775
+ emailVerifiedAt: Date | null;
776
+ phoneVerifiedAt: Date | null;
777
+ lastLoginAt: Date | null;
778
+ }>;
779
+ updateLocale: _spfn_core_route.RouteDef<{
483
780
  body: _sinclair_typebox.TObject<{
484
- publicKey: _sinclair_typebox.TString;
485
- keyId: _sinclair_typebox.TString;
486
- fingerprint: _sinclair_typebox.TString;
487
- algorithm: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"ES256" | "RS256">[]>;
488
- oldKeyId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
781
+ locale: _sinclair_typebox.TString;
489
782
  }>;
490
- }, LoginResult>;
491
- logout: _spfn_core_route.RouteDef<{}, {}, void>;
492
- rotateKey: _spfn_core_route.RouteDef<{}, {
493
- body: _sinclair_typebox.TObject<{
494
- publicKey: _sinclair_typebox.TString;
495
- keyId: _sinclair_typebox.TString;
496
- fingerprint: _sinclair_typebox.TString;
497
- algorithm: _sinclair_typebox.TUnion<_sinclair_typebox.TLiteral<"ES256" | "RS256">[]>;
783
+ }, {}, {
784
+ locale: string;
785
+ }>;
786
+ listRoles: _spfn_core_route.RouteDef<{
787
+ query: _sinclair_typebox.TObject<{
788
+ includeInactive: _sinclair_typebox.TOptional<_sinclair_typebox.TBoolean>;
498
789
  }>;
499
- }, RotateKeyResult>;
500
- changePassword: _spfn_core_route.RouteDef<{
790
+ }, {}, {
791
+ roles: {
792
+ description: string | null;
793
+ id: number;
794
+ name: string;
795
+ displayName: string;
796
+ isBuiltin: boolean;
797
+ isSystem: boolean;
798
+ isActive: boolean;
799
+ priority: number;
800
+ createdAt: Date;
801
+ updatedAt: Date;
802
+ }[];
803
+ }>;
804
+ createAdminRole: _spfn_core_route.RouteDef<{
501
805
  body: _sinclair_typebox.TObject<{
502
- currentPassword: _sinclair_typebox.TString;
503
- newPassword: _sinclair_typebox.TString;
806
+ name: _sinclair_typebox.TString;
807
+ displayName: _sinclair_typebox.TString;
808
+ description: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
809
+ priority: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
810
+ permissionIds: _sinclair_typebox.TOptional<_sinclair_typebox.TArray<_sinclair_typebox.TNumber>>;
504
811
  }>;
505
- }, {}, void>;
506
- getAuthSession: _spfn_core_route.RouteDef<{}, {}, {
812
+ }, {}, {
507
813
  role: {
814
+ description: string | null;
508
815
  id: number;
509
816
  name: string;
510
817
  displayName: string;
818
+ isBuiltin: boolean;
819
+ isSystem: boolean;
820
+ isActive: boolean;
511
821
  priority: number;
822
+ createdAt: Date;
823
+ updatedAt: Date;
512
824
  };
513
- permissions: {
825
+ }>;
826
+ updateAdminRole: _spfn_core_route.RouteDef<{
827
+ params: _sinclair_typebox.TObject<{
828
+ id: _sinclair_typebox.TNumber;
829
+ }>;
830
+ body: _sinclair_typebox.TObject<{
831
+ displayName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
832
+ description: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
833
+ priority: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
834
+ isActive: _sinclair_typebox.TOptional<_sinclair_typebox.TBoolean>;
835
+ }>;
836
+ }, {}, {
837
+ role: {
838
+ description: string | null;
514
839
  id: number;
515
840
  name: string;
516
841
  displayName: string;
517
- category: "custom" | "user" | "auth" | "rbac" | "system" | undefined;
518
- }[];
842
+ isBuiltin: boolean;
843
+ isSystem: boolean;
844
+ isActive: boolean;
845
+ priority: number;
846
+ createdAt: Date;
847
+ updatedAt: Date;
848
+ };
849
+ }>;
850
+ deleteAdminRole: _spfn_core_route.RouteDef<{
851
+ params: _sinclair_typebox.TObject<{
852
+ id: _sinclair_typebox.TNumber;
853
+ }>;
854
+ }, {}, void>;
855
+ updateUserRole: _spfn_core_route.RouteDef<{
856
+ params: _sinclair_typebox.TObject<{
857
+ userId: _sinclair_typebox.TNumber;
858
+ }>;
859
+ body: _sinclair_typebox.TObject<{
860
+ roleId: _sinclair_typebox.TNumber;
861
+ }>;
862
+ }, {}, {
519
863
  userId: number;
520
- email: string | null;
521
- emailVerified: boolean;
522
- phoneVerified: boolean;
864
+ roleId: number;
523
865
  }>;
524
866
  }>;
525
867
 
@@ -527,6 +869,8 @@ interface AuthContext {
527
869
  user: User;
528
870
  userId: string;
529
871
  keyId: string;
872
+ role: string | null;
873
+ locale: string;
530
874
  }
531
875
  declare module 'hono' {
532
876
  interface ContextVariableMap {
@@ -564,82 +908,33 @@ declare module 'hono' {
564
908
  * ```
565
909
  */
566
910
  declare const authenticate: _spfn_core_route.NamedMiddleware<"auth">;
567
-
568
- /**
569
- * Role information for client/API responses
570
- */
571
- interface Role {
572
- id: number;
573
- name: string;
574
- displayName: string;
575
- description: string | null;
576
- isBuiltin: boolean;
577
- isSystem: boolean;
578
- isActive: boolean;
579
- priority: number;
580
- createdAt: Date;
581
- updatedAt: Date;
582
- }
583
911
  /**
584
- * Permission information for client/API responses
585
- */
586
- interface Permission {
587
- id: number;
588
- name: string;
589
- displayName: string;
590
- description: string | null;
591
- category: string | null;
592
- isBuiltin: boolean;
593
- isSystem: boolean;
594
- isActive: boolean;
595
- metadata: Record<string, any> | null;
596
- createdAt: Date;
597
- updatedAt: Date;
598
- }
599
- interface AuthSession {
600
- userId: number;
601
- email: string | null;
602
- emailVerified: boolean;
603
- phoneVerified: boolean;
604
- role: Role;
605
- permissions: Permission[];
606
- }
607
- interface ProfileInfo {
608
- profileId: number;
609
- displayName: string;
610
- firstName: string | null;
611
- lastName: string | null;
612
- avatarUrl: string | null;
613
- bio: string | null;
614
- locale: string;
615
- timezone: string;
616
- website: string | null;
617
- location: string | null;
618
- company: string | null;
619
- jobTitle: string | null;
620
- metadata: Record<string, any> | null;
621
- createdAt: Date;
622
- updatedAt: Date;
623
- }
624
- /**
625
- * User Profile Response
912
+ * Optional authentication middleware
626
913
  *
627
- * Complete user data including:
628
- * - User fields at top level (userId, email, etc.)
629
- * - Profile data as nested field (optional)
914
+ * Same as `authenticate` but does NOT reject unauthenticated requests.
915
+ * - No token continues without auth context
916
+ * - Invalid token continues without auth context
917
+ * - Valid token → sets auth context normally
630
918
  *
631
- * Excludes:
632
- * - Role and permissions (use auth session API)
919
+ * Auto-skips the global 'auth' middleware when used at route level.
920
+ *
921
+ * @example
922
+ * ```typescript
923
+ * // No need for .skip(['auth']) — handled automatically
924
+ * export const getProducts = route.get('/products')
925
+ * .use([optionalAuth])
926
+ * .handler(async (c) => {
927
+ * const auth = getOptionalAuth(c); // AuthContext | undefined
928
+ *
929
+ * if (auth)
930
+ * {
931
+ * return getPersonalizedProducts(auth.userId);
932
+ * }
933
+ *
934
+ * return getPublicProducts();
935
+ * });
936
+ * ```
633
937
  */
634
- interface UserProfile {
635
- userId: number;
636
- email: string | null;
637
- emailVerified: boolean;
638
- phoneVerified: boolean;
639
- lastLoginAt: Date | null;
640
- createdAt: Date;
641
- updatedAt: Date;
642
- profile: ProfileInfo | null;
643
- }
938
+ declare const optionalAuth: _spfn_core_route.NamedMiddleware<"optionalAuth">;
644
939
 
645
- export { VerificationPurposeSchema as $, type AuthSession as A, type ChangePasswordParams as B, type CheckAccountExistsResult as C, sendVerificationCodeService as D, verifyCodeService as E, type SendVerificationCodeParams as F, type VerifyCodeParams as G, type VerifyCodeResult as H, INVITATION_STATUSES as I, registerPublicKeyService as J, KEY_ALGORITHM as K, type LoginResult as L, rotateKeyService as M, revokeKeyService as N, type RegisterPublicKeyParams as O, type PermissionConfig as P, type RotateKeyParams as Q, type RoleConfig as R, type SendVerificationCodeResult as S, type RevokeKeyParams as T, type UserProfile as U, type VerificationTargetType as V, authenticate as W, EmailSchema as X, PhoneSchema as Y, PasswordSchema as Z, TargetTypeSchema as _, type ProfileInfo as a, type RegisterResult as b, type RotateKeyResult as c, USER_STATUSES as d, SOCIAL_PROVIDERS as e, type VerificationPurpose as f, VERIFICATION_TARGET_TYPES as g, VERIFICATION_PURPOSES as h, PERMISSION_CATEGORIES as i, type PermissionCategory as j, type AuthInitOptions as k, type KeyAlgorithmType as l, mainAuthRouter as m, type InvitationStatus as n, type UserStatus as o, type SocialProvider as p, type AuthContext as q, checkAccountExistsService as r, registerService as s, loginService as t, logoutService as u, changePasswordService as v, type CheckAccountExistsParams as w, type RegisterParams as x, type LoginParams as y, type LogoutParams as z };
940
+ export { oauthCallbackService as $, type AuthSession as A, type LogoutParams as B, type CheckAccountExistsResult as C, type ChangePasswordParams as D, sendVerificationCodeService as E, verifyCodeService as F, type SendVerificationCodeParams as G, type VerifyCodeParams as H, type IssueOneTimeTokenResult as I, type VerifyCodeResult as J, KEY_ALGORITHM as K, type LoginResult as L, registerPublicKeyService as M, rotateKeyService as N, type OAuthStartResult as O, type PermissionConfig as P, revokeKeyService as Q, type RoleConfig as R, type SendVerificationCodeResult as S, type RegisterPublicKeyParams as T, type UserProfile as U, type VerificationTargetType as V, type RotateKeyParams as W, type RevokeKeyParams as X, issueOneTimeTokenService as Y, verifyOneTimeTokenService as Z, oauthStartService as _, type RegisterResult as a, buildOAuthErrorUrl as a0, isOAuthProviderEnabled as a1, getEnabledOAuthProviders as a2, getGoogleAccessToken as a3, type OAuthStartParams as a4, type OAuthCallbackParams as a5, type OAuthCallbackResult as a6, authenticate as a7, optionalAuth as a8, EmailSchema as a9, PhoneSchema as aa, PasswordSchema as ab, TargetTypeSchema as ac, VerificationPurposeSchema as ad, type RotateKeyResult as b, type ProfileInfo as c, INVITATION_STATUSES as d, USER_STATUSES as e, SOCIAL_PROVIDERS as f, type VerificationPurpose as g, VERIFICATION_TARGET_TYPES as h, VERIFICATION_PURPOSES as i, PERMISSION_CATEGORIES as j, type PermissionCategory as k, type AuthInitOptions as l, mainAuthRouter as m, type KeyAlgorithmType as n, type InvitationStatus as o, type UserStatus as p, type SocialProvider as q, type AuthContext as r, checkAccountExistsService as s, registerService as t, loginService as u, logoutService as v, changePasswordService as w, type CheckAccountExistsParams as x, type RegisterParams as y, type LoginParams as z };